Как создать .NET DateTime из формата ISO 8601

Я нашел, как преобразовать DateTime в формат ISO 8601, но не знаю, как это сделать. обратное в C #.

У меня есть 2010-08-20T15:00:00Z, и я хочу превратить его в DateTime объект.

Я мог бы сам разделить части струны, но это кажется большим трудом для чего-то, что уже является международным стандартом.


person Ripter    schedule 24.08.2010    source источник
comment
возможный дубликат Преобразовать строку в дату в .NET   -  person abatishchev    schedule 24.08.2010
comment
@Aidin: 24 августа 2010 г., в 12:02   -  person abatishchev    schedule 21.11.2015
comment
@Aidin: и да, это дубликат. Единственная разница в формате. В остальном то же самое.   -  person abatishchev    schedule 21.11.2015
comment
@abatishchev, а потому не дубликат. Ответ в дубликате не обрабатывает 8601.   -  person Spiralis    schedule 03.11.2016
comment
Да это не дубликат. Этот вопрос относится к разбору формата ISO 8601.   -  person Jose    schedule 13.02.2020


Ответы (7)


Это решение использует перечисление DateTimeStyles, а также работает с Z .

DateTime d2 = DateTime.Parse("2010-08-20T15:00:00Z", null, System.Globalization.DateTimeStyles.RoundtripKind);

Это отлично печатает решение.

person Mamta D    schedule 24.08.2010
comment
@Mamta Dalal: попробуй DateTime.ParseExact("2010-08-20T15:00:00Z", "s", CultureInfo.InvariantCulture); Не получается. - person Roatin Marth; 06.12.2011
comment
Отредактированное решение DateTime d2= DateTime.Parse("2010-08-20T15:00:00Z", null, DateTimeStyles.RoundtripKind);, похоже, работает нормально. - person j3ko; 19.12.2012
comment
Любой желающий уточнить это DateTimeStyles.RoundtripKind? описание MSDN пусто. - person Steve Parish; 28.10.2015
comment
Это также применимо к структуре System.DateTimeOffset. - person Vladimir Svyatski; 28.10.2015
comment
похоже, этот вопрос был отредактирован, чтобы отразить лучший ответ, но поскольку @MamtaD перезаписал исходный ответ, комментарии становятся очень вводящими в заблуждение. Вначале я не был уверен, что ответ правильный из-за комментариев вверху, но потом понял, что неправильный ответ был позже заменен правильным. - person Aidin; 21.11.2015
comment
Это вызывает исключение System.Format для строки "06-03-2016T06:42:44.252Z". Как я могу преобразовать эту строку в дату и время? - person user95227; 10.06.2016
comment
@ user95227 вопрос на этой странице относится к формату ISO8601, тогда как ваша строка не в этом формате. Следовательно, правильный ответ на первоначально заданный вопрос может не быть правильным ответом на ваш, поскольку контекст отличается. - person Mamta D; 13.06.2016
comment
Протестировано с идентификатором 2017-10-31T06: 03: 05 + 01: 00. Тоже работает .. Большое спасибо! - person Oswald; 31.10.2017
comment
У меня не работает с дробными цифрами. 2018-06-19T14:56:14.123Z обрабатывается как местное время, а не UTC. Я использую CultureInfo.InvariantCulture вместо null. - person Erik Hart; 19.06.2018
comment
Для получения дополнительной информации о DateTimeStyles.RoundTripKind см. stackoverflow.com/q/39572395/2014893 - person Robert K. Bell; 06.07.2018
comment
Я использую DateTime.Parse (2010-08-20T15: 00: 00Z, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind), поскольку ISO 8601 не может быть затронут культурой. Для DateTimeOffSet должно быть то же самое, правда? DateTimeOffset.Parse (значение, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind) - person João Antunes; 17.04.2019

Хотя MSDN утверждает, что форматы «s» и «o» отражают стандарт, похоже, они могут анализировать только его ограниченное подмножество. Особенно проблема, если строка содержит указание часового пояса. (Ни для базовых форматов ISO8601, ни для форматов с пониженной точностью - однако это не совсем ваш случай.) Вот почему я использую строки настраиваемого формата, когда дело доходит до синтаксического анализа ISO8601. В настоящее время я предпочитаю следующий фрагмент:

static readonly string[] formats = { 
    // Basic formats
    "yyyyMMddTHHmmsszzz",
    "yyyyMMddTHHmmsszz",
    "yyyyMMddTHHmmssZ",
    // Extended formats
    "yyyy-MM-ddTHH:mm:sszzz",
    "yyyy-MM-ddTHH:mm:sszz",
    "yyyy-MM-ddTHH:mm:ssZ",
    // All of the above with reduced accuracy
    "yyyyMMddTHHmmzzz",
    "yyyyMMddTHHmmzz",
    "yyyyMMddTHHmmZ",
    "yyyy-MM-ddTHH:mmzzz",
    "yyyy-MM-ddTHH:mmzz",
    "yyyy-MM-ddTHH:mmZ",
    // Accuracy reduced to hours
    "yyyyMMddTHHzzz",
    "yyyyMMddTHHzz",
    "yyyyMMddTHHZ",
    "yyyy-MM-ddTHHzzz",
    "yyyy-MM-ddTHHzz",
    "yyyy-MM-ddTHHZ"
    };

