【问题标题】:What does DateTimeStyles.RoundtripKind enumeration mean?DateTimeStyles.RoundtripKind 枚举是什么意思?
【发布时间】:2017-01-27 02:20:22
【问题描述】:

我正在阅读回答者的帖子here,在那里我遇到了我试图理解的枚举值DateTimeStyles.RoundtripKind。我查看了 MSDN here,上面写着:

日期的 DateTimeKind 字段在 DateTime 对象时被保留 使用“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.
    

P.S.我尝试在上面创建一个表格,但似乎 SO 不支持创建表格结构。

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

【问题讨论】:

标签: c# .net datetime datetime-format


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    第一部分是将 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 转换回日期时间对象,那么我们需要解析它们。因此,借助传递给 DateTime.Parse API 的 DateTimeStyles.RoundtripKind 枚举值,您实际上表示时区信息已经包含在字符串中,API 会使用该信息适当地解析日期时间。

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

    【讨论】:

      【解决方案3】:

      我很难理解其他答案,所以我决定自己做一些研究。幸运的是,.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。所以这就是设置这个标志的效果:有时候解析后的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).
      

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

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

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

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

      时区 |往返种类 |种类 ---------+---------------+------ "Z" |未指定 |当地的 "Z" |指定 |世界标准时间 不是“Z” |未指定 |当地的 不是“Z” |指定 |当地的

      如果您想解析往返格式的时间戳,并且您希望时间戳的时区为 UTC,那么您应该指定 DateTimeStyles.RoundTripKind 以确保解析的 DateTime 值具有类型 Utc .

      RFC1123(“R”、“r”)格式说明符

      当使用r 格式说明符时,时间戳将始终包含GMT(即使原始DateTime 的类型不是Utc)因此r 格式的表不需要Timezone 专栏。但是,我发现 DateTime.ParseDateTime.ParseExact 在解析 RFC1123 时间戳时表现不同:

      方法 |往返种类 |种类 -----------+---------------+------------ 解析 |未指定 |当地的 解析 |指定 |世界标准时间 解析精确 |未指定 |未指定 解析精确 |指定 |未指定

      使用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)。

      【讨论】:

        猜你喜欢
        • 2013-07-27
        • 1970-01-01
        • 2011-06-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-05
        • 1970-01-01
        • 2012-07-31
        相关资源
        最近更新 更多