为什么DateTime.Parse无法解析UTC日期


74

为什么它不能解析此:

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

3
当您new Date().toUTCString()在Javascript中使用IE9时,IE9仍会错误地添加“ UTC”
Chris S

对于2009年发表此帖子的任何人,此问题的答案是momentjs.com
Liam,

Answers:


89

由于“ UTC”不是有效的时区指示符,因此无法解析该字符串。

UTC时间是通过在时间字符串的末尾添加“ Z”来表示的,因此您的解析代码应如下所示:

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

摘自ISO 8601上Wikipedia文章

如果时间以世界标准时间(UTC)为准,请在时间之后直接添加“ Z”,且不带空格。“ Z”是UTC偏移为零的区域标记。因此,“ 09:30 UTC”表示为“ 09:30Z”或“ 0930Z”。“ 14:45:15 UTC”将是“ 14:45:15Z”或“ 144515Z”。

UTC时间也称为“祖鲁语”时间,因为“祖鲁语”是北约语音字母中的“ Z”。


1
在我的示例中,日期字符串来自互联网浏览器
Dve

@Dave:当您说它来自IE时,是否意味着您从网页中提取了它?您可能需要编写自己的替代的日期时间解析器提取UTC并替换它以Z
西蒙P史蒂文斯

在针对FF进行测试之后,我忘记了在回发到服务器之日调用toUTCString()方法。FF发送GMT,而IE发送UTC。所以我不能怪IE ...这次!
Dve

70
至于其他的答案指出,UTC日期字符串以Z标志将确实被成功解析,但它也将转换为本地时间,即返回DateTimeKindLocal和调整时间戳。要始终获取UTC DateTime,可以使用 DateTime.Parse("2008-01-01 00:00:00Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal)@crokusek建议的或 DateTimeOffset.Parse("2008-01-01 00:00:00Z").UtcDateTime@ruffin建议的之一。
Sergii Volchkov '16

在元标记中http-equiv="last-modified",格式为2013-10-23 @ 17:23:00 UTC,可以吗?
PreguntonCojoneroCabrón

66

假设您的日期时间使用格式“ o”,那么您就拥有“ 2016-07-24T18:47:36Z”,有一种非常简单的方法可以处理此问题。

致电DateTime.Parse("2016-07-24T18:47:36Z").ToUniversalTime()

打电话时会发生什么,您DateTime.Parse("2016-07-24T18:47:36Z")会获得DateTime当地时区的设置。因此它将其转换为当地时间。

将其ToUniversalTime()更改为UTCDateTime并将其转换回UTC时间。


假设这是将Zulu发送到网络api时看到的,但您看到的是当地时间。认为有什么点击了,谢谢
安德鲁

26

只需使用:

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/

希望对您有所帮助。


18

您需要指定格式:

DateTime date = DateTime.ParseExact(
    "Tue, 1 Jan 2008 00:00:00 UTC", 
    "ddd, d MMM yyyy HH:mm:ss UTC", 
    CultureInfo.InvariantCulture);

2
很好的建议,但是如果提供的日期字符串末尾不包含UTC,这将失败。假设您传递的结尾是+01的日期字符串,则将导致FormatException。我想取决于他想做什么。
西蒙·史蒂文斯

17

或在调用中使用AdjustToUniversal DateTimeStyle

DateTime.ParseExact(String, String[], IFormatProvider, DateTimeStyles)

5
这实际上有效。我使用此代码,并从UTC字符串中获取了正确的UTC日期时间:DateTime.TryParseExact(“ 2012-01-30T00:28:00Z”,“ yyyy-MM-ddTHH:mm:ssZ”,CultureInfo.InvariantCulture,DateTimeStyles.AdjustToUniversal,out timeValue));
Roboblob 2012年

21
此方法也适用,UTC进出,无需格式,无需Z:DateTime.Parse(“ 2013/8/3 1:02:41 AM”,CultureInfo.InvariantCulture,DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal);
crokusek

我正在处理类似于Roboblob的UTC时间字符串,并使用类似于Roboblob指定的代码来维护值的UTC值:DateTime.ParseExact(utcTimeStringINeededToParse,“ yyyy-MM-ddTHH:mm:ss.0000000Z”, System.Globalization.CultureInfo.InvariantCulture,System.Globalization.DateTimeStyles.AdjustToUniversal)
StackOverflowUser 2016年

10

要正确解析问题中给出的字符串而不更改它,请使用以下命令:

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参数用于指定给定的字符串是协调的通用时间字符串。


根据文档,“Kind返回DateTime值的属性是” DateTimeKind.Local。ParseExact正确地将其解析为UTC,但是在将其返回之前将其转换为本地时间。DateTimeStyles.RoundtripKind如果希望返回的值原样返回为UTC,则使用此函数。
Daniel Schilling

7

这不是有效的格式,但是“星期二,2008年1月1日00:00:00 GMT”是有效格式。

文档说像这样:

包含时区信息并符合ISO 8601的字符串。例如,以下两个字符串中的第一个指定协调世界时(UTC);第二个指定的时间是比UTC早七小时的时区:

2008-11-01T19:35:00.0000000Z

包含GMT指示符并符合RFC 1123时间格式的字符串。例如:

星期六,2008年11月1日19:35:00 GMT

一个字符串,其中包括日期和时间以及时区偏移信息。例如:

2009/03/01 05:42:00 -5:00


在此格式类似的日期字符串中用“ GMT”简单替换“ UTC”非常有用,谢谢。
James Wilkins 2015年

1
但请注意,这会返回一个DateTime带有KindLocal我。如果您想确保在解析过程中不会脱离UTC旅行车,则解决方法似乎是使用DateTimeOffset.Parse(然后使用x.UtcDateTime)。
鲁芬,2016年

1

只需将“ UTC”替换为“ GMT”即可-简单而且不会破坏正确格式的日期:

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

1

我整理了一个实用程序方法,该方法使用了此处显示的所有技巧以及其他一些技巧:

    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”(单引号)。这是最佳做法,因为区域设置会干扰字符的解释,例如“-”,导致将其解释为“ /”或“。”。或您的区域设置表示为date-components-separator的任何内容。我还包括了第二种实用程序方法,该方法演示了如何解析从Web客户端提供给rest-api后端的最常见的日期字符串格式。请享用。


-4

不知道为什么,但是您可以在try / catch中包装DateTime.ToUniversalTime并在更多代码中获得相同的结果。

祝好运。


ToUniversalTime永远不会引发异常
引发
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.