Учитывая объект DateTime, как мне получить дату ISO 8601 в строковом формате?

Дано:

DateTime.UtcNow

Как получить строку, представляющую одно и то же значение в формате, совместимом с ISO 8601?

Обратите внимание, что ISO 8601 определяет ряд похожих форматов. Конкретный формат, который я ищу:

yyyy-MM-ddTHH:mm:ssZ
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
869
0
613 628
18

Ответы 18

DateTime.UtcNow.ToString("s")

Возвращает что-то вроде 2008-04-10T06: 30: 00

UtcNow, очевидно, возвращает время универсальное глобальное время, поэтому нет никакого вреда в:

string.Concat(DateTime.UtcNow.ToString("s"), "Z")

Просто из интереса: почему string.Concat (), а не '+'?

Daniel Fortunov 22.09.2008 18:53

Привычка, есть ли разница?

Iain 23.09.2008 17:26

@KoenZomers: Я не думаю, что это правильно. Я думаю, что a + b компилируется с тем же промежуточным кодом, что и string.Concat(a, b) (конечно, при условии, что a и b являются строками), поэтому нет никакой разницы в производительности или потреблении памяти.

Mark Byers 25.01.2012 17:54

Да, Марк прав. Коэн, вы только что попали в ловушку абсурдно преждевременной микрооптимизации, даже если вы правы.

Noldorin 14.02.2012 18:03

Почему бы вместо этого не использовать o для получения часового пояса? Конечно, это будет включать микросекунды, такие как 2014-04-09T09:38:29.7562176-04:00 (от DateTime.Now) или 2014-04-09T13:38:29.7562176Z (UtcNow). Сравнить параметры формата

drzaus 09.04.2014 17:50

@MarkByers, это неверно. @Noldorin, это не преждевременно, если это вызывается в цикле, который выполняется тысячи раз, или если это веб-приложение, запускающее этот код при каждом запросе. На мой взгляд, string.Concat следует использовать всегда для интенсивной конкатенации строк (под интенсивным я подразумеваю, что используется регулярно приложением, а не пользователем - опять же, я думаю о сети). @KoenZomers string.Format на самом деле самый медленный способ сделать это. См. Контрольные показатели в середине страницы: dotnetperls.com/string-concat

greg84 23.05.2014 01:50

@ greg84: Вы не совсем правы. Посмотрите эту публикацию архитектора Microsoft Рико Мариани: blogs.msdn.com/b/ricom/archive/2003/12/15/43628.aspx - он говорит, что a + b компилируется в concat + есть дополнительная информация о правильном использовании StringBuilder.

mrówa 17.09.2014 19:55

Судя по ссылкам, упомянутым выше, при объединении двух строк нет никакой разницы. + просто короче в исходном коде. string.Concat дает эффект производительности при объединении по крайней мере 3 строк за один шаг.

Stéphane Gourichon 23.09.2016 18:58

На самом деле string.Concat вредит вам, потому что компилятор оптимизирует +, но не String.Concat. stackoverflow.com/a/8864900/86973

PRMan 19.01.2017 22:33

@PRMan: Это верно только в данном случае, потому что они являются строковыми литералами (например, они могут быть преобразованы в константы). Он распознает это, поэтому просто предварительно объединяет их во время компиляции в одну строку. Если бы у вас был var someString = "World"; var concatd = "Привет" + someString + "!"; тогда он НЕ будет оптимизировать его под «Hello World!». Если someString было константой, то, вероятно, так и будет.

Brent Rittenhouse 16.12.2017 00:35

Это сложнее, чем "o". Кроме того, разница с использованием string.Concat() заключается в том, что на экране отображается больше кода, когда он не нужен (т. Е. Ваши строки не поступают из IEnumerable или динамически созданного массива), что делает его менее читаемым.

binki 15.02.2018 20:19

