moment.js时区不一致

时间:2016-06-17 06:00:35

标签: javascript date momentjs isodate

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

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

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

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

May 2016

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

1 个答案:

答案 0 :(得分:4)

对你的问题的简短回答是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,因为ISOString始终返回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,所以全球时间轴上的点比我传递的字符串提前五个小时。

您所看到的行为 - 将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,这是当下几个竞争对手之一,或者自己手动解析字符串。所有这些都是更好的选择。