ISO 8601 日期 JS 解释差异 - IE/FF 与 Chrome

ISO 8601 Date JS Interpretation Difference - IE/FF versus Chrome

为什么 IE/FF 和 Chrome javascript 引擎 differ on how to interpret 这种 日期格式 (YYYY- MM-DDTHH:mm:ss.fff) 没有时区指示符?

new Date("2015-02-18T15:43:57.803").getUTCHours()

UTC 时间

Chrome: 15
IE11/FF: 21

我不明白 - 是因为 Chrome 假设它是本地的而 IE/FF 假设它是 UTC 吗?这似乎是一个 Chrome 错误。

有趣的是 - 在字符串末尾附加一个 "Z" 告诉 Chrome 和 IE/FF 时间是 UTC,他们可以同意。有没有其他人注意到 javascript 与 Date 的实施差异?

new Date("2015-02-18T15:43:57.803Z").getUTCHours()

UTC 时间

Chrome: 15
IE11/FF: 15

最终 - 这是 out-of-box serializer for ASP.NET Web API, which I thought used JSON.NET, but now appears to be internal where JSON.NET uses IsoDateTimeConverter 的结果。

检查 GlobalConfiguration.Configuration.Formatters.JsonFormatter 告诉我我们正在使用 JsonMediaTypeFormatter。 Web API 不是开箱即用的 JSON.NET 序列化程序吗?

这对 Web API 人来说是一个福音 - 至少在 ASP.NET MVC 中我们有一个一致的日期格式(尽管是专有的 - /Date (刻度数)/)通过 JavascriptSerializer

ES5 says that ISO 8601 format dates without a time zone should be treated as local(that interpretation has since been revised), but the ed. 6 draft 表示将它们视为 UTC。一些脚本引擎已经实现了 ed。 6,部分ES5,其余都不是。

编辑。 6(及更高版本)不符合 ISO 8601 规范。

底线是不要使用 Date.parse(或将字符串传递给 Date 构造函数),手动解析日期字符串。

对我们来说,这个问题的症结在于 DateTimeStyles.RoundtripKind 仅在您的 DateTime 属性设置 DateTime.DateTimeKind 时有效( 不同于 DateTimeKind.Unspecified - 默认 ) 或更好 - 使用 DateTimeOffset 其中 enforces use of the TimeZone specificity.

因为我们已经有了 DateTime class 属性,我们现在通过从 DateTimeZoneHandling.RoundtripKind 分配 JsonSerializerSettings.DateTimeZoneHandling 来解决这个问题(DateTime default) 到 Global.asax.cs 中的 DateTimeZoneHandling.Utc。这一更改实质上是将“Z”附加到 DateTime 的末尾 - 但是还有一个步骤可以将本地时间转换为 UTC。

第二步是通过分配 IsoDateTimeConverter.DateTimeStyles which JSON.NET JsonSerializer 来提供偏移量,将从 SerializerSettings.Converters 获取并自动从本地时间转换为 UTC - 很像开箱即用的 ASP.NET MVC 确实如此。

显然 - 还有其他选择,但这是适合我们的解决方案。

Global.asax.cs

protected void Application_Start() {
    GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc;
    GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new IsoDateTimeConverter() { DateTimeStyles = DateTimeStyles.AdjustToUniversal });
}

DateTimeStyles.AdjustToUniversalreason this works is because RoundtripKind honors DateTime's DateTimeKind - which is Unspecified by default. We want to explicitly convert this to UTC - which JavaScriptSerializer used to do for us out of the box for ASP.NET MVC. The regional offset is provided 将您的本地 DateTime 转换为 UTC。