эээ ... кто сказал, что он должен быть быстрым, а не читаемым человеком? Оптимизирован ли он для времени, потраченного на написание String.Concat (.... '- что бесценно: D: D

d.popov 18.07.2018 18:35

Вы знаете, что ответ старый, если в примере есть дата, которая произошла более 10 лет назад. Эй, он все еще работает безупречно!

Gaspa79 02.08.2018 23:39

@BrentRittenhouse, на самом деле "literal" + variable + "literal2" в точности совпадает с string.Concat. И если у вас достаточно знаков +, он фактически оптимизирует его в массив строк, который затем отправляется в string.Concat (string []).

PRMan 21.11.2018 02:18

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', который будет включать смещение местного часового пояса. на выходе ".

Tom Lianza 02.11.2010 07:59

Я живу в Австралии, и мне пришлось использовать ToString("yyyy-MM-ddTHH:mm:ssK"), чтобы это работало (с плагином jquery timeago, который я использовал).

GONeale 03.08.2011 09:50

Если вы работаете со службами REST Windows Live, вам также понадобится ToString ("yyyy-MM-ddTHH: mm: ssK", System.Globalization.CultureInfo.InvariantCulture).

Adarsha 18.10.2012 17:04

Если вы хотите включить смещение часового пояса, сделайте следующее: dt.ToString("s") + dt.ToString("zzz") // 2013-12-05T07: 19: 04-08: 00

alekop 06.12.2013 07:18

Grrrr. Время - такая сложная тема. Спасибо, мистер Флеминг!

Jowen 05.05.2014 14:06

Косая черта (\ :) вызывает проблемы со строкой ... вставьте символ @, чтобы вместо этого использовать строковый литерал.

Gigi 29.08.2014 16:50

Интересно, что ссылка на «Параметры форматирования даты и времени» не включает «o» в свой список средств форматирования строк. Странный.

core 27.10.2015 23:52

@core: это один из стандартных форматов, который отличается от связанных пользовательских форматов: msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx

Wayne 29.10.2015 20:59

Пожалуйста, сначала укажите самый простой вариант "o" с наименьшим количеством кода, наименее вероятно испорченным.

binki 15.02.2018 20:20

Думаю, стоит отметить, что при форматировании с DateTimeOffset формат ToString("o") отличается от DateTime. dateTime.ToString("o") => как указано выше, оканчиваясь на Z. dateTimeOffset.ToString("o") => дата, заканчивающаяся на +00:00. Итак, начиная с DateTimeOffset, вы хотите использовать dateTimeOffset.UtcDateTime.ToString("o");.

Matt Scully 29.08.2018 18:02

Первый вариант, который вы даете, на самом деле очень неправильный: вы добавляете смещение часового пояса ко времени UTC. Единственный способ, которым этот вариант может быть правильным, - использовать DateTime.Now вместо DateTime.UtcNow. Второй вариант с форматом "o" правильный и менее подвержен ошибкам.

Phil 10.01.2019 13:41

Нет ничего плохого в том, чтобы добавить Z или +0: 00 ко времени UTC. Если единственная информация о времени - это строка, это законный способ сообщить, что это время в формате UTC.

qwlice 12.06.2019 11:53

+00:00 в качестве смещения для представления UTC действителен в соответствии с Спецификации ISO8601 (раздел 3.4.2): "представляет знак плюса [+], если в сочетании со следующим элементом необходимо представить положительное значение или нуль. Поэтому просто используйте формат o. как с DateTime, так и с DateTimeOffset.

Saeb Amini 04.12.2019 04:12

ISO 8601 является григорианским, поэтому первая часть вашего ответа, ToString("yyyy-MM-ddTHH\:mm\:ss.fffffffzzz"), даст неверные результаты в негрегорианских культурах, таких как new CultureInfo("ar-SA"). Демо-скрипт здесь: dotnetfiddle.net/RNvaPr. Вам необходимо передать дополнительный параметр CultureInfo.InvariantCulture. Поскольку это лучший ответ, я хотел бы внести исправление.

dbc 08.03.2021 17:35

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.DateTi‌​meFormat.SortableDat‌​eTimePattern);. Однако, поскольку все они исключают часовой пояс и т. д., У вас может не быть другого выбора, кроме как использовать явное средство форматирования, то есть "yyyy-MM-ddTHH:mm:ss.fffZ".

