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

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

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

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

Ответ 1

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

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

Это прекрасно отображает решение.

Ответ 2

using System.Globalization;

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

Ответ 3

Хотя 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-less (я делаю), вы можете добавить строку "s", чтобы значительно расширить количество измененных изменений формата.

Ответ 4

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

Ответ 5

Кажется важным точно соответствовать формату строки 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);

true

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

Ответ 6

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

Ответ 7

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