DateTimeStyles.RoundtripKind枚举是什么意思?
What does DateTimeStyles.RoundtripKind enumeration mean?
我正在阅读这个答案 where I came across this enumeration value DateTimeStyles.RoundtripKind
. I'm trying to understand it now. I looked into MSDN docs here 上面写着:
The DateTimeKind field of a date is preserved when a DateTime object
is converted to a string using the "o" or "r" standard format
specifier, and the string is then converted back to a DateTime object.
我在上一段提到的post中input
变量指向的时间戳如下:
<timestamp time='2016-09-16T13:45:30'>
我运行她的代码并且有效。现在关联我拥有的所有信息变得有点混乱:
上面的时间戳包含一些标识符T
MSDN 文档讨论了 o
和 r
格式说明符,它没有说明它是什么?
如果您在 MSDN link 上深入了解 DateTimeKind
枚举的更多详细信息,我在上面引用过,它没有提到 o
和 r
格式说明符。 Here 是 link 表示:
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.
有人可以帮助我理解 DateTimeStyles.RoundtripKind
枚举及其工作原理吗?
往返格式适用于 "machine consumption" - 它可以很容易地解析回相同的 DateTime 值。
大多数其他格式用于 "human consumption",向某人显示日期(可能包括时间)。
所以我终于能够理解这一点并在这里分享相同的信息,如果它对其他人也有帮助的话:
第一部分是将 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
您可以清楚地看到输出的字符串日期时间中嵌入了信息,这表明:
- 2016 年 9 月 23 日,星期五 15:39:21 GMT 是 DateTimeKind.Utc(GMT 文本存在)
- 2016-09-23T15:39:21.8899216+05:30表示日期时间DateTimeKind.Local(T 字符按照 ISO 8601 标准存在)
现在是第二部分。如果我必须将存储在 gmtDateTimeString
和 localDateTimeString
中的日期时间字符串转换回日期时间对象,那么我们需要解析它们。因此,在 DateTimeStyles.RoundtripKind 枚举值传递给 DateTime.Parse API 的帮助下,您实际上表示该时区信息已经包含在字符串中,API 使用该信息适当地解析日期时间。
通常,当日期时间数据以 XML 格式通过网络传输时,会使用 ISO 8601 格式,我在 post 中看到我在此线程中 post 提出问题之前提到过。因此,在解析从 XML 文档中获取的此类日期时间字符串时,使用 DateTimeStyles.RoundtripKind 来根据时间获取正确的日期时间值是合适的-字符串中存在区域信息。
我很难理解其他答案,所以我决定自己做一些研究。幸运的是,.NET 库的源代码可以在线获得。
DateTimeStyles.RoundTripKind
has a comment in the source:
// Attempt to preserve whether the input is unspecified, local or UTC
它或多或少与 DateTimeStyles.RoundTripKind
上的 MSDN 文档一样模糊:
The DateTimeKind field of a date is preserved when a DateTime object is converted to a string using the "o" or "r" standard format specifier, and the string is then converted back to a DateTime object.
通过浏览 Reference Source 网站可以看出 DateTimeStyles.RoundTripKind
很少使用。本质上,如果设置了标志,则 it may modify the kind of the DateTime
to DateTimeKind.Utc
。所以这是设置这个标志的效果:有时解析的 DateTime
值的 Kind
属性 设置为 Utc
.
发生这种情况的确切时间由内部标志控制 ParseFlags.TimeZoneUtc
. It is more complicated to determine when this flag gets set but as far as I can tell the parser will set this flag if the timezone is specified using either Z
or GMT
. There is 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
=15=] 如果字符串中的时区是 UTC 时区,则值设置为 Utc
。
但是,如果没有设置标志会发生什么?确定这一点的最佳方法是对两个格式说明符进行一些实际测试。
往返("O"、"o")格式说明符
当使用 o
格式说明符时,时间戳的时区将是 Z
(UTC)或 +/-
与 UTC 的偏移量(例如 2017-02-26T22:55:15.4923368+01:00
)。这是一个 table,显示从往返时间戳解析的 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
格式的 113=] 不需要 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
方法创建一个新的时间戳来做到这一点。
结论
在解析round-trip和RFC1123时间戳时指定DateTimeStyles.RoundTripKind
以确保解析的DateTime
值的Kind
属性为Utc
。
如果往返时间戳具有非零偏移量,则您必须将时间戳解析为 DateTimeOffset
值以保留偏移量(Local
不会告诉您偏移量是多少是 - 只是它可能与 0 不同)。
不要使用DateTime.ParseExact
解析RFC1123时间戳(或在解析时间戳后将种类更改为Utc
)。
我正在阅读这个答案 DateTimeStyles.RoundtripKind
. I'm trying to understand it now. I looked into MSDN docs here 上面写着:
The DateTimeKind field of a date is preserved when a DateTime object is converted to a string using the "o" or "r" standard format specifier, and the string is then converted back to a DateTime object.
我在上一段提到的post中input
变量指向的时间戳如下:
<timestamp time='2016-09-16T13:45:30'>
我运行她的代码并且有效。现在关联我拥有的所有信息变得有点混乱:
上面的时间戳包含一些标识符
T
MSDN 文档讨论了
o
和r
格式说明符,它没有说明它是什么?如果您在 MSDN link 上深入了解
DateTimeKind
枚举的更多详细信息,我在上面引用过,它没有提到o
和r
格式说明符。 Here 是 link 表示: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.
有人可以帮助我理解 DateTimeStyles.RoundtripKind
枚举及其工作原理吗?
往返格式适用于 "machine consumption" - 它可以很容易地解析回相同的 DateTime 值。
大多数其他格式用于 "human consumption",向某人显示日期(可能包括时间)。
所以我终于能够理解这一点并在这里分享相同的信息,如果它对其他人也有帮助的话:
第一部分是将 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
您可以清楚地看到输出的字符串日期时间中嵌入了信息,这表明:
- 2016 年 9 月 23 日,星期五 15:39:21 GMT 是 DateTimeKind.Utc(GMT 文本存在)
- 2016-09-23T15:39:21.8899216+05:30表示日期时间DateTimeKind.Local(T 字符按照 ISO 8601 标准存在)
现在是第二部分。如果我必须将存储在 gmtDateTimeString
和 localDateTimeString
中的日期时间字符串转换回日期时间对象,那么我们需要解析它们。因此,在 DateTimeStyles.RoundtripKind 枚举值传递给 DateTime.Parse API 的帮助下,您实际上表示该时区信息已经包含在字符串中,API 使用该信息适当地解析日期时间。
通常,当日期时间数据以 XML 格式通过网络传输时,会使用 ISO 8601 格式,我在 post 中看到我在此线程中 post 提出问题之前提到过。因此,在解析从 XML 文档中获取的此类日期时间字符串时,使用 DateTimeStyles.RoundtripKind 来根据时间获取正确的日期时间值是合适的-字符串中存在区域信息。
我很难理解其他答案,所以我决定自己做一些研究。幸运的是,.NET 库的源代码可以在线获得。
DateTimeStyles.RoundTripKind
has a comment in the source:
// Attempt to preserve whether the input is unspecified, local or UTC
它或多或少与 DateTimeStyles.RoundTripKind
上的 MSDN 文档一样模糊:
The DateTimeKind field of a date is preserved when a DateTime object is converted to a string using the "o" or "r" standard format specifier, and the string is then converted back to a DateTime object.
通过浏览 Reference Source 网站可以看出 DateTimeStyles.RoundTripKind
很少使用。本质上,如果设置了标志,则 it may modify the kind of the DateTime
to DateTimeKind.Utc
。所以这是设置这个标志的效果:有时解析的 DateTime
值的 Kind
属性 设置为 Utc
.
发生这种情况的确切时间由内部标志控制 ParseFlags.TimeZoneUtc
. It is more complicated to determine when this flag gets set but as far as I can tell the parser will set this flag if the timezone is specified using either Z
or GMT
. There is 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
=15=] 如果字符串中的时区是 UTC 时区,则值设置为 Utc
。
但是,如果没有设置标志会发生什么?确定这一点的最佳方法是对两个格式说明符进行一些实际测试。
往返("O"、"o")格式说明符
当使用 o
格式说明符时,时间戳的时区将是 Z
(UTC)或 +/-
与 UTC 的偏移量(例如 2017-02-26T22:55:15.4923368+01:00
)。这是一个 table,显示从往返时间戳解析的 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
格式的 113=] 不需要 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
方法创建一个新的时间戳来做到这一点。
结论
在解析round-trip和RFC1123时间戳时指定DateTimeStyles.RoundTripKind
以确保解析的DateTime
值的Kind
属性为Utc
。
如果往返时间戳具有非零偏移量,则您必须将时间戳解析为 DateTimeOffset
值以保留偏移量(Local
不会告诉您偏移量是多少是 - 只是它可能与 0 不同)。
不要使用DateTime.ParseExact
解析RFC1123时间戳(或在解析时间戳后将种类更改为Utc
)。