moment.js时区不一致 [英] moment.js timezone inconsistency

查看:762
本文介绍了moment.js时区不一致的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am formatting a given date using momentjs. The following behaves differently in different timezones:

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

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

It gives me May 2016 in timezone of America/Denver and June 2016 in Asia/Karachi. I tested by changing the browser timezone to different timezones. It should be June 2016 in both.

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

When i change the format in new Date() to use slashes instead of hyphens like below, it gives me correct result in both timezones i.e. May 2016.

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

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

Both seem to be valid ISO strings, what would cause this inconsistency?

推荐答案

您的问题的简短答案是,javascript日期解析器对任何人都无效.相反,您应该只使用Moment的解析器来获取所需的结果.以有意义的方式解析日期大约是该时刻存在的原因的50%. 如果您消除了日期调用并使用Moment解析日期,则将在任何浏览器中看到以下代码将在2016年6月生成,因为如果使用Moment的默认构造函数,则您的字符串将被解释为本地时间:

The short answer to your question is that parser for javascript date doesn't work in a way that makes sense to anybody. Instead, you should just use Moment's parser to get the result you want. Parsing dates in a way that makes sense is about 50% of the reason that moment exists. If you eliminate the date call and use Moment to parse your date, you will observe that the following code will result in June 2016 in any browser, because your string will be interpreted as local time if you are using Moment's default constructor:

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

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

If you wanted to use slashes instead, it would be:

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

请参阅矩分析"指南,以获取有关矩如何使用其不同的构造函数方法解释时间的更多信息.

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

The long answer is that when you pass a string in ISO8601 format that is date only to the JavaScript date constructor, it will interpret that string as UTC. Because Denver is UTC -6 on daylight time, and Karachi is UTC +5 all the time, when moment then displays that timestamp as local time you see the result that you do. You can observe the following:

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

请注意,上述时间戳中的"Z"表示它是UTC,因为toISOString始终返回UTC时间戳.该时间戳记是卡拉奇的六月,因为卡拉奇领先于UTC,而五月的丹佛是因为丹佛落后于UTC.

Note that the 'Z' in the above timestamp indicates that it is UTC, as toISOString always returns a UTC timestamp. That timestamp is June in Karachi because Karachi is ahead of UTC, while May in Denver because Denver is behind UTC.

也要注意这一点:

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

如果我在字符串上放置时间,则将其解释为本地时间.由于我的时区是1月1日的UTC-5,因此全球时间轴上的时间要比我传递的字符串早五小时.

If I put a time on my string, it is interpreted as local time. Because my timezone was UTC-5 on January 1, the point on the global timeline is appropriately five hours ahead of the string I passed.

您所看到的行为-将2016-06-01解释为UTC,但将2016-06-01T00:00解释为本地,实际上是为了解决跨浏览器的技术问题. 在ECMA 262规范的第7版中它已成为标准行为,因此可以期待为了不改变. 也请参见此链接.

The behavior you are seeing - interpreting 2016-06-01 as UTC, but 2016-06-01T00:00 as local, is actually an effort to accommodate technical debt across browsers. It has been made the standard behavior in the 7th edition of the ECMA 262 specification, so expect for that not to change. See this link as well.

或者,当您使用斜杠(2016/06/01)时,您使用的JS实现会选择将该格式解释为本地时间,因为它不符合ECMA标准中的任何格式.这不是有效的ISO8601格式.请务必注意,此行为是特定于实现的,并且会因浏览器/环境而异. ECMA标准未定义用于解析该日期格式的行为. 其他浏览器可能会以其他方式解析此字符串.

Alternately, when you use the slashes (2016/06/01) the JS implementation that you are using is choosing to interpret that format as local time, as it does not conform to any of the formats in the ECMA standard. This is NOT a valid ISO8601 format. It is very important to note that this behavior is implementation specific, and will vary across browsers/environments. The ECMA standard does not define a behavior for parsing that date format. Other browsers may parse this string in other ways.

作为一般建议,请勿使用JavaScript日期解析器.它行不通.您可以使用Moment.js,它是当下的几个竞争对手之一,也可以自己手动解析字符串.所有这些都是更好的选择.

As general advice, don't use the JavaScript date parser. It doesn't work right. You can use Moment.js, one of moment's several competitors, or manually parse strings yourself. All of these are better options.

这篇关于moment.js时区不一致的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