Почему нельзя DateTime.Parse разобрать дату UTC - PullRequest
56 голосов
/ 18 ноября 2009

Почему не может разобрать это:

DateTime.Parse("Tue, 1 Jan 2008 00:00:00 UTC")

Ответы [ 10 ]

68 голосов
/ 18 ноября 2009

Невозможно проанализировать эту строку, поскольку «UTC» не является допустимым указателем часового пояса.

Время UTC обозначается добавлением «Z» в конец строки времени, поэтому ваш код синтаксического анализа должен выглядеть следующим образом:

DateTime.Parse("Tue, 1 Jan 2008 00:00:00Z");

Из статьи Википедии о ISO 8601

Если время указано в UTC, добавьте «Z» сразу после времени без пространство. «Z» - обозначение зоны для нулевое смещение UTC. "09:30 UTC" поэтому представлен как "09: 30Z" или "0930Z". "14:45:15 UTC" будет «14: 45: 15Z» или «144515Z».

Время UTC также известно как время "Зулу", поскольку «Зулу» является фонетическим алфавитное слово для «Z».

41 голосов
/ 24 июля 2016

Если вы используете формат «o» для даты и времени, поэтому у вас есть «2016-07-24T18: 47: 36Z», существует очень простой способ справиться с этим.

Звоните DateTime.Parse("2016-07-24T18:47:36Z").ToUniversalTime().

Что происходит, когда вы звоните DateTime.Parse("2016-07-24T18:47:36Z"), если вы получаете DateTime, установленный на местный часовой пояс. Так что он конвертирует его в местное время.

ToUniversalTime() изменяет его на UTC DateTime и преобразует обратно во время UTC.

16 голосов
/ 18 ноября 2009

Вам необходимо указать формат:

DateTime date = DateTime.ParseExact(
    "Tue, 1 Jan 2008 00:00:00 UTC", 
    "ddd, d MMM yyyy HH:mm:ss UTC", 
    CultureInfo.InvariantCulture);
12 голосов
/ 07 марта 2017

Просто используйте это:

var myDateUtc = DateTime.SpecifyKind(DateTime.Parse("Tue, 1 Jan 2008 00:00:00"), DateTimeKind.Utc);

if (myDateUtc.Kind == DateTimeKind.Utc)
{
     Console.WriteLine("Yes. I am UTC!");
}

Вы можете проверить этот код с помощью онлайн-компилятора c #:

http://rextester.com/

Надеюсь, это поможет.

12 голосов
/ 18 ноября 2009

или используйте AdjustToUniversal DateTimeStyle при вызове

DateTime.ParseExact(String, String[], IFormatProvider, DateTimeStyles)
9 голосов
/ 29 мая 2014

Чтобы правильно проанализировать приведенную в вопросе строку, не меняя ее, используйте следующее:

using System.Globalization;

string dateString = "Tue, 1 Jan 2008 00:00:00 UTC";
DateTime parsedDate = DateTime.ParseExact(dateString, "ddd, d MMM yyyy hh:mm:ss UTC", CultureInfo.CurrentCulture, DateTimeStyles.AssumeUniversal);

Эта реализация использует строку, чтобы указать точный формат анализируемой строки даты. Параметр DateTimeStyles используется для указания того, что данная строка является согласованной универсальной временной строкой.

7 голосов
/ 18 ноября 2009

Это недопустимый формат, однако «Вт, 1 января 2008 00:00:00 GMT» имеет значение.

Документация гласит:

Строка, которая включает информацию о часовом поясе и соответствует ISO 8601. Например, первая из следующих двух строк обозначает Всемирное координированное время (UTC); вторая обозначает время в часовом поясе на семь часов раньше UTC:

2008-11-01T19: 35: 00.0000000Z

Строка, которая включает обозначение GMT ​​и соответствует формату времени RFC 1123. Например:

Суббота, 01 ноября 2008 19:35:00 по Гринвичу

Строка, которая включает дату и время вместе с информацией о смещении часового пояса. Например:

03.01.2009 05:42:00 -5: 00

0 голосов
/ 24 октября 2018

Я собрал вспомогательный метод, который использует все советы, показанные здесь, а также некоторые другие:

    static private readonly string[] MostCommonDateStringFormatsFromWeb = {
        "yyyy'-'MM'-'dd'T'hh:mm:ssZ",  //     momentjs aka universal sortable with 'T'     2008-04-10T06:30:00Z          this is default format employed by moment().utc().format()
        "yyyy'-'MM'-'dd'T'hh:mm:ss.fffZ", //  syncfusion                                   2008-04-10T06:30:00.000Z      retarded string format for dates that syncfusion libs churn out when invoked by ejgrid for odata filtering and so on
        "O", //                               iso8601                                      2008-04-10T06:30:00.0000000
        "s", //                               sortable                                     2008-04-10T06:30:00
        "u"  //                               universal sortable                           2008-04-10 06:30:00Z
    };

    static public bool TryParseWebDateStringExactToUTC(
        out DateTime date,
        string input,
        string[] formats = null,
        DateTimeStyles? styles = null,
        IFormatProvider formatProvider = null
    )
    {
        formats = formats ?? MostCommonDateStringFormatsFromWeb;
        return TryParseDateStringExactToUTC(out date, input, formats, styles, formatProvider);
    }

    static public bool TryParseDateStringExactToUTC(
        out DateTime date,
        string input,
        string[] formats = null,
        DateTimeStyles? styles = null,
        IFormatProvider formatProvider = null
    )
    {
        styles = styles ?? DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal; //0 utc
        formatProvider = formatProvider ?? CultureInfo.InvariantCulture;

        var verdict = DateTime.TryParseExact(input, result: out date, style: styles.Value, formats: formats, provider: formatProvider);
        if (verdict && date.Kind == DateTimeKind.Local) //1
        {
            date = date.ToUniversalTime();
        }

        return verdict;

        //0 employing adjusttouniversal is vital in order for the resulting date to be in utc when the 'Z' flag is employed at the end of the input string
        //  like for instance in   2008-04-10T06:30.000Z
        //1 local should never happen with the default settings but it can happen when settings get overriden   we want to forcibly return utc though
    }

Обратите внимание на использование «-» и «T» (в одинарных кавычках). Это делается в соответствии с передовой практикой, поскольку региональные настройки мешают интерпретации символов, таких как «-», что приводит к его интерпретации как «/» или «». или что бы ваши региональные настройки не обозначали как разделитель даты-компонентов. Я также включил второй служебный метод, который показывает случаи, как анализировать наиболее часто встречающиеся форматы строк даты, передаваемые в бэкэнды rest-api от веб-клиентов. Наслаждайтесь.

0 голосов
/ 16 марта 2017

Просто замените «UTC» на «GMT» - просто и не нарушает правильно отформатированные даты:

DateTime.Parse("Tue, 1 Jan 2008 00:00:00 UTC".Replace("UTC", "GMT"))
0 голосов
/ 18 ноября 2009

Не знаю почему, но вы можете обернуть DateTime.ToUniversalTime в try / catch и добиться того же результата в большем количестве кода.

Удачи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...