DateTimeStyles.RoundtripKind枚举是什么意思?

时间:2016-09-19 11:44:55

标签: c# .net datetime datetime-format

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

  

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

我提到的帖子中输入的时间戳如下:

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

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

  1. 上述时间戳包含一些标识T
  2. MSDN文档讨论了or格式说明符,它没有说明它是什么?
  3. 如果您在我上面引用的MSDN链接上详细了解DateTimeKind枚举的详细信息,则说明or格式说明符没有任何内容。 Here是指的链接:

    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.
    
  4. P.S。我尝试在上面创建一个表,但似乎SO没有创建表格结构的原生支持。

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

3 个答案:

答案 0 :(得分:11)

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

第一部分是将C#DateTime对象转换为字符串。有许多格式说明符要做,但对于我们来说,“r”和“o”格式说明符与DateTimeStyles.RoundtripKind有关。您可以查看所有日期时间格式说明符here。看看使用这些格式说明符在代码中进行转换时会发生什么:

//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 GMT属于DateTimeKind.Utc(“GMT”文字存在)
  • 2016-09-23T15:39:21.8899216+05:30表示DateTimeKind.Local的日期时间(根据ISO 8601标准,“T”字符出现)

现在是第二部分。如果我要将这些日期时间字符串gmtDateTimeStringlocalDateTimeString转换回日期时间对象,那么我们需要解析它们。因此,在传递给DateTimeStyles.RoundtripKind API的DateTime.Parse枚举值的帮助下,您实际上表示时区信息已在字符串中烘焙,API会使用该信息正确地解析日期时间。

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

答案 1 :(得分:5)

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

DateTimeStyles.RoundTripKind has a comment in the source

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

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

  

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

通过导航参考源网站,可以看出DateTimeStyles.RoundTripKind使用得很少。基本上,如果设置了标志,则it may modify the kind of the DateTime to DateTimeKind.Utc。因此,这是设置此标志的效果:有时,已解析的Kind值的DateTime属性设置为Utc

当发生这种情况时,内部标志ParseFlags.TimeZoneUtc正确控制。确定何时设置此标志会更复杂,但据我所知,如果使用ZGMT指定时区,解析器将设置此标志。有a comment about this in the source code

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

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

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

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

使用o格式说明符时,时间戳的时区将为Z表示UTC或+/-与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),因此{ {1}}格式不需要r列。但是,我发现解析RFC1123时间戳时TimezoneDateTime.Parse的行为有所不同:

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

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

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

结论

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

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

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

答案 2 :(得分:3)

往返格式用于“机器消耗” - 可以轻松地将其解析回相同的DateTime值。
大多数其他格式用于“人类消费”,以向人显示日期(可能包括时间)。