2016-09-19 88 views
5

我正在阅读回答者的帖子here,我遇到了这个我试图理解的调查员DateTimeStyles.RoundtripKind。我看着MSDN here它说:DateTimeStyles.RoundtripKind枚举是什么意思?

当DateTime对象 被转换为使用“○”或“r”标准格式 说明符字符串的日期的DateTimeKind字段被保留,并且该字符串是然后转换回DateTime对象。

在后输入时间戳我提到是这样的:

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

我跑到她的代码,它仍然有效。现在,它是所有一团糟连接所有我掌握的信息:

  1. 上述时间标记包含了一些标识T
  2. MSDN文档谈到or格式说明它不知道是什么?
  3. 如果您在MSDN链接上查询更多关于DateTimeKind枚举的详细信息,我已经在上面引用了它,并没有提到or格式说明符。 Here是说的链接:

成员名称说明

本地=>为代表的时间是当地时间。

未指定=>所表示的时间未指定为本地时间或协调世界时(UTC)。

Utc =>所代表的时间是UTC。

P.S.我试着在上面创建一个表,但它似乎没有本地支持创建表格结构。

那么有人可以帮我理解DateTimeStyles.RoundtripKind枚举和它是如何工作的?

+2

有关o和r的详细信息,请参阅https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx –

+1

“T”只是ISO-8601的一部分格式 –

+1

在示例中,“T”不是格式说明符。 –

回答

6

所以,我终于能理解这一点,并在这里共享相同的信息,如果它可以为他人有所帮助过:

第一部分是转换C#DateTime对象转换为字符串。有很多格式说明符可以做到这一点,但对于我们来说,关于DateTimeStyles.RoundtripKind,“r”和“o”格式说明符是我们关心的。您可以看到所有日期时间格式说明符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 GMTDateTimeKind.Utc( “GMT” 文本存在时)
  • 2016-09-23T15:39:21.8899216+05:30表示DateTimeKind.Local的日期时间( “T” 字的存在按照ISO 8601标准)

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

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

2

往返格式是为了“机器消耗” - 它可以很容易地解析回相同的DateTime值。
其他大多数格式都是为了“人类消费”,向一个人展示日期(可能包括时间)。

2

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

DateTimeStyles.RoundTripKind has a comment in the source

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

它或多或少正如含糊上DateTimeStyles.RoundTripKind MSDN文档:

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

通过浏览Reference Source网站,可以看出DateTimeStyles.RoundTripKind的使用非常少。实质上,如果该标志被设置,则it may modify the kind of the DateTime to DateTimeKind.Utc。因此,这是设置此标志的效果:有时,解析的DateTime值的Kind属性设置为Utc

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

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

我的结论是,如果一个时间戳使用格式化或者orDateTimeStyles.RoundTripKind在解析时间戳然后将得到的DateTimeKind是,如果时区的设置为Utc使用字符串是UTC时区。

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

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

当使用o格式说明时间戳的时区要么是Z对于UTC或+/-的从UTC偏移(例如2017-02-26T22:55:15.4923368+01:00) 。下面是显示DateTime值从往返时间戳解析的Kind属性的值表:

 
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列。然而,我发现,DateTime.ParseDateTime.ParseExact不同的行为时,RFC1123时间戳解析:

 
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,以确保解析DateTimeKind属性为Utc

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

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