新date(“2017-01-01”)和新date(“2017-1-1”)之间有什么区别?
我在chrome控制台inputnew Date("2017-01-01")
,输出显示其小时为8,但是new Date("2017-01-1")
和new Date("2017-1-01")
显示他们的小时都是0,那么new Date(dateString)
如何parsing呢?
new Date("2017-01-01") // Sun Jan 01 2017 08:00:00 GMT+0800 (中国标准时间)* new Date("2017-01-1") // Sun Jan 01 2017 00:00:00 GMT+0800 (中国标准时间)* new Date("2017-1-1") // Sun Jan 01 2017 00:00:00 GMT+0800 (中国标准时间)* new Date("2017-1-01") // Sun Jan 01 2017 00:00:00 GMT+0800 (中国标准时间)*
“2017-01-01”遵循ISO标准 ES5date时间string格式(简化ISO 8601扩展格式) ,因此是UTC时间,即中国上午8点。 所有其他string在Chrome 1中被parsing为本地时间。
1 Chromium中的相关源代码: https : //cs.chromium.org/chromium/src/v8/src/dateparser-inl.h? type = cs & l = 16
Chromium中的date分析遵循标准的ES5规则以及这些额外的规则:
- 第一个数字之前的任何无法识别的单词都将被忽略。
- 括号文字被忽略。
- 一个无符号的数字后跟
:
是一个时间值,并被添加到TimeComposer
。 一个数字后跟::
增加了第二个零。 一个数字紧跟着.
也是一个时间,必须以毫秒为单位。 任何其他号码是一个date组件,并添加到DayComposer
。 - 一个月份名称(或者真的:任何具有与三个月份相同的前三个字母的单词)在
Day
composer中被logging为指定的月份。 - 一个可识别为时区的单词被logging为
(+|-)(hhmm|hh:)
。 - 旧版date不允许在读取数字(在第一个数字之前,允许任何垃圾
)
之后使用额外的符号(+
或-
)或不匹配)。 - 任何满足ES5规则和上述规则的string都将使用ES5规则进行分析。 这意味着
"1970-01-01"
将在UTC时区不在本地时区。
那是什么意思?
首先请注意,“2017-01-01”是以UTC时间进行分析的,因为它是“date”string而不是“date时间”string,它与“date”string的ES5定义相匹配。 如果附加时间,那么它将遵循ISO标准并在当地时间进行parsing。
例子:
-
2017-01-01
– 2017年1月1日,UTC时间 -
2017-01-01T00:00
– 2017年1月1日在当地时间 -
2017-1-1
– 2017年1月1日在当地时间 -
2017-(hello)01-01
– 2017年1月1日在当地时间 -
may 2017-01-01
– 2017年5月1日在当地时间 -
mayoooo 2017-01-01
– 2017年5月1日在当地时间 -
"jan2017feb-mar01apr-may01jun"
– 2017年6月1日在当地时间
新date(“2017-01-01”)和新date(“2017-1-1”)之间的差异
new Date("2017-01-01")
是在规范(更多下面)。 new Date("2017-1-1")
不是,所以JavaScript引擎想要应用的任何“…特定于实现的启发式或特定于实现的date格式”都会落后。 例如,你不能保证如何(或是否)它将成功parsing,如果是的话,是否将被parsing为UTC或本地时间。
虽然new Date("2017-01-01")
是规范的,可惜的是浏览器应该做什么,它已经成为一个移动的目标,因为它没有时区指标:
- 在ES5 (2009年12月)中,没有时区指示符的string应该被parsing为UTC。 但是这与date/时间格式所基于的ISO-8601标准不一致,即没有时区指示符的string应该是本地时间,而不是UTC。 所以在ES5中,
new Date("2017-01-01")
在UTC中被parsing。 - 在ES2015 (又名ES6,2015年6月)中,没有时区指示符的string应该是本地时间,而不是UTC,如ISO-8601。 所以在ES2015中,
new Date("2017-01-01")
被parsing为当地时间。 - 但是 , 在ES2016 (2016年6月)中又一次发生了变化,因为浏览器一直在parsing仅有date的表单,而且这些表单在UTC中是多年的。 因此,从ES2016开始, 仅使用date格式(如
"2017-01-01"
)以UTC格式parsing,但在当地时间parsingdate/时间格式(如"2017-01-01T00:00:00"
)。
可悲的是,并非所有的JavaScript引擎目前都实现了这个规范。 Chrome(截至撰写本文,为v56)以UTC分析date/时间表格,即使它们应该是本地时间(IE9也是如此)。 但是,Chrome,Firefox和IE11(我没有IE10或Edge)都能正确处理date格式(如UTC)。 IE8完全不实现ISO-8601格式(在ES5规范发布之前已经发布)。
当parsingdate时,JavaScript将ISOdate解释为UTC时间和其他格式为本地时间。
正如MDN文章所言,
如果string仅为ISO 8601date,则UTC时区用于解释参数。
给定一个“2014年3月7日”的datestring,parse()假定一个本地时区, 但是给定一个ISO格式,例如“2014-03-07”,它将假设一个UTC时区(ES5和ECMAScript 2015) 。 因此,使用这些string生成的Date对象可能表示不同时刻,具体取决于支持的ECMAScript版本,除非系统设置为UTC本地时区。 这意味着两个显示等同的datestring可能会导致两个不同的值,具体取决于正在转换的string的格式。
// 2017-03-28 is interpreted as UTC time, // shown as 2017-03-28 00:00:00 in UTC timezone, // shown as 2017-03-28 06:00:00 in my timezone: console.log("ISO dates:"); var isoDates = [new Date("2017-03-28")]; for (var dt of isoDates) { console.log(dt.toUTCString() + " / " + dt.toLocaleString()); } // Other formats are interpreted as local time, // shown as 2017-03-27 18:00:00 in my timezone, // shown 2017-03-28 00:00:00 in my timezone: console.log("Other formats:"); var otherDates = [new Date("2017-3-28"), new Date("March 28, 2017"), new Date("2017/03/28")]; for (var dt of otherDates) { console.log(dt.toUTCString() + " / " + dt.toLocaleString()); }
这种格式是国际标准(ISO格式)
new Date("2017-01-01")
这保证了所有浏览器的相同输出。
但是,其他格式可能会根据浏览器而改变,因为它们没有很好的定义。
正如你可以看到这种格式
new Date("2017-1-1")
在Chrome中成功parsing,但在IE 11中出错