如何处理双夏令时浏览器兼容性问题
How to deal with double daylight savings time browser compatibility issues
我遇到的问题是 Chrome 和 IE/Edge 给出不同的结果,将某些 JavaScript 日期时间序列化为 JSON - 例如英国的 1945 年夏天.
我有一个 JavaScript 对象,其中包含通过日历组件设置的日期类型,该日历组件将时间设置为当地时间午夜。该对象通过 JSON.stringify 序列化,后者又使用 Date.toJSON,后者又使用 Date.toISOString.
如果我的本地日期时间是 1977 年 5 月 1 日,在我的英国语言环境中,这将序列化为 "1977-04-30T23:00:00.000Z",即 UTC 晚上 11 点1977 年 4 月 30 日。这很好,但是如果我从本地 1945 年 5 月 1 日开始,我最终会使用 Chrome 与 IE/Edge 得到不同的结果。 Chrome 正确地给我 "1945-04-30T22:00:00.000Z"。这是晚上 10 点而不是晚上 11 点的原因是因为英国在二战期间实行双夏令时。
IE/Edge 然而减去一个小时意味着 JSON UTC 日期时间字符串超出一个小时。
这对我来说意味着 我不能相信传回服务器的 JSON 序列化数据 除非我知道它来自哪个浏览器。
我正在考虑覆盖 Data.prototype.toJSON 以将序列化更改为基于本地时间的内容,但包括时区偏移,例如“1945-05-01T00:00:00.000+0200”。至少那时我知道用户的实际意图。然而,这似乎有点极端,想知道我是否遗漏了什么。 JSON.stringify 是将要发送到服务器的数据序列化的常用方法,但整个机制似乎存在缺陷。
的确,历史时区信息因实施而异。您在不同的浏览器中看到不同的结果,因为 Windows 不跟踪英国的历史变化。 IE 和经典 Edge(不是 Chromium 版本)使用 Windows 时区数据进行这些转换。 Chrome 提供了正确的结果,因为它附带了来自 IANA time zone database (via ICU) 的自己的时区数据。
对于您描述的场景,用户从选择器中选择日期(大概是出生日期或类似的日期),处理此问题的最佳方法是 而不是 .而不是使用 Date
对象(这不是真正的 date 但实际上是 timestamp),保留原始年、月, 以及用户选择的日期。您可以为每个值或您自己创建的对象或数组保留单独的值,或者更常见的是,您可以保留 ISO 8601 格式的仅限日期的字符串,例如 "1945-04-30"
.
确实,如果您使用 <input type="date"/>
HTML5 元素,其 value
将是该格式的字符串而不是 Date
对象。还有其他日期选择器会 return 该字符串,但如果您坚持使用一个 return 是 Date
对象的日期选择器,那么只需根据 [=16] 的结果构造您自己的字符串=]、.getMonth()
和 .getDate()
(适当填充零)。
然后您可以在 JSON 结果中传递该字符串,而不必担心任何一方的任何转换 to/from UTC,也不必担心历史时区数据是否存在。
作为替代方案,如果您坚持使用 Date
对象,那么一些人使用的方法是在序列化之前将时间显式设置为中午时间(例如中午 12 点) .即使时间转换为 to/from UTC.
,这也会使年月日组件保持在相同的原始日历日期
我遇到的问题是 Chrome 和 IE/Edge 给出不同的结果,将某些 JavaScript 日期时间序列化为 JSON - 例如英国的 1945 年夏天.
我有一个 JavaScript 对象,其中包含通过日历组件设置的日期类型,该日历组件将时间设置为当地时间午夜。该对象通过 JSON.stringify 序列化,后者又使用 Date.toJSON,后者又使用 Date.toISOString.
如果我的本地日期时间是 1977 年 5 月 1 日,在我的英国语言环境中,这将序列化为 "1977-04-30T23:00:00.000Z",即 UTC 晚上 11 点1977 年 4 月 30 日。这很好,但是如果我从本地 1945 年 5 月 1 日开始,我最终会使用 Chrome 与 IE/Edge 得到不同的结果。 Chrome 正确地给我 "1945-04-30T22:00:00.000Z"。这是晚上 10 点而不是晚上 11 点的原因是因为英国在二战期间实行双夏令时。
IE/Edge 然而减去一个小时意味着 JSON UTC 日期时间字符串超出一个小时。
这对我来说意味着 我不能相信传回服务器的 JSON 序列化数据 除非我知道它来自哪个浏览器。
我正在考虑覆盖 Data.prototype.toJSON 以将序列化更改为基于本地时间的内容,但包括时区偏移,例如“1945-05-01T00:00:00.000+0200”。至少那时我知道用户的实际意图。然而,这似乎有点极端,想知道我是否遗漏了什么。 JSON.stringify 是将要发送到服务器的数据序列化的常用方法,但整个机制似乎存在缺陷。
的确,历史时区信息因实施而异。您在不同的浏览器中看到不同的结果,因为 Windows 不跟踪英国的历史变化。 IE 和经典 Edge(不是 Chromium 版本)使用 Windows 时区数据进行这些转换。 Chrome 提供了正确的结果,因为它附带了来自 IANA time zone database (via ICU) 的自己的时区数据。
对于您描述的场景,用户从选择器中选择日期(大概是出生日期或类似的日期),处理此问题的最佳方法是 而不是 .而不是使用 Date
对象(这不是真正的 date 但实际上是 timestamp),保留原始年、月, 以及用户选择的日期。您可以为每个值或您自己创建的对象或数组保留单独的值,或者更常见的是,您可以保留 ISO 8601 格式的仅限日期的字符串,例如 "1945-04-30"
.
确实,如果您使用 <input type="date"/>
HTML5 元素,其 value
将是该格式的字符串而不是 Date
对象。还有其他日期选择器会 return 该字符串,但如果您坚持使用一个 return 是 Date
对象的日期选择器,那么只需根据 [=16] 的结果构造您自己的字符串=]、.getMonth()
和 .getDate()
(适当填充零)。
然后您可以在 JSON 结果中传递该字符串,而不必担心任何一方的任何转换 to/from UTC,也不必担心历史时区数据是否存在。
作为替代方案,如果您坚持使用 Date
对象,那么一些人使用的方法是在序列化之前将时间显式设置为中午时间(例如中午 12 点) .即使时间转换为 to/from UTC.