JavaScriptSerializer 使用 DateTime 或 DateTimeOffset 反序列化

JavaScriptSerializer Deserialize with DateTime or DateTimeOffset

针对 .NET4.5 编译的 VB2012:这几天一直困扰着我。我有 json 数据,我正在用 JavaScriptSerializer.Deserialize class 解析。其中一个字段显示如下:

depart 2017-09-22T00:45:00-07:00

出发的当地时间(这是在洛杉矶)。

在我的包装纸里class我写了

Public Class JsonLeg
    Public depart As DateTime
    Public blah...many more fields
End Class

我摄取 json 数据并使用 JavaScriptSerializer.Deserialize 解析它。之后我调试输出,它看起来像这样

depart                 [Kind=Local] 2017-09-22T02:45:00
depart.ToLocalTime     [Kind=Local] 2017-09-22T02:45:00
depart.ToUniversalTime [Kind=Utc  ] 2017-09-22T07:45:00

看起来一切正常,但 ToLocalTime 只是将其转换为我计算机位于达拉斯的时区。我需要的是洛杉矶 2017-09-22T00:45:00 的 当地时间,以与没有种类的日期列表进行比较。我如何提取原始位置的本地时间而不是计算机的本地时间?

我确实使用 DateTimeOffset 作为变量进行了测试,但恐怕我不明白解串器在解析 json 数据时在做什么。

调试看起来像:

depart.DateTime      [Kind=Unspecified] 2017-09-22T00:45:00
depart.LocalDateTime [Kind=Local      ] 2017-09-22T02:45:00
depart.UtcDateTime   [Kind=Utc        ] 2017-09-22T07:45:00

在这种情况下,DateTimeOffset.DateTime 满足了我的需求。但为什么?我试图了解它们之间的区别以及反序列化器如何解析每个区别。

您的数据在 ISO 8601 extended format, with offset. This is also covered by RFC3339.

当您使用 JavaScriptSerializer 将此格式的字符串反序列化为 DateTime 时,它会做出一个相当宏大的假设,即它是从另一个 DateTime 生成的 [=13] =].由于您的机器和生成数据的机器之间的偏移量可能匹配也可能不匹配,因此它首先应用提供的偏移量以获取 UTC,然后转换回您的本地时区。这可能不是您想要的行为,并且没有很好的方法让 JavaScriptSerializer 表现得不同。解析为 DateTimeOffset 更有意义。生成的日期、时间和偏移量部分与所提供的完全匹配。

一旦你有一个 DateTimeOffset,调用 .DateTime 只返回日期和时间部分,结果类型为 Unspecified。这是所有 DateTimeOffset 个实例的标准行为,而不仅仅是那些通过解析获得的实例。原因是偏移量可以是任何东西,将它映射到 LocalUtc 将是错误的。

同样,.LocalDateTime 转换为考虑偏移量的本地时间(类似于直接解析为 DateTime)。 .UtcDateTime 将偏移量考虑在内并转换为 UTC,类似于在 DateTime 版本上调用 .ToUniversalTime()

此外,您应该考虑使用 Json.NET 而不是 JavaScriptSerializer。大多数 .NET 社区,包括 Microsoft,现在都使用此库进行 JSON 序列化。它更加灵活,并且在日期和时间方面往往开箱即用。