Дано:
DateTime.UtcNow
Как получить строку, представляющую одно и то же значение в формате, совместимом с ISO 8601?
Обратите внимание, что ISO 8601 определяет ряд похожих форматов. Конкретный формат, который я ищу:
yyyy-MM-ddTHH:mm:ssZ





DateTime.UtcNow.ToString("s")
Возвращает что-то вроде 2008-04-10T06: 30: 00
UtcNow, очевидно, возвращает время универсальное глобальное время, поэтому нет никакого вреда в:
string.Concat(DateTime.UtcNow.ToString("s"), "Z")
Привычка, есть ли разница?
@KoenZomers: Я не думаю, что это правильно. Я думаю, что a + b компилируется с тем же промежуточным кодом, что и string.Concat(a, b) (конечно, при условии, что a и b являются строками), поэтому нет никакой разницы в производительности или потреблении памяти.
Да, Марк прав. Коэн, вы только что попали в ловушку абсурдно преждевременной микрооптимизации, даже если вы правы.
Почему бы вместо этого не использовать o для получения часового пояса? Конечно, это будет включать микросекунды, такие как 2014-04-09T09:38:29.7562176-04:00 (от DateTime.Now) или 2014-04-09T13:38:29.7562176Z (UtcNow). Сравнить параметры формата
@MarkByers, это неверно. @Noldorin, это не преждевременно, если это вызывается в цикле, который выполняется тысячи раз, или если это веб-приложение, запускающее этот код при каждом запросе. На мой взгляд, string.Concat следует использовать всегда для интенсивной конкатенации строк (под интенсивным я подразумеваю, что используется регулярно приложением, а не пользователем - опять же, я думаю о сети). @KoenZomers string.Format на самом деле самый медленный способ сделать это. См. Контрольные показатели в середине страницы: dotnetperls.com/string-concat
@ greg84: Вы не совсем правы. Посмотрите эту публикацию архитектора Microsoft Рико Мариани: blogs.msdn.com/b/ricom/archive/2003/12/15/43628.aspx - он говорит, что a + b компилируется в concat + есть дополнительная информация о правильном использовании StringBuilder.
Судя по ссылкам, упомянутым выше, при объединении двух строк нет никакой разницы. + просто короче в исходном коде. string.Concat дает эффект производительности при объединении по крайней мере 3 строк за один шаг.
На самом деле string.Concat вредит вам, потому что компилятор оптимизирует +, но не String.Concat. stackoverflow.com/a/8864900/86973
@PRMan: Это верно только в данном случае, потому что они являются строковыми литералами (например, они могут быть преобразованы в константы). Он распознает это, поэтому просто предварительно объединяет их во время компиляции в одну строку. Если бы у вас был var someString = "World"; var concatd = "Привет" + someString + "!"; тогда он НЕ будет оптимизировать его под «Hello World!». Если someString было константой, то, вероятно, так и будет.
Это сложнее, чем "o". Кроме того, разница с использованием string.Concat() заключается в том, что на экране отображается больше кода, когда он не нужен (т. Е. Ваши строки не поступают из IEnumerable или динамически созданного массива), что делает его менее читаемым.
эээ ... кто сказал, что он должен быть быстрым, а не читаемым человеком? Оптимизирован ли он для времени, потраченного на написание String.Concat (.... '- что бесценно: D: D
Вы знаете, что ответ старый, если в примере есть дата, которая произошла более 10 лет назад. Эй, он все еще работает безупречно!
@BrentRittenhouse, на самом деле "literal" + variable + "literal2" в точности совпадает с string.Concat. И если у вас достаточно знаков +, он фактически оптимизирует его в массив строк, который затем отправляется в string.Concat (string []).
Note to readers: Several commenters have pointed out some problems in this answer (related particularly to the first suggestion). Refer to the comments section for more information.
DateTime.UtcNow.ToString("yyyy-MM-ddTHH\:mm\:ss.fffffffzzz");
Это дает вам дату, аналогичную 2008-09-22T13: 57: 31.2311892-04: 00.
Другой способ:
DateTime.UtcNow.ToString("o");
что дает вам 2008-09-22T14: 01: 54.9571247Z
Чтобы получить указанный формат, вы можете использовать:
DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ")
Параметры форматирования даты и времени
В наши дни это (попытка визуализировать время в формате UTC со смещением, что не имеет большого смысла) вызывает исключение. Итак, я согласен с другими, что формат «s» с инвариантной культурой, вероятно, более правильный. К вашему сведению, сообщение formatexception: «DateTime в формате UTC преобразуется в текст в формате, который подходит только для местного времени. Это может произойти при вызове DateTime.ToString с использованием спецификатора формата 'z', который будет включать смещение местного часового пояса. на выходе ".
Я живу в Австралии, и мне пришлось использовать ToString("yyyy-MM-ddTHH:mm:ssK"), чтобы это работало (с плагином jquery timeago, который я использовал).
Если вы работаете со службами REST Windows Live, вам также понадобится ToString ("yyyy-MM-ddTHH: mm: ssK", System.Globalization.CultureInfo.InvariantCulture).
Если вы хотите включить смещение часового пояса, сделайте следующее: dt.ToString("s") + dt.ToString("zzz") // 2013-12-05T07: 19: 04-08: 00
Grrrr. Время - такая сложная тема. Спасибо, мистер Флеминг!
Косая черта (\ :) вызывает проблемы со строкой ... вставьте символ @, чтобы вместо этого использовать строковый литерал.
Интересно, что ссылка на «Параметры форматирования даты и времени» не включает «o» в свой список средств форматирования строк. Странный.
@core: это один из стандартных форматов, который отличается от связанных пользовательских форматов: msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx
Пожалуйста, сначала укажите самый простой вариант "o" с наименьшим количеством кода, наименее вероятно испорченным.
Думаю, стоит отметить, что при форматировании с DateTimeOffset формат ToString("o") отличается от DateTime. dateTime.ToString("o") => как указано выше, оканчиваясь на Z. dateTimeOffset.ToString("o") => дата, заканчивающаяся на +00:00. Итак, начиная с DateTimeOffset, вы хотите использовать dateTimeOffset.UtcDateTime.ToString("o");.
Первый вариант, который вы даете, на самом деле очень неправильный: вы добавляете смещение часового пояса ко времени UTC. Единственный способ, которым этот вариант может быть правильным, - использовать DateTime.Now вместо DateTime.UtcNow. Второй вариант с форматом "o" правильный и менее подвержен ошибкам.
Нет ничего плохого в том, чтобы добавить Z или +0: 00 ко времени UTC. Если единственная информация о времени - это строка, это законный способ сообщить, что это время в формате UTC.
+00:00 в качестве смещения для представления UTC действителен в соответствии с Спецификации ISO8601 (раздел 3.4.2): "представляет знак плюса [+], если в сочетании со следующим элементом необходимо представить положительное значение или нуль. Поэтому просто используйте формат o. как с DateTime, так и с DateTimeOffset.
ISO 8601 является григорианским, поэтому первая часть вашего ответа, ToString("yyyy-MM-ddTHH\:mm\:ss.fffffffzzz"), даст неверные результаты в негрегорианских культурах, таких как new CultureInfo("ar-SA"). Демо-скрипт здесь: dotnetfiddle.net/RNvaPr. Вам необходимо передать дополнительный параметр CultureInfo.InvariantCulture. Поскольку это лучший ответ, я хотел бы внести исправление.
DateTime.UtcNow.ToString("s", System.Globalization.CultureInfo.InvariantCulture) должен дать вам то, что вы ищете, поскольку спецификатор формата «s» описывается как сортируемый шаблон даты / времени; соответствует ISO 8601.
Обновлено: Чтобы получить дополнительный Z в конце, как того требует OP, используйте "o" вместо "s".
Я считаю, что это правильный ответ. Нет смысла явно определять yyyy-MM-etc, если Microsoft уже внедрила ISO 8601. Ответ Иана тоже был правильным, но вы всегда должны указывать InvariantCulture (или любой другой CultureInfo) по нескольким причинам (т.е. никогда не предполагайте, что .NET должен просто предположить). Вы также можете использовать: DateTime.UtcNow.ToString(CultureInfo.InvariantCulture.DateTimeFormat.SortableDateTimePattern);. Однако, поскольку все они исключают часовой пояс и т. д., У вас может не быть другого выбора, кроме как использовать явное средство форматирования, то есть "yyyy-MM-ddTHH:mm:ss.fffZ".
Хотя он соответствует, он не учитывает часовой пояс Z, который выглядит следующим образом: DateTime.UtcNow.ToString(c, CultureInfo.InvariantCulture)) => 2012-06-26T11:55:36, и нет разрешения в миллисекундах, которое было бы очень хорошо, поскольку компьютеры делают изрядное количество тиков в секунду.
С o вы получаете 2012-06-26T11:55:36.1007668Z, что означает 36.1007668 секунд, поэтому вы получаете разрешение до 1/10^7 секунды. Из ISO8601: 2004 If a decimal fraction is included, lower order time elements (if any) shall be omitted and the decimal fraction shall be divided from the integer part by the decimal sign [...] the comma (,) or full stop (.)
@ stimpy77 Указание CultureInfo для "s" не имеет смысла, потому что: «O» (или «o»), «R» (или «r»), «s» и «u». Эти строки соответствуют строкам настраиваемого формата, определенным инвариантным языком и региональными параметрами. Они создают строковые представления значений даты и времени, которые должны быть идентичными в разных культурах ».
@binki Вы уверены, что s инвариантен? Из вашей ссылки (перейти к форматированию строк) говорится, что s использует SortableDateTimePattern, в котором говорится, что «свойство определяет формат культурно-специфический строк даты, которые ... снабжены строкой стандартного формата« s »». То же для R. С другой стороны, U и O инвариантны.
@drzaus, DateTimeFormatInfo - это класс sealed. В перечислении типы форматных строкSortableDateTimePattern не указан как «Свойства, которые определяют строки результатов с учетом языка и региональных параметров». Вместо этого, ниже в таблице, "s" задокументирован «для определения строки результата, соответствующей стандарту ISO 8601». ISO 8601 не учитывает локализацию AFAIK. Просто надеюсь, что библиотека классов действительно делает то, что написано в документации ;-).
@binki - сейчас очень запуталась. Согласно документация, которую я связал ранее для SortableDateTimePattern, он должен быть специфичным для культуры. ОДНАКО, кажется, что это противоречит его собственным примерам (поскольку все они выглядят одинаково); попробуйте DateTime.Now.ToString("s", new CultureInfo(myCulture)).
@drzaus, меня это тоже смущает. Но я думаю, это просто означает, что вы можете использовать любой объект CultureInfo, даже то, что не является InvariantCulture, и получить те же результаты. То есть ISO8601 дает вам одну и ту же строку независимо от культуры. Тогда вам не придется возиться с InvariantCulture (?). Но это просто кажется неуместным в классе, где большинство других членов должен различаются в зависимости от культуры.
"o" превосходит.
Да, "s" сбивает с толку. Определение против реализации? «Свойство SortableDateTimePattern определяет формат строк даты, зависящий от языка и региональных параметров.», но он реализован как определенный стандарт, который не меняется в зависимости от языка и региональных параметров: «Строка формата, возвращаемая свойством SortableDateTimePattern, отражает определенный стандарт (ISO 8601) [...] Следовательно, это всегда одинаково, независимо от культуры». Цитаты взяты из документации msdn.microsoft.com/en-us/library/….
Выберете ли вы "o" или "s", зависит от вашего использования, и стоит прочитать документацию по обоим (ссылки здесь). Но короче говоря, "o" полезен там, где вы хотите сохранить свойство Kind при синтаксическом анализе результата в обратном порядке (отсюда и «двусторонний переход»). Это полезно, например, при сохранении значения в базе данных для последующего извлечения.
Чтобы преобразовать DateTime.UtcNow в строковое представление гггг-ММ-ддТЧЧ: мм: ссZ, вы можете использовать метод ToString () структуры DateTime с настраиваемой строкой форматирования. При использовании строк настраиваемого формата с DateTime важно помнить, что вам нужно избегать разделителей, используя одинарные кавычки.
Следующее вернет нужное строковое представление:
DateTime.UtcNow.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'", DateTimeFormatInfo.InvariantInfo)
Я бы просто использовал XmlConvert:
XmlConvert.ToString(DateTime.UtcNow, XmlDateTimeSerializationMode.RoundtripKind);
Он автоматически сохранит часовой пояс.
Я пошел дальше и добавил метод расширения. общедоступный статический класс DateTimeExtensions {общедоступная статическая строка ToIsoFormat (это DateTime dateTime) {return XmlConvert.ToString (dateTime, XmlDateTimeSerializationMode.RoundtripKind); }}
The
"s"standard format specifier represents a custom date and time format string that is defined by the DateTimeFormatInfo.SortableDateTimePattern property. The pattern reflects a defined standard (ISO 8601), and the property is read-only. Therefore, it is always the same, regardless of the culture used or the format provider supplied. The custom format string is"yyyy'-'MM'-'dd'T'HH':'mm':'ss".When this standard format specifier is used, the formatting or parsing operation always uses the invariant culture.
- от MSDN
Так можно ли использовать .ToString("s")?
Я так считаю. - Если ваше требование соответствует исходному вопросу, то есть ... Но обратите внимание на предупреждение Саймона Уилсона ниже
Использовать:
private void TimeFormats()
{
DateTime localTime = DateTime.Now;
DateTime utcTime = DateTime.UtcNow;
DateTimeOffset localTimeAndOffset = new DateTimeOffset(localTime, TimeZoneInfo.Local.GetUtcOffset(localTime));
//UTC
string strUtcTime_o = utcTime.ToString("o");
string strUtcTime_s = utcTime.ToString("s");
string strUtcTime_custom = utcTime.ToString("yyyy-MM-ddTHH:mm:ssK");
//Local
string strLocalTimeAndOffset_o = localTimeAndOffset.ToString("o");
string strLocalTimeAndOffset_s = localTimeAndOffset.ToString("s");
string strLocalTimeAndOffset_custom = utcTime.ToString("yyyy-MM-ddTHH:mm:ssK");
//Output
Response.Write("<br/>UTC<br/>");
Response.Write("strUtcTime_o: " + strUtcTime_o + "<br/>");
Response.Write("strUtcTime_s: " + strUtcTime_s + "<br/>");
Response.Write("strUtcTime_custom: " + strUtcTime_custom + "<br/>");
Response.Write("<br/>Local Time<br/>");
Response.Write("strLocalTimeAndOffset_o: " + strLocalTimeAndOffset_o + "<br/>");
Response.Write("strLocalTimeAndOffset_s: " + strLocalTimeAndOffset_s + "<br/>");
Response.Write("strLocalTimeAndOffset_custom: " + strLocalTimeAndOffset_custom + "<br/>");
}
UTC
strUtcTime_o: 2012-09-17T22:02:51.4021600Z
strUtcTime_s: 2012-09-17T22:02:51
strUtcTime_custom: 2012-09-17T22:02:51Z
Local Time
strLocalTimeAndOffset_o: 2012-09-17T15:02:51.4021600-07:00
strLocalTimeAndOffset_s: 2012-09-17T15:02:51
strLocalTimeAndOffset_custom: 2012-09-17T22:02:51Z
похоже, вы стали жертвой копирования по местному обычаю ;-) string strLocalTimeAndOffset_custom = localTimeAndOffset.ToString("yyyy-MM-ddTHH:mm:ssK"); приведет к: strLocalTimeAndOffset_custom: 2012-09-17T22:02:51-07:00
Если вы разрабатываете под SharePoint 2010 или выше, вы можете использовать
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
...
string strISODate = SPUtility.CreateISO8601DateTimeFromSystemDateTime(DateTime.Now)
SharePoint, когда вашего .Net недостаточно Java.
Использование SharePoint для этого похоже на то, как если бы вы принесли кадку с желе, мокрую коробку спичек и двух шимпанзе, идущих по трапеции, на перестрелку.
Надеюсь, даже в SharePoint вы сможете использовать BCL .ToString("o") или, лучше, $"My complicated string {dt:o}".
System.DateTime.UtcNow.ToString("o")
=>
val it : string = "2013-10-13T13:03:50.2950037Z"
Согласен, это единственный способ быть абсолютно уверенным в том, что у вас есть однозначная дата / время в любом часовом поясе.
Вы можете получить "Z" (ISO 8601универсальное глобальное время) с помощью следующего кода:
Dim tmpDate As DateTime = New DateTime(Now.Ticks, DateTimeKind.Utc)
Dim res as String = tmpDate.toString("o") '2009-06-15T13:45:30.0000000Z
Вот почему:
ISO 8601 имеет несколько разных форматов:
DateTimeKind.Local
2009-06-15T13:45:30.0000000-07:00
DateTimeKind.Utc
2009-06-15T13:45:30.0000000Z
DateTimeKind.Unspecified
2009-06-15T13:45:30.0000000
.NET предоставляет нам перечисление с этими параметрами:
'2009-06-15T13:45:30.0000000-07:00
Dim strTmp1 As String = New DateTime(Now.Ticks, DateTimeKind.Local).ToString("o")
'2009-06-15T13:45:30.0000000Z
Dim strTmp2 As String = New DateTime(Now.Ticks, DateTimeKind.Utc).ToString("o")
'2009-06-15T13:45:30.0000000
Dim strTmp3 As String = New DateTime(Now.Ticks, DateTimeKind.Unspecified).ToString("o")
Примечание: Если вы примените «служебную программу наблюдения» Visual Studio 2008 к части toString ("о"), вы можете получить другие результаты, я не знаю, является ли это ошибкой, но в этом случае у вас будут лучшие результаты при использовании строковой переменной при отладке.
Источник: Строки стандартных форматов даты и времени (MSDN)
В большинстве этих ответов указаны миллисекунды / микросекунды, что явно не поддерживается ISO 8601. Правильный ответ:
System.DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ssK");
// or
System.DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssK");
Рекомендации:
Прочтите вашу собственную ссылку на Википедию в разделе «Times». В нем упоминаются «десятичные дроби», что означает, что ISO 8601 поддерживает как миллисекунды, так и микросекунды (но взаимодействующие стороны могут ограничивать количество принимаемых десятичных знаков).
У вас есть несколько вариантов, в том числе спецификатор формата «Туда и обратно (« O »)».
var date1 = new DateTime(2008, 3, 1, 7, 0, 0);
Console.WriteLine(date1.ToString("O"));
Console.WriteLine(date1.ToString("s", System.Globalization.CultureInfo.InvariantCulture));
Выход
2008-03-01T07:00:00.0000000
2008-03-01T07:00:00
Однако DateTime + TimeZone может вызвать другие проблемы, как описано в сообщении блога DateTime и DateTimeOffset в .NET: передовой опыт и распространенные ошибки:
DateTime has countless traps in it that are designed to give your code bugs:
1.- DateTime values with DateTimeKind.Unspecified are bad news.
2.- DateTime doesn't care about UTC/Local when doing comparisons.
3.- DateTime values are not aware of standard format strings.
4.- Parsing a string that has a UTC marker with DateTime does not guarantee a UTC time.
Стандарт ISO8601 используется в Strava, например. Однако используйте: StartTime.ToString ("yyyy-MM-ddTHH: mm: ssZ") вместо ToString ("o"), который добавляет миллисекунды и т. д.
Для меня «yyyy-MM-dd-THH: mm: ssZ» буквально выводило «Z» в конце моей строки вместо маркера часового пояса, который не делал то, что я хотел. ToString ("o") действительно сделал то, что мне нужно, намного проще и короче.
@BlairConnolly Вы были правы. Спецификатор формата "z" должно было быть в нижнем регистре. Как указано здесь, заглавная буква «Z» действительна только тогда, когда ваша дата фактически находится в UTC.
Интересно, что пользовательский формат «yyyy-MM-ddTHH: mm: ssK» (без ms) - самый быстрый способ форматирования.
Также интересно, что формат "S" медленный на Classic и быстрый на Core ...
Конечно числа очень близки, разница между некоторыми строками незначительна (тесты с суффиксом _Verify такие же, как и без этого суффикса, демонстрирует повторяемость результатов)
BenchmarkDotNet=v0.10.5, OS=Windows 10.0.14393
Processor=Intel Core i5-2500K CPU 3.30GHz (Sandy Bridge), ProcessorCount=4
Frequency=3233539 Hz, Resolution=309.2587 ns, Timer=TSC
[Host] : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1637.0
Clr : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1637.0
Core : .NET Core 4.6.25009.03, 64bit RyuJIT
Method | Job | Runtime | Mean | Error | StdDev | Median | Min | Max | Rank | Gen 0 | Allocated |
--------------------- |----- |-------- |-----------:|----------:|----------:|-----------:|-----------:|-----------:|-----:|-------:|----------:|
CustomDev1 | Clr | Clr | 1,089.0 ns | 22.179 ns | 20.746 ns | 1,079.9 ns | 1,068.9 ns | 1,133.2 ns | 8 | 0.1086 | 424 B |
CustomDev2 | Clr | Clr | 1,032.3 ns | 19.897 ns | 21.289 ns | 1,024.7 ns | 1,000.3 ns | 1,072.0 ns | 7 | 0.1165 | 424 B |
CustomDev2WithMS | Clr | Clr | 1,168.2 ns | 16.543 ns | 15.474 ns | 1,168.5 ns | 1,149.3 ns | 1,189.2 ns | 10 | 0.1625 | 592 B |
FormatO | Clr | Clr | 1,563.7 ns | 31.244 ns | 54.721 ns | 1,532.5 ns | 1,497.8 ns | 1,703.5 ns | 14 | 0.2897 | 976 B |
FormatS | Clr | Clr | 1,243.5 ns | 24.615 ns | 31.130 ns | 1,229.3 ns | 1,200.6 ns | 1,324.2 ns | 13 | 0.2865 | 984 B |
FormatS_Verify | Clr | Clr | 1,217.6 ns | 11.486 ns | 10.744 ns | 1,216.2 ns | 1,205.5 ns | 1,244.3 ns | 12 | 0.2885 | 984 B |
CustomFormatK | Clr | Clr | 912.2 ns | 17.915 ns | 18.398 ns | 916.6 ns | 878.3 ns | 934.1 ns | 4 | 0.0629 | 240 B |
CustomFormatK_Verify | Clr | Clr | 894.0 ns | 3.877 ns | 3.626 ns | 893.8 ns | 885.1 ns | 900.0 ns | 3 | 0.0636 | 240 B |
CustomDev1 | Core | Core | 989.1 ns | 12.550 ns | 11.739 ns | 983.8 ns | 976.8 ns | 1,015.5 ns | 6 | 0.1101 | 423 B |
CustomDev2 | Core | Core | 964.3 ns | 18.826 ns | 23.809 ns | 954.1 ns | 935.5 ns | 1,015.6 ns | 5 | 0.1267 | 423 B |
CustomDev2WithMS | Core | Core | 1,136.0 ns | 21.914 ns | 27.714 ns | 1,138.1 ns | 1,099.9 ns | 1,200.2 ns | 9 | 0.1752 | 590 B |
FormatO | Core | Core | 1,201.5 ns | 16.262 ns | 15.211 ns | 1,202.3 ns | 1,178.2 ns | 1,225.5 ns | 11 | 0.0656 | 271 B |
FormatS | Core | Core | 993.5 ns | 19.272 ns | 24.372 ns | 999.4 ns | 954.2 ns | 1,029.5 ns | 6 | 0.0633 | 279 B |
FormatS_Verify | Core | Core | 1,003.1 ns | 17.577 ns | 16.442 ns | 1,009.2 ns | 976.1 ns | 1,024.3 ns | 6 | 0.0674 | 279 B |
CustomFormatK | Core | Core | 878.2 ns | 17.017 ns | 20.898 ns | 877.7 ns | 851.4 ns | 928.1 ns | 2 | 0.0555 | 215 B |
CustomFormatK_Verify | Core | Core | 863.6 ns | 3.968 ns | 3.712 ns | 863.0 ns | 858.6 ns | 870.8 ns | 1 | 0.0550 | 215 B |
Код:
public class BenchmarkDateTimeFormat
{
public static DateTime dateTime = DateTime.Now;
[Benchmark]
public string CustomDev1()
{
var d = dateTime.ToUniversalTime();
var sb = new StringBuilder(20);
sb.Append(d.Year).Append("-");
if (d.Month <= 9)
sb.Append("0");
sb.Append(d.Month).Append("-");
if (d.Day <= 9)
sb.Append("0");
sb.Append(d.Day).Append("T");
if (d.Hour <= 9)
sb.Append("0");
sb.Append(d.Hour).Append(":");
if (d.Minute <= 9)
sb.Append("0");
sb.Append(d.Minute).Append(":");
if (d.Second <= 9)
sb.Append("0");
sb.Append(d.Second).Append("Z");
var text = sb.ToString();
return text;
}
[Benchmark]
public string CustomDev2()
{
var u = dateTime.ToUniversalTime();
var sb = new StringBuilder(20);
var y = u.Year;
var d = u.Day;
var M = u.Month;
var h = u.Hour;
var m = u.Minute;
var s = u.Second;
sb.Append(y).Append("-");
if (M <= 9)
sb.Append("0");
sb.Append(M).Append("-");
if (d <= 9)
sb.Append("0");
sb.Append(d).Append("T");
if (h <= 9)
sb.Append("0");
sb.Append(h).Append(":");
if (m <= 9)
sb.Append("0");
sb.Append(m).Append(":");
if (s <= 9)
sb.Append("0");
sb.Append(s).Append("Z");
var text = sb.ToString();
return text;
}
[Benchmark]
public string CustomDev2WithMS()
{
var u = dateTime.ToUniversalTime();
var sb = new StringBuilder(23);
var y = u.Year;
var d = u.Day;
var M = u.Month;
var h = u.Hour;
var m = u.Minute;
var s = u.Second;
var ms = u.Millisecond;
sb.Append(y).Append("-");
if (M <= 9)
sb.Append("0");
sb.Append(M).Append("-");
if (d <= 9)
sb.Append("0");
sb.Append(d).Append("T");
if (h <= 9)
sb.Append("0");
sb.Append(h).Append(":");
if (m <= 9)
sb.Append("0");
sb.Append(m).Append(":");
if (s <= 9)
sb.Append("0");
sb.Append(s).Append(".");
sb.Append(ms).Append("Z");
var text = sb.ToString();
return text;
}
[Benchmark]
public string FormatO()
{
var text = dateTime.ToUniversalTime().ToString("o");
return text;
}
[Benchmark]
public string FormatS()
{
var text = string.Concat(dateTime.ToUniversalTime().ToString("s"),"Z");
return text;
}
[Benchmark]
public string FormatS_Verify()
{
var text = string.Concat(dateTime.ToUniversalTime().ToString("s"), "Z");
return text;
}
[Benchmark]
public string CustomFormatK()
{
var text = dateTime.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssK");
return text;
}
[Benchmark]
public string CustomFormatK_Verify()
{
var text = dateTime.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssK");
return text;
}
}
https://github.com/dotnet/BenchmarkDotNet использовался
Чтобы отформатировать как 2018-06-22T13: 04: 16, который может быть передан в URI API, используйте:
public static string FormatDateTime(DateTime dateTime)
{
return dateTime.ToString("s", System.Globalization.CultureInfo.InvariantCulture);
}
Я думаю, что эта строка даты ISO не зависит от культуры по определению.
DateTime.Now.ToString("yyyy-MM-dd'T'HH:mm:ss zzz");
DateTime.Now.ToString("O");
ПРИМЕЧАНИЕ. В зависимости от того, какое преобразование вы выполняете на своей стороне, вы будете использовать первую строку (наиболее подходящую) или вторую.
Убедитесь, что формат применяется только по местному времени, поскольку «zzz» - это информация о часовом поясе для преобразования UTC.

