【问题标题】:moment.js timezone inconsistencymoment.js 时区不一致
【发布时间】:2016-06-17 06:00:35
【问题描述】:

我正在使用 momentjs 格式化给定的日期。以下在不同时区的行为不同:

moment(new Date("2016" + "-" + "06" + "-01").toISOString()).format('MMMM YYYY')

它在美国/丹佛时区给我May 2016,在亚洲/卡拉奇给我June 2016。我通过将浏览器时区更改为不同的时区进行了测试。两者都应该是June 2016

当我将new Date() 中的格式更改为使用斜杠而不是如下连字符时,它会在两个时区(即May 2016)中给出正确的结果。

moment(new Date("2016" + "/" + "06" + "/01").toISOString()).format('MMMM YYYY')

两者似乎都是有效的 ISO 字符串,什么会导致这种不一致?

【问题讨论】:

  • new Date("2016" + "-" + "06" + "-01").toISOString() 产生2016-06-01T00:00:00Z

标签: javascript date momentjs isodate


【解决方案1】:

对您的问题的简短回答是,javascript 日期解析器无法以对任何人都有意义的方式工作。相反,您应该只使用 Moment 的解析器来获得您想要的结果。以一种有意义的方式解析日期是那个时刻存在的大约 50% 的原因。 如果您消除日期调用并使用 Moment 解析您的日期,您将观察到以下代码将在任何浏览器中生成 2016 年 6 月,因为如果您使用 Moment 的默认构造函数,您的字符串将被解释为本地时间:

moment('2016-06-01').format()

如果您想改用斜线,那就是:

moment('2016/06/01', 'YYYY/MM/DD').format()

See moment's parsing guide for more information about how moment interprets times with it's different constructor methods.

长答案是,当您将 ISO8601 格式的字符串传递给 JavaScript 日期构造函数时,它将将该字符串解释为 UTC。因为丹佛在夏令时是 UTC -6,而卡拉奇一直是 UTC +5,所以当时刻将该时间戳显示为本地时间时,您会看到您所做的结果。您可以观察以下内容:

var a = new Date('2016-06-01'); 
a.toISOString();
"2016-06-01T00:00:00.000Z"

请注意,上面时间戳中的“Z”表示它是 UTC,因为 toISOString 总是返回一个 UTC 时间戳。该时间戳是卡拉奇的 6 月,因为卡拉奇领先于 UTC,而丹佛的时间戳是 5 月,因为丹佛落后于 UTC。

也要注意这一点:

var a = new Date('2016-06-01T00:00'); 
a.toISOString();
"2016-06-01T05:00:00.000Z"

如果我在字符串上加上时间,它会被解释为当地时间。因为我的时区是 1 月 1 日的 UTC-5,所以全球时间线上的点比我传递的字符串提前了 5 小时。

您所看到的行为 - 将 2016-06-01 解释为 UTC,但将 2016-06-01T00:00 解释为本地,实际上是为了适应跨浏览器的技术债务。 It has been made the standard behavior in the 7th edition of the ECMA 262 specification,所以希望这不会改变。 See this link as well.

或者,当您使用斜杠 (2016/06/01) 时,您正在使用的 JS 实现选择将该格式解释为本地时间,因为它不符合 ECMA 标准中的任何格式。这不是有效的 ISO8601 格式。请务必注意,此行为是特定于实现的,并且会因浏览器/环境而异。 The ECMA standard does not define a behavior for parsing that date format.其他浏览器可能会以其他方式解析这个字符串。

一般建议不要使用 JavaScript 日期解析器。它不能正常工作。您可以使用 Moment.js,Moment 的几个竞争对手之一,或者自己手动解析字符串。所有这些都是更好的选择。

【讨论】:

  • 太好了。唯一的问题是我在使用非 ISO 格式和矩解析器时收到的弃用警告。
  • 我之前使用 Date 构造函数来避免该警告
  • 指定日期格式,就像我在第二个示例中所做的那样。您收到弃用警告的原因是这个问题。它正在回退到日期解析器并且日期解析器不起作用
  • "…javascript 日期对任何人都不起作用"。由于 moment.js 完全依赖内置的 Date 对象作为其功能的基础,因此您可能指的是解析字符串的规范,而不是对象本身。
  • "...将 2016-06-01 解释为 UTC,但将 2016-06-01T00:00 解释为本地,实际上是所有主要浏览器中都存在的错误。因为它存在于所有浏览器,它已成为第 7 版 ECMA 262 规范中的标准行为。“我不确定这是对参考的准确解释。
猜你喜欢
  • 2017-07-30
  • 2023-03-02
  • 1970-01-01
  • 1970-01-01
  • 2021-11-16
  • 1970-01-01
  • 1970-01-01
  • 2015-03-13
  • 2015-03-21
相关资源
最近更新 更多