.NET System.DateTime.ToLocalTime()返回无效的本地时间值



我从服务器收到一个json,其时间戳为UTC格式:

{
"foo": "2017-11-05T08:30:00"
}

并使用CCD_ 1将其转换为.NET实例。我接收到的DateTime属性具有一个包含DateTimeKind = Unspecified的有效值。

然后我调用obj.foo.ToLocalTime()并获得2017-11-05 00:30 AM,而我在计算机上的真实本地时间是2017-11-05 01:30 AM(-7)

为什么损失了1个小时(我想这与夏令时有关)?

我如何在反序列化级别上解决这个问题,以便每个实例都能正确地转换为有效的UTC DateTime实例?

更新:这发生在2017年11月5日,当时夏令时机会出现,客户(-7)有待定的UTC夏令时更改,而UTC已经超过了该点(UTC时间为8:30,而客户时间为凌晨1:30,我们预计时间更改为凌晨2:00)。现在它工作正常,没有任何更改,但值得修复服务器(Z)和客户端(UTC)端。

您的问题是您的时间戳值"2017-11-05T08:30:00"完全缺少时区指示符,UTC为"2017-11-05 T08:30:00Z",本地时区为"2017-11-105T08:00-07:00"。也就是说,您关于时间戳是UTC格式的的声明是错误的。

当这种情况发生时,Json.NET将该值解析为具有Json.Deserialize0的DateTime(这是有道理的,因为实际上Json中未指定时区)。后来,其他一些代码将其解释为本地时间,但由于夏令时实际上在您在个人资料中列出的地点(美国华盛顿特区)提出此问题时到期,事情变得混乱起来,因为DateTime不记得它的时区偏移,只记得它是否在机器的本地时区。(有关此限制的更多信息,请参阅本文档页以及Jon Skeet的DateTime到底出了什么问题?,其中特别提到.Net日期和时间类型的某些错误只能在夏令时更改期间发生。)如果夏令时在反序列化时间戳和随后处理时间戳之间过期,你会得到你所看到的错误。

话虽如此,您会问,我如何在反序列化级别上解决这个问题,以便每个实例都可以正确地转换为有效的UTC DateTime实例这可以通过在反序列化期间设置JsonSerializerSettings.DateTimeZoneHandling == DateTimeZoneHandling.Utc来完成:

var settings = new JsonSerializerSettings
{
DateTimeZoneHandling = DateTimeZoneHandling.Utc,
};
var root = JsonConvert.DeserializeObject<RootObject>(json, settings);

这里解释了DateTimeZoneHandling的可能值:

  • 本地:视为本地时间。如果DateTime对象表示协调世界时(UTC),则会将其转换为本地时间。

  • Utc:视为Utc。如果DateTime对象表示本地时间,则会将其转换为UTC。

  • 未指定:如果DateTime正在转换为字符串,则视为本地时间。如果字符串正在被转换为DateTime,如果指定了时区,则转换为本地时间。

  • RoundtripKind:转换时应保留时区信息。

通过使用DateTimeZoneHandling.Utc,时间戳将从一开始就被假定为UTC,因此不应出现由于夏令时变化而导致的奇怪行为。

您还可以考虑修复服务器代码,使其在时间戳值后正确地附加一个Z,以表明该值实际上是UTC。

小提琴样品显示了所有四种设置的作用。

相关内容

  • 没有找到相关文章