你尚未登录,仅允许查看本站部分内容。请登录使用邀请码注册
season.chen

夏令时间:可能被你忽略的一个坑 6个回复 专栏 @ Javascript

season.chen 发布于 10 月前

前端的童鞋,请你在你的浏览器的console里执行这么一句: new Date(1987,3,12),然后来看看结果。

  • Chrome: Sun Apr 12 1987 01:00:00 GMT+0900 (CDT)
  • Firefox: Date {Sat Apr 11 1987 23:00:00 GMT+0800 (CST)}

发现没有,两个不一样?chrome里多了一个小时,Firefox里少了一个小时。什么鬼???

让咱们先来看看夏令时间是咋回事

夏时制,夏时令(Daylight Saving Time:DST),又称“日光节约时制”和“夏令时间”,是一种为节约能源而人为规定地方时间的制度,在这一制度实行期间所采用的统一时间称为“夏令时间”。一般在天亮早的夏季人为将时间提前一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电。各个采纳夏时制的国家具体规定不同。目前全世界有近110个国家每年要实行夏令时。

1986年至1991年,中华人民共和国在全国范围实行了六年夏令时,每年从4月中旬的第一个星期日2时整(北京时间)到9月中旬第一个星期日的凌晨2时整(北京夏令时)。除1986年因是实行夏令时的第一年,从5月4日开始到9月14日结束外,其它年份均按规定的时段施行。夏令时实施期间,将时间调快一小时。1992年4月5日后不再实行。

这么看来,1987-04-12 这一天刚好在中国执行夏令时间的范围内。

寻根问底

再在Firefox中执行这么一句:

new Date(1987,3,11,23,0,0,0).getTime() - new Date(1987,3,12,1,0,0,0).getTime() 结果为-3600000,刚好等于 60 * 60 * 1000,也就是一小时,不应该是相差两小时的么?

原因是:浏览器的new Date默认会解析出本地时间,而在中国,因为从1987-4-11的一天结束之后,本来应该是1987-4-12日00:00:00的,但是刚好这一天开始夏令时,所以会将时钟拨快一小时,变成1987-04-12 01:00:00

也就是说,再计算本地时间的时候,1987-04-11 23:00:00 再过3600000毫秒,就变成1987-04-12 01:00:00

也就是说,1987-4-12 00:00:00在中国的本地时间中是不存在的。

ECMASCRIPT 规范对于本地时间不存在时的处理

moment.js 的作者给我这么一句话:

This is actually standard browser behavior in compliance with the ECMA standard. China did a DST transition at midnight on April 12 1987. This means that the date and time in question - 1987-04-12T00:00.00 - does not exist. Given an ambiguous time, the ECMA standard specifies that the time should be shifted by the amount of the transition, to result in a time that actually exists, but it does not specify in which direction. In this case, Firefox is shifting it back by one hour.

也就是说,解析本地时间的时候,如果不存在的时间浏览器会给一个模糊的时间,并且带一个便宜,chrome往后调了一小时,Firefox往前调了一小时

那么问题来了

在实行夏令时间的阶段,一年中有一小时不存在,而另一个小时会出现两次。

var date = new Date(1987,3,12,0,0,0);
date.setHours(0);
console.log(date)

Firefox回退了一天,chrome前进了一小时。

实际中遇到的问题

最头疼的就是日历插件了,现在好多日历插件都是使用本地时间计算的,选择后传给你一个date对象,你根据Date解析成字符串,却发现这一天怎么都选择不了。

有些日历插件在Firefox(mac)上'1987-04-12'这一天显示不出来。。

或者给你一个字符串'1987-04-12', 你解析出毫秒传给后台,两个浏览器解析的并不同,莫名其妙少一天。。。

或者后台没有使用夏令时间,传给你一个时间戳,某些浏览器解析出来后少了一天。。。

解决

现在有些日历插件都是使用UTC时间的,所以不会出现这些问题,但是仅限于前后的传值是通过'2013-11-11'这种format格式传,而不是通过时间戳传。

登录后回复,如无账号,请使用邀请码注册