DateTimeStyles.往返类枚举均值

本文关键字:枚举 DateTimeStyles | 更新日期: 2023-09-27 18:07:53

我在这里阅读这个答案,在那里我遇到了这个枚举值DateTimeStyles.RoundtripKind。我现在试着去理解它。我查看了MSDN文档这里写着:

日期的DateTimeKind字段在DateTime对象中保留使用" 0 "转换为字符串。或";r"标准格式指定符,然后将字符串转换回DateTime对象。

上一段提到的post中input变量所指向的时间戳如下:

<timestamp time='2016-09-16T13:45:30'>

我运行了她的代码,它可以工作。现在把所有的信息关联起来就有点麻烦了:

  1. 以上时间戳包含一些标识符T

  2. MSDN文档讨论了or格式说明符,它没有告诉它是什么?

  3. 如果你在我上面引用的MSDN链接上深入挖掘DateTimeKind枚举的更多细节,它没有提到or格式说明符。这是一个链接,上面写着:

    Member Name   |  Description
    --------------------------------------------------------------------------------
    Local         |  The time represented is local time.
    

    Unspecified   |  The time represented is not specified as either local time or Coordinated Universal Time (UTC).
    

    Utc           |      The time represented is UTC.
    

所以有人能帮助我理解DateTimeStyles.RoundtripKind枚举和它是如何工作的吗?

DateTimeStyles.往返类枚举均值

所以我终于能够理解这一点,并在这里分享相同的信息,如果它对其他人也有帮助:

第一部分是c# DateTime对象到字符串的转换。有许多格式说明符可以做到这一点,但对我们来说,ro格式说明符与DateTimeStyles.RoundtripKind有关。您可以在这里看到所有日期时间格式说明符。看看在代码中使用这些格式说明符进行转换时会发生什么:
//r corresponds to RFC 1123 format (GMT date time format)
var gmtDateTimeString = DateTime.Now.ToString("r"); //gives Fri, 23 Sep 2016 15:39:21 GMT 
//o corresponds to ISO 8601 (Local date time format)
var localDateTimeString = DateTime.Now.ToString("o"); //gives 2016-09-23T15:39:21.8899216+05:30

你可以清楚地看到输出的字符串日期时间嵌入了信息,这表明:

  • Fri, 23 Sep 2016 15:39:21 GMTDateTimeKind的。格林尼治时间Utc (文本存在)
  • 2016-09-23T15:39:21.8899216+05:30表示DateTimeKind的日期时间。本地 (T字符根据ISO 8601标准存在)

现在是第二部分。如果我必须将存储在gmtDateTimeStringlocalDateTimeString中的日期时间字符串转换回日期时间对象,那么我们需要解析它们。所以在DateTimeStyles的帮助下。RoundtripKind传递给日期时间的枚举值。解析 API,您实际上表示时区信息已经在字符串中烘烤,API使用该信息适当地解析日期时间。

通常情况下,当日期时间数据以XML格式通过电线传输时,使用ISO 8601格式,这是我在帖子中看到的,我在这个帖子中发布问题之前提到过。因此,在解析从XML文档获得的日期时间字符串时,使用DateTimeStyles是合适的。RoundtripKind根据字符串中存在的时区信息获取正确的日期时间值。

我很难理解其他的答案,所以我决定自己做一些研究。幸运的是,. net库的源代码可以在线获得。

DateTimeStyles.RoundTripKind在源代码中有注释:

// Attempt to preserve whether the input is unspecified, local or UTC

它或多或少就像DateTimeStyles.RoundTripKind上的MSDN文档一样模糊:

当使用"o"或"r"标准格式说明符将DateTime对象转换为字符串,然后将字符串转换回DateTime对象时,日期的DateTimeKind字段将被保留。

通过浏览参考源网站,可以看到DateTimeStyles.RoundTripKind的使用很少。实际上,如果设置了该标志,则可以将DateTime的类型修改为DateTimeKind.Utc。这就是设置这个标志的效果:有时解析后的DateTime值的Kind属性被设置为Utc

具体发生的时间由内部标志ParseFlags.TimeZoneUtc控制。确定何时设置此标志更为复杂,但据我所知,如果使用ZGMT指定时区,解析器将设置此标志。在源代码中有一个注释:

// NOTENOTE : for now, we only support "GMT" and "Z" (for Zulu time).

我的结论是,如果使用or格式化时间戳,并且在解析时间戳时使用DateTimeStyles.RoundTripKind,则如果字符串中的时区是UTC时区,则结果DateTime值的Kind设置为Utc

但是,如果没有设置标志会发生什么?确定这一点的最佳方法是对这两个格式说明符进行一些实际测试。

往返("O", "O")格式说明符

当使用o格式指定符时,时间戳的时区将为UTC的Z或与UTC的偏移量+/-(例如2017-02-26T22:55:15.4923368+01:00)。下面的表格显示了从往返时间戳解析的DateTime值的Kind属性值:

<>之前时区|往返类型|类型---------+---------------+------"Z"|未指定|本地"Z" |指定| Utc非"Z"|未指定|本地非"Z"|指定|本地之前

如果你想解析一个往返格式的时间戳,并且你希望时间戳的时区是UTC,那么你应该指定DateTimeStyles.RoundTripKind,以确保解析的DateTime值类型为Utc

RFC1123 ("R", "R")格式说明符

当使用r格式说明符时,时间戳将始终包含GMT(即使原始DateTime的类型不是Utc),因此r格式的表不需要Timezone列。但是,我发现DateTime.ParseDateTime.ParseExact在解析RFC1123时间戳时的行为不同:

<>之前Method | RoundTripKind | Kind-----------+---------------+------------解析|未指定|本地解析|指定| UtcParseExact |未指定|未指定ParseExact |指定|未指定之前

当使用Parse方法时,RFC1123格式的时间戳的行为与往返格式的UTC时间戳相同。然而,由于某种原因,ParseExact方法忽略了DateTimeStyles.RoundTripKind标志。在解析往返格式化时间戳时不会出现这种情况。

如果你想解析RFC1123格式的时间戳,你应该使用Parse方法并指定DateTimeStyles.RoundTripKind,或者如果你喜欢ParseExact方法,你必须将解析的时间戳类型修改为Utc。您可以使用DateTime.SpecifyKind方法创建一个新的时间戳。

结论

解析往返时间戳和RFC1123时间戳时指定DateTimeStyles.RoundTripKind,以确保解析后的DateTime值的Kind属性为Utc

如果一个往返时间戳有一个非零的偏移量,那么你必须将时间戳解析成DateTimeOffset的值来保留偏移量(Local不会告诉你偏移量是什么——只是告诉你它可能与0不同)。

不使用DateTime.ParseExact来解析RFC1123时间戳(或者在时间戳被解析后将类型更改为Utc)。

往返格式意味着"机器消费"-它可以很容易地解析回相同的DateTime值。
大多数其他格式是供"人使用"的,用于向人显示日期(可能包括时间)。