当使用下面的调用在JavaScript中初始化一个新的Date对象时,我发现month参数从0开始计数。

new Date(2010, 3, 1);  // that's the 1st April 2010!

为什么month参数从0开始?另一方面,月份的日期参数(最后一个)是1到31之间的数字。有什么好的理由吗?


当前回答

我知道这不是最初问题的答案,但我只是想向你们展示我对这个问题的首选解决方案,我似乎从来没有记住过,因为它不时地出现。

小函数zerofill可以在需要的地方填充零,月份只是加了+1:

function zerofill(i) {
    return (i < 10 ? '0' : '') + i;
}

function getDateString() {
    const date = new Date();
    const year = date.getFullYear();
    const month = zerofill(date.getMonth()+1);
    const day = zerofill(date.getDate());
    return year + '-' + month + '-' + day;
}

但是,是的,Date有一个相当不直观的API,当我读Brendan Eich的Twitter时,我笑了。

其他回答

在java中也是这样的。可能是为了将int转换为字符串(0 - jan,, 1-feb),他们这样编码..因为它们可能有一个字符串数组(索引从0开始)的月份名称和这些月份数字,如果他们从0开始,它将更容易映射到月份字符串。

一年总是有12个月,所以早期的C实现可能使用一个静态的固定宽度数组,索引为0..11。

2023年真正的问题是:

如果Date从JS的第一天就被打破了,为什么28年后(如果你从零开始算的话是27年)它还在这里?

JS有很多不好的部分/怪癖,最糟糕的是其中一些在几十年里都没有被修复(有趣的事实:我们谈论的是Date日期)。

但我们很幸运,看来《约会》即将结束。

扰流板

new Temporal.PlainDate(2020, 11, 26); // => 2020-11-26

时间(建议)

提案介绍如下:

日期一直是ECMAScript中一个长期存在的痛点。这是一个针对Temporal的建议,这是一个充当顶级名称空间的全局对象(如Math),它为ECMAScript语言带来了一个现代的日期/时间API。

正如文档中报告的那样,它基于“我们检查过的常见用例”,并为不同类型的数据提供了多种类型:

普通类型没有时区 zoneeddatetime类型有一个时区 大多数类型都有日历 许多有用的类型:Absolute, DateTime, Date, Time, TimeZone,…

这是一个概述各种时态类型及其关系的模式

您可以在可用的文档和漂亮的烹饪书中阅读更多关于它们的信息。或者探索当前的问题。

颞叶何时可用

自21年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

这个问题的真正答案是从java.util复制的。日期,也有这个怪癖。在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上的绝大多数函数。日期,将它们移到java.util。日历,但即便如此,仍然有零位月。开发人员受够了这一点,创建了Joda-Time库,最终导致了java。Java 8(2014)内置的时间包。

简而言之,Java花了18年的时间才得到一个正确设计的内置日期/时间API,但JavaScript仍然停留在黑暗时代。我们确实有优秀的库,如Luxon Moment.js、date-fns、js-joda等。但是到目前为止,该语言只内置了Date。希望这种情况在不久的将来会随着TC39 Temporal提案而改变。

我知道这不是最初问题的答案,但我只是想向你们展示我对这个问题的首选解决方案,我似乎从来没有记住过,因为它不时地出现。

小函数zerofill可以在需要的地方填充零,月份只是加了+1:

function zerofill(i) {
    return (i < 10 ? '0' : '') + i;
}

function getDateString() {
    const date = new Date();
    const year = date.getFullYear();
    const month = zerofill(date.getMonth()+1);
    const day = zerofill(date.getDate());
    return year + '-' + month + '-' + day;
}

但是,是的,Date有一个相当不直观的API,当我读Brendan Eich的Twitter时,我笑了。