对您的问题的简短回答是,javascript date 的解析器无法以对任何人都有意义的方式工作。相反,您应该只使用 Moment 的解析器来获得您想要的结果。以一种有意义的方式解析日期是那个时刻存在的大约 50% 的原因。如果您消除日期调用并使用 Moment 解析您的日期,您将观察到以下代码将在任何浏览器中生成 2016 年 6 月,因为如果您使用 Moment 的默认构造函数,您的字符串将被解释为本地时间:
moment('2016-06-01').format()
如果你想改用斜杠,它会是:
moment('2016/06/01', 'YYYY/MM/DD').format()
有关 moment 如何使用不同的构造函数方法解释时间的更多信息,请参阅 moment 的解析指南。
长答案是,当您将 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 解释为本地,实际上是为了适应跨浏览器的技术债务。它已成为 ECMA 262 规范第 7 版中的标准行为,因此希望它不会改变。请参阅此链接。
或者,当您使用斜杠 (2016/06/01) 时,您正在使用的 JS 实现选择将该格式解释为本地时间,因为它不符合 ECMA 标准中的任何格式。这不是有效的 ISO8601 格式。请务必注意,此行为是特定于实现的,并且会因浏览器/环境而异。ECMA 标准没有定义解析该日期格式的行为。其他浏览器可能会以其他方式解析此字符串。
作为一般建议,不要使用 JavaScript 日期解析器。它不能正常工作。您可以使用 Moment.js,Moment 的几个竞争对手之一,或者自己手动解析字符串。所有这些都是更好的选择。