当Date
使用下面的调用在 JavaScript 中初始化一个新对象时,我发现月份参数从零开始计数。
new Date(2010, 3, 1); // that's the 1st April 2010!
为什么月份参数从 0 开始?另一方面,月份参数(最后一个)是从 1 到 31 的数字。这样做有充分的理由吗?
当Date
使用下面的调用在 JavaScript 中初始化一个新对象时,我发现月份参数从零开始计数。
new Date(2010, 3, 1); // that's the 1st April 2010!
为什么月份参数从 0 开始?另一方面,月份参数(最后一个)是从 1 到 31 的数字。这样做有充分的理由吗?
这个问题的真正答案是它是从 复制的java.util.Date
,它也有这个怪癖。可以在twitter上找到 Brendan Eich 的证明,他是最初实现 JavaScript 的人:
https://twitter.com/BrendanEich/status/481939099138654209
https://twitter.com/BrendanEich/status/771006397886533632
Brendan 还指出 Netscape 的 Ken Smith 是从 Java 移植过来的。
https://twitter.com/BrendanEich/status/771006208949891072
这发生在 1995 年,当时 JDK 1.0 处于测试阶段。它于 1996 年推出。 1997 年,JDK 1.1 出现,弃用了 上的绝大多数功能java.util.Date
,将它们移至java.util.Calendar
,但即便如此,仍然有从零开始的月份。对此感到厌烦的开发人员创建了Joda-Time库,最终将java.time
包嵌入到 Java 8 (2014) 中。
简而言之,Java 花了 18 年的时间才获得正确设计的内置日期/时间 API,但 JavaScript 仍然停留在黑暗时代。我们确实有这样优秀的库力信通 Moment.js,日期FNS,JS-乔达,等等。但截至目前,除了Date
内置于该语言之外,别无他物。希望这会在不久的将来随着TC39 临时提案而改变。
这是编程世界中一个古老的(可能是不幸的,可能正在消亡)传统,请参阅旧标准(POSIX)localtime C 函数http://linux.die.net/man/3/localtime
除了一个月中的某一天之外的所有内容都是基于 0 的,请参阅此处以获取包括范围的完整列表:)
它实际上是基于 1 天的天数是这里的怪人......够奇怪了。为什么这样做?我不知道......但可能发生在他们被贴上膏药并决定分号是可选的同一次会议上。
2021 年真正的问题是:
如果
Date
从 JS 的第一天起就被打破了,为什么 26 年(如果从零开始数则是 25 年)它仍然在这里?
JS 有很多不好的部分/怪癖,最糟糕的是其中一些已经几十年没有被修复(有趣的事实:我们正在谈论Date
日期)。
但我们很幸运,看起来末日Date
已经临近了。
new Temporal.PlainDate(2020, 11, 26); // => 2020-11-26
从提案介绍:
Date
一直是 ECMAScript 中长期存在的痛点。这是对 的提议Temporal
,Object
作为顶级命名空间(如Math
)的全局变量,为 ECMAScript 语言带来了现代日期/时间 API。
正如文档中所报告的那样,它基于“我们检查过的常见用例”,并且针对不同类型的数据具有多种类型:
Plain
类型没有时区ZonedDateTime
类型有时区Absolute
, DateTime
, Date
, Time
, TimeZone
, ...您可以在可用文档和漂亮的食谱中阅读有关它们的更多信息。或者探索当前的问题以寻找开放的问题。
自21年3 月起,它处于第 3 阶段/草案(请参阅TC39 阶段参考)。请参阅 TC39 21 年 3 月的幻灯片。
现在它可以很快包含在 TypeScript 中,因为他们的政策是:
当新功能达到第 3 阶段时,它们就可以包含在 TypeScript 中了。
可能对于 Node 和主要浏览器,我们需要等待更多。
同时,您可以使用Temporal polyfill对其进行试验。
npm install --save proposal-temporal
// temporal-test.js
const { Temporal } = require('proposal-temporal');
// or as an ES module
// import { Temporal } from 'proposal-temporal/lib/index.mjs';
// 11 means November now!
const date = new Temporal.PlainDate(2020, 11, 26); // => 2020-11-26
const sameDate = Temporal.PlainDate.from(
{year: 2020, month: 11, day: 26}); // => 2020-11-26
一年总有 12 个月,因此早期的 C 实现可能使用索引为 0..11 的静态固定宽度数组。