Я не так уверен в #ChrisHynes, поскольку он спрашивает о предложении, которое я сделал относительно первой строки кода, но если вы правы и в этом случае, ответ будет «ReSharper».
Удивлен, что этого никто не предложил:
System.DateTime.UtcNow.ToString("u").Replace(' ','T')
# Using PowerShell Core to demo
# Lowercase "u" format
[System.DateTime]::UtcNow.ToString("u")
> 2020-02-06 01:00:32Z
# Lowercase "u" format with replacement
[System.DateTime]::UtcNow.ToString("u").Replace(' ','T')
> 2020-02-06T01:00:32Z
UniversalSortableDateTimePattern дает вам почти все, что вы хотите (что больше является представлением RFC 3339).
Добавлен: Я решил использовать тесты, которые были в ответе https://stackoverflow.com/a/43793679/653058, чтобы сравнить, как это работает.
tl: dr; это дорогое удовольствие, но на моем старом паршивом ноутбуке чуть больше половины миллисекунды :-)
Выполнение:
[Benchmark]
public string ReplaceU()
{
var text = dateTime.ToUniversalTime().ToString("u").Replace(' ', 'T');
return text;
}
Полученные результаты:
// * Summary *
BenchmarkDotNet=v0.11.5, OS=Windows 10.0.19002
Intel Xeon CPU E3-1245 v3 3.40GHz, 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=3.0.100
[Host] : .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64bit RyuJIT
DefaultJob : .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64bit RyuJIT
| Method | Mean | Error | StdDev |
|--------------------- |---------:|----------:|----------:|
| CustomDev1 | 562.4 ns | 11.135 ns | 10.936 ns |
| CustomDev2 | 525.3 ns | 3.322 ns | 3.107 ns |
| CustomDev2WithMS | 609.9 ns | 9.427 ns | 8.356 ns |
| FormatO | 356.6 ns | 6.008 ns | 5.620 ns |
| FormatS | 589.3 ns | 7.012 ns | 6.216 ns |
| FormatS_Verify | 599.8 ns | 12.054 ns | 11.275 ns |
| CustomFormatK | 549.3 ns | 4.911 ns | 4.594 ns |
| CustomFormatK_Verify | 539.9 ns | 2.917 ns | 2.436 ns |
| ReplaceU | 615.5 ns | 12.313 ns | 11.517 ns |
// * Hints *
Outliers
BenchmarkDateTimeFormat.CustomDev2WithMS: Default -> 1 outlier was removed (668.16 ns)
BenchmarkDateTimeFormat.FormatS: Default -> 1 outlier was removed (621.28 ns)
BenchmarkDateTimeFormat.CustomFormatK: Default -> 1 outlier was detected (542.55 ns)
BenchmarkDateTimeFormat.CustomFormatK_Verify: Default -> 2 outliers were removed (557.07 ns, 560.95 ns)
// * Legends *
Mean : Arithmetic mean of all measurements
Error : Half of 99.9% confidence interval
StdDev : Standard deviation of all measurements
1 ns : 1 Nanosecond (0.000000001 sec)
// ***** BenchmarkRunner: End *****
Принятый ответ «o» действительно работает, но дает досадную точность (черт возьми .XXXXXXX секунд), тогда как я предпочитаю это, поскольку он останавливается на секундах.
Также в этом документе утверждается, что «u» - это ISO 8601, но что с пробелом вместо T? собери это вместе microsoft
@jhocking en.wikipedia.org/wiki/ISO_8601#cite_note-30 ISO 8601 относительно разрешителен, если вы его прочитаете ...
Используя Newtonsoft.Json, вы можете делать
JsonConvert.SerializeObject(DateTime.UtcNow)
Пример: https://dotnetfiddle.net/O2xFSl
лучший ответ здесь.
Как упоминалось в другом ответе, у DateTime есть проблемы с дизайном.
Я предлагаю использовать NodaTime для управления значениями даты / времени:
Итак, для создания и форматирования ZonedDateTime вы можете использовать следующий фрагмент кода:
var instant1 = Instant.FromUtc(2020, 06, 29, 10, 15, 22);
var utcZonedDateTime = new ZonedDateTime(instant1, DateTimeZone.Utc);
utcZonedDateTime.ToString("yyyy-MM-ddTHH:mm:ss'Z'", CultureInfo.InvariantCulture);
// 2020-06-29T10:15:22Z
var instant2 = Instant.FromDateTimeUtc(new DateTime(2020, 06, 29, 10, 15, 22, DateTimeKind.Utc));
var amsterdamZonedDateTime = new ZonedDateTime(instant2, DateTimeZoneProviders.Tzdb["Europe/Amsterdam"]);
amsterdamZonedDateTime.ToString("yyyy-MM-ddTHH:mm:ss'Z'", CultureInfo.InvariantCulture);
// 2020-06-29T12:15:22Z
Для меня код NodaTime выглядит довольно многословным. Но типы действительно полезны. Они помогают правильно обрабатывать значения даты и времени.
To use
NodaTimewithNewtonsoft.Jsonyou need to add reference toNodaTime.Serialization.JsonNetNuGet package and configure JSON options.
services
.AddMvc()
.AddJsonOptions(options =>
{
var settings=options.SerializerSettings;
settings.DateParseHandling = DateParseHandling.None;
settings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
});
Просто из интереса: почему string.Concat (), а не '+'?