译者 | 平川
策划 | Tina
在搭建这个网站的过程中,我遇到了以下奇怪的事情:
console.log(new Date('2025/05/28').toDateString()); // Wed May 28 2025
console.log(new Date('2025-05-28').toDateString()); // Tue May 27 2025
// 去掉月份的 0
console.log(new Date('2025-5-28').toDateString()); // Wed May 28 2025
你在你的机器上可能会得到不同的结果。
发生了什么?
在 JavaScript 中,Date
代表一个时间点(即自纪元以来的毫秒数)。把完整的日期字符串打印出来就更明显了:
const date = new Date('2025/05/28');
console.log(date); // Wed May 28 2025 00:00:00 GMT-0700 (Pacific Daylight Time)
console.log(date.toDateString()); // Wed May 28 2025
在这种情况下,传入的日期字符串被解释成我所在时区的一个时间戳。toDateString() 的操作也是相对于本地时间,所以我们得到了相同的月份日期。
和'2025-05-28'的区别在于解析行为。这个字符串被解释为 UTC,所以最终得到了不同的时间点:
const date = new Date('2025-05-28');
console.log(date); // Tue May 27 2025 17:00:00 GMT-0700 (Pacific Daylight Time)
console.log(date.toDateString()); // Tue May 27 2025
为什么会有这种差异?
浏览器日期解析的冒险
在翻阅 Chrome/Firefox/Safari 的代码和提交历史后,我重建了一个时间线:
console.log(new Date('2025-05-28')); // Tue May 27 2025 17:00:00 GMT-0700 (Pacific Daylight Time)
console.log(new Date('2025-05-28T00:00')); // Wed May 28 2025 00:00:00 GMT-0700 (Pacific Daylight Time)
这种行为一直维持到今天,除了像'2025-05-28'这样的有效 ISO 日期字符串之外,Date 构造函数会将接收到的每个可能的字符串都作为本地时间。
有趣的是,从 2009 年发布到 2020 年初,尽管被设计为标准格式,主要浏览器在处理缺少偏移的情况时从未一致过。与此同时,在解析'2025-05-28T00:00'时,Chrome 经历了多次反复(local → UTC → local → UTC → local )。而这一切只是为了解决 Firefox 2009 年的行为问题,在我看来,它是所有行为中最不直观的。
JavaScript Temporal
JavaScript Temporal 即将面世:这是一组新的日期和时间 API,旨在取代 Date 对象。
整个日期解析问题最初是源于时区歧义,但在很多情况下,我们希望将仅日期字符串视为纯日期。例如,当我说今年的圣诞节是 2025-12-25 时,我指的并不是 2025-12-25T00:00:00.000Z 这个时间。
Date 只能表示后者,而 Temporal 则提供了 纯日期(即不含时区的日期)选项。 '2025-12-25'
就是 2025-12-25,完全避免了解析歧义的问题。
但如果我们真想把一个仅日期的字符串解析成一个时间戳呢?如果字符串本身没有时区,Temporal 会选择哪个时区?
答案是:这是一个严重错误;必须提供 偏移 或 时区标识符。不要重复犯错了。
被诅咒的区域
在阅读浏览器日期解析源代码之前,我从未意识到它可以如此宽容。
下面是 Chrome/Firefox 浏览器的一个有趣示例:你能找出为什么这个日期字符串被解析为五月吗?
const date = 'it is wednesday, my dudes. 2025, April, maybe...28(?)';
console.log(new Date(date)); // Wed May 28 2025 00:00:00 GMT-0700 (Pacific Daylight Time)
原文链接:
https://brandondong.github.io/blog/javascript_dates
声明:本文为 InfoQ 翻译,未经许可禁止转载。