我正在阅读回答者的帖子here,在那里我遇到了我想要了解的这个调查员DateTimeStyles.RoundtripKind
。我查看了MSDN here,其中说:
DateTime对象时保留日期的DateTimeKind字段 使用“o”或“r”标准格式转换为字符串 说明符,然后将字符串转换回DateTime对象。
我提到的帖子中输入的时间戳如下:
<timestamp time='2016-09-16T13:45:30'>
我运行了她的代码,它仍然有效。现在连接我所拥有的所有信息都是一团糟:
T
o
和r
格式说明符,它没有说明它是什么?如果您在我上面引用的MSDN链接上详细了解DateTimeKind
枚举的详细信息,则说明o
和r
格式说明符没有任何内容。 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.
P.S。我尝试在上面创建一个表,但似乎SO没有创建表格结构的原生支持。
那么有人可以帮助我理解DateTimeStyles.RoundtripKind
枚举及其工作原理吗?
答案 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”字符出现)现在是第二部分。如果我要将这些日期时间字符串gmtDateTimeString
和localDateTimeString
转换回日期时间对象,那么我们需要解析它们。因此,在传递给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
正确控制。确定何时设置此标志会更复杂,但据我所知,如果使用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
,那么Kind
会生成DateTime
如果字符串中的时区是UTC时区,则value设置为Utc
。
然而,当没有设置标志时会发生什么?确定这一点的最佳方法是对两个格式说明符进行一些实际测试。
使用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
。
使用r
格式说明符时,时间戳将始终包含GMT
(即使原始DateTime
的类型不是Utc
),因此{ {1}}格式不需要r
列。但是,我发现解析RFC1123时间戳时Timezone
和DateTime.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值。
大多数其他格式用于“人类消费”,以向人显示日期(可能包括时间)。