Jon Davis 21.08.2010 00:07

Хотя он соответствует, он не учитывает часовой пояс Z, который выглядит следующим образом: DateTime.UtcNow.ToString(c, CultureInfo.InvariantCulture)) => 2012-06-26T11:55:36, и нет разрешения в миллисекундах, которое было бы очень хорошо, поскольку компьютеры делают изрядное количество тиков в секунду.

Henrik 26.06.2012 16:05

С 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 (.)

Henrik 26.06.2012 16:11

@binki Вы уверены, что s инвариантен? Из вашей ссылки (перейти к форматированию строк) говорится, что s использует SortableDateTimePattern, в котором говорится, что «свойство определяет формат культурно-специфический строк даты, которые ... снабжены строкой стандартного формата« s »». То же для R. С другой стороны, U и O инвариантны.

drzaus 09.04.2014 17:45

@drzaus, DateTimeFormatInfo - это класс sealed. В перечислении типы форматных строкSortableDateTimePattern не указан как «Свойства, которые определяют строки результатов с учетом языка и региональных параметров». Вместо этого, ниже в таблице, "s" задокументирован «для определения строки результата, соответствующей стандарту ISO 8601». ISO 8601 не учитывает локализацию AFAIK. Просто надеюсь, что библиотека классов действительно делает то, что написано в документации ;-).

binki 10.04.2014 17:30

@binki - сейчас очень запуталась. Согласно документация, которую я связал ранее для SortableDateTimePattern, он должен быть специфичным для культуры. ОДНАКО, кажется, что это противоречит его собственным примерам (поскольку все они выглядят одинаково); попробуйте DateTime.Now.ToString("s", new CultureInfo(myCulture)).

drzaus 11.04.2014 01:02

@drzaus, меня это тоже смущает. Но я думаю, это просто означает, что вы можете использовать любой объект CultureInfo, даже то, что не является InvariantCulture, и получить те же результаты. То есть ISO8601 дает вам одну и ту же строку независимо от культуры. Тогда вам не придется возиться с InvariantCulture (?). Но это просто кажется неуместным в классе, где большинство других членов должен различаются в зависимости от культуры.

binki 11.04.2014 01:09

"o" превосходит.

binki 15.02.2018 20:26

Да, "s" сбивает с толку. Определение против реализации? «Свойство SortableDateTimePattern определяет формат строк даты, зависящий от языка и региональных параметров.», но он реализован как определенный стандарт, который не меняется в зависимости от языка и региональных параметров: «Строка формата, возвращаемая свойством SortableDateTimePattern, отражает определенный стандарт (ISO 8601) [...] Следовательно, это всегда одинаково, независимо от культуры». Цитаты взяты из документации msdn.microsoft.com/en-us/library/….

Timo 14.05.2018 18:27

Выберете ли вы "o" или "s", зависит от вашего использования, и стоит прочитать документацию по обоим (ссылки здесь). Но короче говоря, "o" полезен там, где вы хотите сохранить свойство Kind при синтаксическом анализе результата в обратном порядке (отсюда и «двусторонний переход»). Это полезно, например, при сохранении значения в базе данных для последующего извлечения.

Neo 28.08.2019 02:30

Чтобы преобразовать 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); }}

muruge 27.03.2012 01:32

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")?

AhmetB - Google 24.02.2014 01:59

Я так считаю. - Если ваше требование соответствует исходному вопросу, то есть ... Но обратите внимание на предупреждение Саймона Уилсона ниже

Amal 24.02.2014 11:21

Использовать:

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

Holly 29.04.2015 12:42

Если вы разрабатываете под SharePoint 2010 или выше, вы можете использовать

using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
...
string strISODate = SPUtility.CreateISO8601DateTimeFromSystemDateTime(DateTime.Now)

