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

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

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

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

7 ответов

Решение

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

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

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

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

using System.Globalization;

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

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

Это прекрасно работает в 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"));

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

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

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

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

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

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

В VS2010 Immediate Window:

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

правда

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

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

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