public static DateTime ParseISO8601String ( string str )
{
    return DateTime.ParseExact ( str, formats, 
        CultureInfo.InvariantCulture, DateTimeStyles.None );
}

Если вы не возражаете против синтаксического анализа строк без TZ (я так и поступаю), вы можете добавить строку «s», чтобы значительно увеличить количество изменяемых форматов.

person Alexey Biryukov    schedule 19.07.2013
comment
Я бы добавил "yyyyMMdd" в массив formats для уменьшения точности до дней, поскольку это иногда бывает, когда RFC 5545 RRULE будет полагаться на DTSTART для предоставления времени. - person Kyle Falconer; 01.08.2014
comment
Использование K позволяет объединить различные обработки часовых поясов. У меня более обширный вариант на stackoverflow.com/a/31246449/400547, но он, если что-то слишком обширный (принимает вещи это действительный ISO 8601, но не используется в более распространенных профилях), но он показывает, как K может уменьшить размер на треть. - person Jon Hanna; 06.07.2015

Вот вариант, который мне больше подходит (версия LINQPad):

DateTime d;
DateTime.TryParseExact(
    "2010-08-20T15:00:00Z",
    @"yyyy-MM-dd\THH:mm:ss\Z",
    CultureInfo.InvariantCulture,
    DateTimeStyles.AssumeUniversal, 
    out d);
d.ToString()

производит

true
8/20/2010 8:00:00 AM
person Reb.Cabin    schedule 13.05.2011
comment
В настоящее время я использую это для проверки в своих модульных тестах того, что все строки, которые, как я ожидаю, будут датами, имеют формат Iso8601. Спасибо! - person anthv123; 27.01.2015
comment
Почему это возвращает метку времени не в формате UTC ?! Довольно серьезное нарушение принципа наименьшего удивления, поскольку инвариантная культура с AssumeUniversal не должна этого делать, потому что летнее время сильно различается по всему миру, поэтому возвращение в ваш местный преобладающий часовой пояс может привести к ошибкам, если вы начнете запускать код на сервере с разные настройки! - person Elaskanator; 19.07.2019

Кажется важным точно соответствовать формату строки ISO для работы TryParseExact. Я думаю, что Exact is Exact, и этот ответ очевиден для большинства, но в любом случае ...

В моем случае ответ Reb.Cabin не работает, так как у меня немного другой ввод в соответствии с моим «значением» ниже.

Значение: 2012-08-10T14:00:00.000Z

Там несколько лишних 000 за миллисекунды, а может быть и больше.

Однако, если я добавлю несколько .fff в формат, как показано ниже, все в порядке.

Строка формата: @"yyyy-MM-dd\THH:mm:ss.fff\Z"

В непосредственном окне VS2010:

DateTime.TryParseExact(value,@"yyyy-MM-dd\THH:mm:ss.fff\Z", CultureInfo.InvariantCulture,DateTimeStyles.AssumeUniversal, out d);

правда

Возможно, вам также придется использовать DateTimeStyles.AssumeLocal, в зависимости от того, в какой зоне ваше время ...

person Rob Von Nesselrode    schedule 14.08.2012
comment
У меня это сработало, но мне также пришлось изменить AssumeUniversal на AdjustToUniversal. - person Augusto Barreto; 09.04.2019

Это отлично работает в LINQPad4:

Console.WriteLine(DateTime.Parse("2010-08-20T15:00:00Z"));
Console.WriteLine(DateTime.Parse("2010-08-20T15:00:00"));
Console.WriteLine(DateTime.Parse("2010-08-20 15:00:00"));
person Zar Shardan    schedule 18.12.2012

DateTime.ParseExact(...) позволяет вам сообщить синтаксическому анализатору, что представляет каждый символ.

person Jerod Houghtelling    schedule 24.08.2010

person    schedule
comment
выдает False и d ~~ ›1/1/0001 12:00:00 AM в LinqPad :( - person Reb.Cabin; 13.05.2011
comment
@Reb: 2010-08-20T15: 00: 00 и s, если на конце нет Z - person abatishchev; 13.05.2011
comment
исправлено :) Z появляется во всех моих образцах (которые происходят из различных устройств GPS и файлов GPX) - person Reb.Cabin; 14.05.2011
comment
обнаружил в другой ссылке ISO 8601, что Z обозначает зону - как в часовом поясе. - person Reb.Cabin; 17.05.2011
comment
Z на самом деле означает зулусское время или всемирное координированное время. en.wikipedia.org/wiki/ISO_8601#UTC - person Peter Stephens; 22.06.2011
comment
@ Reb.Cabin - Какие изменения вы внесли, чтобы исправить это? - person Shailesh; 15.05.2020