分享

DateTime.TryParse和Z字母的大小写

 码农9527 2021-05-12

   最近,我受命以从后端到前端的特定格式提供日期,我注意到我发现自己的行为有些奇怪。

private static void OutputDateInfo(string value){
    Console.WriteLine($"Input: {value}");    if (DateTime.TryParse(value, out DateTime dateTimeValue))
    {
        Console.WriteLine($"Setialized to universal format 
                {dateTimeValue.ToString("yyyy-MM-dd'T'HH:mm:ssZ")}");
    }
    Console.WriteLine();
}//somewhere in mainOutputDateInfo("2021-04-15T21:01:00.0000000Z");
OutputDateInfo("2021-04-15T21:01:00.0000000");1234567891011121314复制代码类型:[cpp]

web

    产生输出:

Input: 2021-04-15T21:01:00.0000000Z
Setialized to universal format 2021-04-16T00:01:00Z

Input: 2021-04-15T21:01:00.0000000Setialized to universal format 2021-04-15T21:01:00Z12345复制代码类型:[cpp]

    因此,就像我在UTC+3时区的Kyiv一样,它看起来像Z字母强制ToString方法,将日期转换为本地时间。

    正如文档所述:

    引用:

    如果s不包含任何时区信息,则result包含一个DateTime值,该方法的返回值时其Kind属性为DateTimeKind.Unspecified。如果要解析的字符串包含时区信息,则方法返回时,结果包含DateTime值,其Kind属性为DateTimeKind.Local。

    这DateTimeKind使得ToString投日期为本地时区?让我们记录更多属性以查看是否存在这种情况:

private static void OutputDateInfo(string value){
    Console.WriteLine($"Input: {value}");    if (DateTime.TryParse(value, out DateTime dateTimeValue))
    {
        Console.WriteLine($"Setialized to universal format 
                         {dateTimeValue.ToString("yyyy-MM-dd'T'HHssZ")}");
        Console.WriteLine($"Setialized to default format {dateTimeValue}");
        Console.WriteLine($"Setialized with conversion to universal time 
                         {dateTimeValue.ToUniversalTime()}");
        Console.WriteLine($"Kind: {dateTimeValue.Kind}");
    }
    Console.WriteLine();
}1234567891011121314复制代码类型:[csharp]

    现在我们在控制台中看到:

Input: 2021-04-15T21:01:00.0000000Z
Setialized to universal format 2021-04-16T00:01:00Z
Setialized to default format 16.04.2021 0:01:00Setialized with conversion to universal time 15.04.2021 21:01:00Kind: Local

Input: 2021-04-15T21:01:00.0000000Setialized to universal format 2021-04-15T21:01:00Z
Setialized to default format 15.04.2021 21:01:00Setialized with conversion to universal time 15.04.2021 18:01:00Kind: Unspecified1234567891011复制代码类型:[cpp]

    因此,我们确实当我们调用ToString一个DateTimeKind.Local实例,它会根据服务器时区调整。

    但是,为什么将字母Z视为时区信息?上面提到的文档没有带Z字母的示例。答案是有问题的格式是ISO-8601格式,Z代表“零UTC偏移量”。是否将此格式的字符串与指定时区的任何其他字符串一样对待,还是这种特殊处理?通过比较它们,我们将得到答案。

OutputDateInfo("2021-04-15T2100.0000000Z");
OutputDateInfo("2021-04-15T2100.0000000");
OutputDateInfo("2021-04-15T1400.0000000 -7:00");123复制代码类型:[cpp]

    产量:

Input: 2021-04-15T21:01:00.0000000Z
Setialized to universal format 2021-04-16T00:01:00Z
Setialized to default format 16.04.2021 0:01:00Setialized with conversion to universal time 15.04.2021 21:01:00Kind: Local

Input: 2021-04-15T21:01:00.0000000Setialized to universal format 2021-04-15T21:01:00Z
Setialized to default format 15.04.2021 21:01:00Setialized with conversion to universal time 15.04.2021 18:01:00Kind: Unspecified

Input: 2021-04-15T14:01:00.0000000 -7:00Setialized to universal format 2021-04-16T00:01:00Z
Setialized to default format 16.04.2021 0:01:00Setialized with conversion to universal time 15.04.2021 21:01:00Kind: Local1234567891011121314151617复制代码类型:[cpp]

    如您所见,ISO-8601格式的字符串与指定了时区的任何其他日期字符串一样对待。

    我的意图不是将其视为本地时间,而是将其视为UTC时间。我的目标是为前端提供通用时间,以便将其调整为最终用户的本地时间。我们如何欺骗.NET认为这是没有任何时区的通用时间?答案是接受的过载DateTimeStyles:

private static void OutputDateInfo(string value){
    Console.WriteLine($"Input: {value}");    if (DateTime.TryParse(value, null, DateTimeStyles.AdjustToUniversal, 
                          out DateTime universalTime))
    {
        Console.WriteLine($"Adjusted to universal {universalTime}");
    }

    Console.WriteLine();
}1234567891011复制代码类型:[cpp]

    输出:

Input: 2021-04-15T21:01:00.0000000Z
Adjusted to universal 15.04.2021 21:01:00Input: 2021-04-15T21:01:00.0000000Adjusted to universal 15.04.2021 21:01:00Input: 2021-04-15T14:01:00.0000000 -7:00Adjusted to universal 15.04.2021 21:01:0012345678复制代码类型:[cpp]

    我认为,DateTimeKind在文学和博客中代表性不足。但是,在解析日期字符串并将日期转换回字符串时,绝对应该考虑到这一点。另外,值得记住的是,ISO-8601格式的日期字符串与指定了时区信息的任何其他字符串一样,尽管乍一看可能并不明显。

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多