我很难理解其他答案,所以我决定自己做一些研究。幸运的是,.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
控制。确定何时设置此标志更为复杂,但据我所知,如果使用Z
或GMT
指定时区,解析器将设置此标志。有a comment about this in the source code:
// NOTENOTE : for now, we only support "GMT" and "Z" (for Zulu time).
我的结论是,如果一个时间戳使用格式化或者o
或r
和DateTimeStyles.RoundTripKind
在解析时间戳然后将得到的DateTime
值Kind
是,如果时区的设置为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.Parse
和DateTime.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
,以确保解析DateTime
值Kind
属性为Utc
。
如果往返时间戳具有非零偏移量,那么您将不得不将时间戳解析为DateTimeOffset
值以保留偏移量(Local
不会告诉您偏移量是什么 - 只是它可能不同于0)。
请勿使用DateTime.ParseExact
解析RFC1123时间戳(或在解析时间戳后将类型更改为Utc
)。
有关o和r的详细信息,请参阅https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx –
“T”只是ISO-8601的一部分格式 –
在示例中,“T”不是格式说明符。 –