让C#正确设置已解析ISO 8601字符串的Kind属性

让C#正确设置已解析ISO 8601字符串的Kind属性,c#,datetime,iso,C#,Datetime,Iso,我很难理解为什么解析DateTime的Parse方法解析的格式化字符串不能正确设置新DateTime对象的Kind属性。我已经阅读了这篇文章,结合ISO文档,似乎Parse方法应该能够设置Kind值,但是它不是 例如: Console.Write(System.DateTime.Parse(“2018-11-17T01:00:00”).Kind) 返回:未指定 但是,根据ISO标准,这是一种有效的格式,表示该值为本地时间 ISO 8601中的时区表示为本地时间(未指定位置)、UTC或UTC的偏

我很难理解为什么解析DateTime的
Parse
方法解析的格式化字符串不能正确设置新
DateTime
对象的
Kind
属性。我已经阅读了这篇文章,结合ISO文档,似乎
Parse
方法应该能够设置
Kind
值,但是它不是

例如:

Console.Write(System.DateTime.Parse(“2018-11-17T01:00:00”).Kind)

返回:未指定

但是,根据ISO标准,这是一种有效的格式,表示该值为本地时间

ISO 8601中的时区表示为本地时间(未指定位置)、UTC或UTC的偏移量。如果未提供带有时间表示的UTC关系信息,则假定时间为本地时间

如果时间以UTC为单位,则在时间后直接添加一个Z,不带空格。Z是零UTC偏移的区域指示符

更奇怪的是,在字符串中添加Z会将
Kind
属性设置为Local

为了正确设置UTC字符串的
Kind
值,在
Parse
方法中需要使用RoundtripKind的DateTimeStyle。但是,如果从字符串中删除Z,则类型将再次设置为未指定

这是DateTime类的问题吗

微软没有遵循ISO标准吗


还是我不理解ISO标准?

您可以明确指定字符串应解释为本地时间:

Console.Write
(
    DateTime.Parse("2018-11-17T01:00:00", null, DateTimeStyles.AssumeLocal).Kind
);
输出:

Local

不要使用
DateTime
来解析字符串,而是使用
DateTimeOffset
。然后,您可以使用生成的
DateTimeOffset
LocalDateTime
UtcDateTime
属性以本地时间或UTC时间显式获取字符串表示的时间。或者,您可以使用
Offset
属性来检查字符串最初是否包含时区偏移。

要解析ISO 8601字符串并适当设置
DateTimeKind
,您可以使用或使用包含的自定义字符串

例如:

DateTime dt = DateTime.ParseExact(yourISO8601String, "yyyy-MM-dd'T'HH:mm:ss.FFFK",
                                CultureInfo.InvariantCulture, DateTimeStyles.RountripKind);
DateTimeStyles.RoundtripKind
提供以下行为:

  • 如果传入值没有提供时区偏移,则生成的
    DateTime
    将具有
    DateTimeKind.Unspecified
  • 如果传入值的时区偏移量为
    Z
    ,则生成的
    DateTime
    将具有
    DateTimeKind.Utc
  • 如果传入值具有数字时区偏移量,例如
    -07:00
    +01:00
    ,甚至
    +00:00
    ,则生成的
    DateTime
    将具有
    DateTimeKind.Local
    ,并且该值将从提供的时区偏移量转换为本地时区

虽然这在很多情况下都有效,但第三个项目符号的转换行为通常是不受欢迎的,因此在大多数情况下,最好解析为
DateTimeOffset
,而不是
DateTime

我试图解释以Z结尾或不以Z结尾的传入字符串,而不必预先解析它。如果我记得的话,我通过在字符串末尾添加Z来测试它,它仍然表示Local或Unspecified。