SharePoint, когда вашего .Net недостаточно Java.

Henrik 27.02.2015 18:30

Использование SharePoint для этого похоже на то, как если бы вы принесли кадку с желе, мокрую коробку спичек и двух шимпанзе, идущих по трапеции, на перестрелку.

nathanchere 29.06.2015 11:27

Надеюсь, даже в SharePoint вы сможете использовать BCL .ToString("o") или, лучше, $"My complicated string {dt:o}".

binki 15.02.2018 20:34

System.DateTime.UtcNow.ToString("o")

=>

val it : string = "2013-10-13T13:03:50.2950037Z"

Согласен, это единственный способ быть абсолютно уверенным в том, что у вас есть однозначная дата / время в любом часовом поясе.

Matt Wilko 01.09.2015 18:54

Вы можете получить "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 поддерживает как миллисекунды, так и микросекунды (но взаимодействующие стороны могут ограничивать количество принимаемых десятичных знаков).

Søren Boisen 06.05.2015 15:56

У вас есть несколько вариантов, в том числе спецификатор формата «Туда и обратно (« 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"), который добавляет миллисекунды и т. д.

peterincumbria 13.03.2016 18:42

Для меня «yyyy-MM-dd-THH: mm: ssZ» буквально выводило «Z» в конце моей строки вместо маркера часового пояса, который не делал то, что я хотел. ToString ("o") действительно сделал то, что мне нужно, намного проще и короче.

Blair Connolly 19.01.2017 00:45

@BlairConnolly Вы были правы. Спецификатор формата "z" должно было быть в нижнем регистре. Как указано здесь, заглавная буква «Z» действительна только тогда, когда ваша дата фактически находится в UTC.

jpaugh 24.06.2020 18:02

Интересно, что пользовательский формат «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 не зависит от культуры по определению.

Jonas 25.02.2019 15:28

DateTime.Now.ToString("yyyy-MM-dd'T'HH:mm:ss zzz");

DateTime.Now.ToString("O");

ПРИМЕЧАНИЕ. В зависимости от того, какое преобразование вы выполняете на своей стороне, вы будете использовать первую строку (наиболее подходящую) или вторую.

Убедитесь, что формат применяется только по местному времени, поскольку «zzz» - это информация о часовом поясе для преобразования UTC.

image

Я не так уверен в #ChrisHynes, поскольку он спрашивает о предложении, которое я сделал относительно первой строки кода, но если вы правы и в этом случае, ответ будет «ReSharper».

PSM 18.11.2018 06:11

Удивлен, что этого никто не предложил:

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 секунд), тогда как я предпочитаю это, поскольку он останавливается на секундах.

jhocking 06.06.2019 04:39

Также в этом документе утверждается, что «u» - это ISO 8601, но что с пробелом вместо T? собери это вместе microsoft

jhocking 06.06.2019 04:45

@jhocking en.wikipedia.org/wiki/ISO_8601#cite_note-30 ISO 8601 относительно разрешителен, если вы его прочитаете ...

rburte 07.06.2019 00:27

Используя Newtonsoft.Json, вы можете делать

JsonConvert.SerializeObject(DateTime.UtcNow)

Пример: https://dotnetfiddle.net/O2xFSl

лучший ответ здесь.

The Integrator 06.04.2020 21:18

Как упоминалось в другом ответе, у DateTime есть проблемы с дизайном.

NodaTime

Я предлагаю использовать 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 выглядит довольно многословным. Но типы действительно полезны. Они помогают правильно обрабатывать значения даты и времени.

Newtonsoft.Json

To use NodaTime with Newtonsoft.Json you need to add reference to NodaTime.Serialization.JsonNet NuGet package and configure JSON options.

services
    .AddMvc()
    .AddJsonOptions(options =>
    {
        var settings=options.SerializerSettings;
        settings.DateParseHandling = DateParseHandling.None;
        settings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
    });

Другие вопросы по теме