DateTimeStyles.RoundtripKind枚举是什么意思?

RBT*_*RBT 15 .net c# datetime datetime-format

我正在阅读回答者的帖子,那里我遇到了这个DateTimeStyles.RoundtripKind我想要了解的调查员.我查看了MSDN ,其中说:

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

我引用的帖子中输入的时间戳如下:

<timestamp time='2016-09-16T13:45:30'>
Run Code Online (Sandbox Code Playgroud)

我运行她的代码,它仍然有效.现在连接我所拥有的所有信息都是一团糟:

  1. 上面的时间戳包含一些标识符 T
  2. MSDN文档讨论or格式化说明符,它没有说明它是什么?
  3. 如果你进入挖掘更多的细节上DateTimeKind列举的MSDN链接我上面引述只字未提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.
    
    Run Code Online (Sandbox Code Playgroud)

PS我尝试在上面创建一个表,但似乎SO没有创建表格结构的原生支持.

那么有人可以帮助我理解DateTimeStyles.RoundtripKind枚举及其工作原理吗?

RBT*_*RBT 12

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

第一部分是将C#DateTime对象转换为字符串.有许多格式说明符要做,但对于我们来说,"r"和"o"格式说明符是我们关注的问题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
Run Code Online (Sandbox Code Playgroud)

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

  • Fri, 23 Sep 2016 15:39:21 GMTDateTimeKind.Utc("GMT"文本存在)
  • 2016-09-23T15:39:21.8899216+05:30表示日期时间DateTimeKind.Local("T"字符按ISO 8601标准存在)

现在是第二部分.如果我要转换这些日期时间字符串gmtDateTimeString,并localDateTimeString返回到一个日期时间对象,然后我们需要分析它们.因此,在DateTimeStyles.RoundtripKind传递给DateTime.ParseAPI 的枚举值的帮助下,您实际上表示时区信息已经在字符串中被烘焙,并且API使用该信息适当地解析日期时间.

通常,当日期时间数据以XML格式通过网络传输时,我使用的是ISO 8601格式,我在帖子中看到了这个格式,我在帖子中提到了这个问题.因此,在解析从XML文档获得的这样的日期时间字符串DateTimeStyles.RoundtripKind时,根据字符串中存在的时区信息使用它来获取正确的日期时间值是合适的.


Mar*_*age 6

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

DateTimeStyles.RoundTripKind在来源中有评论:

// Attempt to preserve whether the input is unspecified, local or UTC
Run Code Online (Sandbox Code Playgroud)

它或多或少与MSDN文档一样模糊DateTimeStyles.RoundTripKind:

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

通过导航参考源网站,可以看出DateTimeStyles.RoundTripKind使用很少.基本上,如果设置了标志,那么它可以修改DateTimeto 的类型DateTimeKind.Utc.所以这是设置此标志的效果:有时Kind解析DateTime值的属性设置为Utc.

究竟何时发生这种情况由内部标志控制ParseFlags.TimeZoneUtc.这是更复杂,以确定何时该标志置位,但据我可以告诉大家,如果正在使用或者指定的时区的解析器将设置该标志ZGMT.有这个源代码中的注释:

// NOTENOTE : for now, we only support "GMT" and "Z" (for Zulu time).
Run Code Online (Sandbox Code Playgroud)

我的结论是,如果一个时间戳使用或者格式化orDateTimeStyles.RoundTripKind在解析时间戳用于那么Kind所产生的DateTime值设置为Utc如果字符串中的时区是UTC时区.

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

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

使用o格式说明符时,时间戳的时区将是ZUTC或UTC +/-的偏移量(例如2017-02-26T22:55:15.4923368+01:00).这是一个表,显示从往返时间戳解析的值的Kind属性DateTime值:

Timezone | RoundTripKind | Kind
---------+---------------+------
"Z"      | Not specified | Local
"Z"      | Specified     | Utc
Not "Z"  | Not specified | Local
Not "Z"  | Specified     | Local

如果要以往返格式解析时间戳,并且您希望时间戳的时区为UTC,那么您应指定DateTimeStyles.RoundTripKind以确保解析的DateTime值具有类型Utc.

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

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

Method     | RoundTripKind | Kind
-----------+---------------+------------
Parse      | Not specified | Local
Parse      | Specified     | Utc
ParseExact | Not specified | Unspecified
ParseExact | Specified     | Unspecified

使用该Parse方法时,RFC1123格式的时间戳与往返格式的UTC时间戳相同.但是,由于某种原因,该ParseExact方法忽略该DateTimeStyles.RoundTripKind标志.解析往返格式化时间戳时不是这种情况.

如果要解析RFC1123格式的时间戳,则应使用该Parse方法并指定,DateTimeStyles.RoundTripKind或者如果您更喜欢该ParseExact方法,则必须修改解析时间戳的类型Utc.您可以通过使用该DateTime.SpecifyKind方法创建新的时间戳来实现.

结论

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

如果往返时间戳具有非零偏移量,那么您必须将时间戳解析为DateTimeOffset值以保留偏移量(Local不会告诉您偏移量是什么 - 只是它可能与0不同).

不要DateTime.ParseExact用于解析RFC1123时间戳(或者在解析时间戳Utc之后将类型更改为).