我正在努力理解为什么解析由DateTime的Parse
方法解析的ISO 8601格式的字符串不会设置新Kind
对象的DateTime
属性的原因正确地。我查看了帖子How to create a .NET DateTime from ISO 8601 format,并与ISO文档结合使用,看来Parse
方法应该能够设置Kind
值,但是不能。
示例:
Console.Write(System.DateTime.Parse("2018-11-17T01:00:00").Kind);
返回:未指定
但是,根据ISO标准,这是一种有效的格式,表明该值是本地时间。
ISO 8601中的时区表示为本地时间(未指定位置),UTC或与UTC的偏移量。如果未使用时间表示形式提供任何UTC关系信息,则该时间假定为当地时间。
Coordinated Universal Time (UTC)
如果时间以UTC表示,则在时间后直接添加一个Z,不能带空格。 Z是UTC偏移为零的区域指示符
甚至陌生的是,在字符串中添加Z会将Kind
属性设置为Local。
为了正确设置UTC字符串的Kind
值,在Parse
方法中需要RoundtripKind的DateTimeStyle。但是,如果再次从字符串Kind
中删除Z,则会再次设置为Unspecified。
DateTime类是否有问题?
Microsoft是否未遵循ISO标准?
还是我不了解ISO标准?
答案 0 :(得分:2)
要解析ISO 8601字符串并适当设置DateTimeKind
,可以将DateTimeStyles.RoundtripKind
与the o
standard format specifier或包含the K
custom format specifier的自定义字符串一起使用。
例如:
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
。
答案 1 :(得分:1)
不要使用DateTime
来解析字符串,而是使用DateTimeOffset
。然后,您可以使用生成的LocalDateTime
的{{1}}或UtcDateTime
属性,以显式获取本地时间或UTC时间中的字符串表示的时间。或者,您可以使用DateTimeOffset
属性来检查字符串最初是否包含时区偏移。
答案 2 :(得分:-2)
您可以明确指定将字符串解释为本地时间:
Console.Write
(
DateTime.Parse("2018-11-17T01:00:00", null, DateTimeStyles.AssumeLocal).Kind
);
输出:
Local