2010-08-24 2 views
80

Я нашел, как превратить DateTime в формат ISO 8601, но ничего о том, как сделать обратное в C#.Как создать .NET DateTime из ISO 8601 формат

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

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

+1

Возможный дубликат [Преобразование строки в Date в .NET] (http://stackoverflow.com/questions/2188585/convert-string-to-date-in-net) – abatishchev

+2

Искать сначала пожалуйста. Это 100-й вопрос по этому вопросу в этом месяце – abatishchev

+8

@abatishchev no Это не дубликат этого вопроса. Возможно, сначала вы должны прочитать вопрос перед ответом. – Aidin

ответ

87

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

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

Печатается решение идеально.

+0

@Mamta Dalal: попробуйте 'DateTime.ParseExact (« 2010-08-20T15: 00: 00Z »,« s », CultureInfo.InvariantCulture);« Это не удается. –

+3

Редактированное решение 'DateTime d2 = DateTime.Parse (« 2010-08-20T15: 00: 00Z », null, DateTimeStyles.RoundtripKind);' похоже, работает хорошо. – j3ko

+0

@ j3ko Благодарю вас –

0

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

21
using System.Globalization; 

DateTime d; 
DateTime.TryParseExact(
    "2010-08-20T15:00:00", 
    "s", 
    CultureInfo.InvariantCulture, 
    DateTimeStyles.AssumeUniversal, out d); 
+1

производит False и d ~~> «1/1/0001 12:00:00 AM» в LinqPad :( –

+0

@Reb: «2010-08-20T15: 00: 00» и «s», если нет «Z», в конце – abatishchev

+0

исправлено :) Z отображается во всех моих образцах (которые происходят из разных GPS-устройств и файлов GPX) –

12

Вот один, который работает лучше для меня (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 
+0

Отличное решение, спасибо. – kamui

+0

В настоящее время, используя это, чтобы проверить в моих модульных тестах, что все строки, которые я ожидаю быть датами, имеют формат Iso8601. Благодаря! – anthv123

3

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

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

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

Есть несколько дополнительных 000-х там в течение миллисекунд, и может быть больше.

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

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

В VS2010 окне Immediate:

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

правда

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

2

Это отлично работает в 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")); 
17

Хотя 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», чтобы значительно расширить число крытых изменений формата.

+2

Я бы добавил '' yyyyMMdd'' в массив 'formats' для точности, уменьшенной до дней, так как это иногда бывает, когда RFC 5545 RRULE будет полагаться на DTSTART, чтобы обеспечить время. –

+0

Использование 'K' позволяет вам вручную сгруппировать ваши рукописные записи в часовых поясах. У меня более обширный вариант на http://stackoverflow.com/a/31246449/400547, но это, если что-то слишком обширное (принимает материал, который соответствует ISO 8601, но не используется в более общих профилях), но он показывает, как «K 'может уменьшить размер на треть. –

Смежные вопросы