为什么在JavaScript的Date构造函数中月份参数的范围是0到11?

Agn*_*ian 105 javascript datetime date

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

new Date(2010, 3, 1);  // that's the 1st April 2010!
Run Code Online (Sandbox Code Playgroud)

为什么月份参数从0开始?另一方面,月份参数(最后一个)是从1到31的数字.这有充分的理由吗?

Mat*_*int 82

这个问题的真正答案是,它是复制而来的java.util.Date,也有这个怪癖.证明可以在Twitter上找到Brendan Eich--最初实现JavaScript的人(包括Date对象):

https://twitter.com/BrendanEich/status/481939099138654209

第一条推文

https://twitter.com/BrendanEich/status/771006397886533632

第二条推文

这发生在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,date -fnsjs-joda.但截至目前,只有Date内置于该语言.希望这会在不久的将来发生变化.

  • 啊......很好的旧演示驱动开发方法. (18认同)
  • @Yassir - 这项工作正在进行中。https://tc39.es/proposal-temporal/docs/ (4认同)

leo*_*loy 48

这是编程世界中一个古老的(可能是不幸的,可能是垂死的)传统,请参阅旧标准(POSIX)本地时间 C函数http://linux.die.net/man/3/localtime

  • JS`Date`对象是从Java 1.0移植的,这就是原因.继承它的所有缺陷...... http://stackoverflow.com/questions/344380/why-is-january-month-0-in-java-calendar (14认同)
  • 是 2019 年,我正在解决与此行为相关的问题,因此只要 Angular 等框架和 javascript 等语言不反对这种情况,它仍然会发生 - 请在 2025 年及以后随意发表评论;-) (3认同)
  • 这种传统总是让我花时间调试日期问题……想知道这种传统造成了多少工作时间的浪费。 (3认同)
  • 你是对的,传统通常是完全不一致的,而且常常是不合理的,我真的希望这种“坏”的传统真的正在消亡…… (2认同)
  • 它*永远*不会改变。有大量令人难以理解的现有代码假定了这种行为。(我的意思是,在 JavaScript 中。) (2认同)

Nic*_*ver 28

除了当月的所有日期都是0基础,请参阅此处查看完整列表,包括范围 :)

这实际上是基于1天的日子,这里是古怪的......奇怪的是.为什么要这样做?我不知道......但可能发生了相同的会议,他们得到了贴纸,并决定分号是可选的.

  • 他们为什么年份不是从0开始的? (4认同)

lif*_*foo 6

2021 年真正的问题是:

如果Date从 JS 的第一天起就被破坏了,为什么 26 年(如果从零开始数则是 25 年)它仍然在这里?

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

但我们很幸运,看起来末日Date已经临近了。

剧透

new Temporal.PlainDate(2020, 11, 26); // => 2020-11-26
Run Code Online (Sandbox Code Playgroud)

时间(提案)

从提案介绍:

Date一直是 ECMAScript 中长期存在的痛点。这是一个提议Temporal,它是一个Object作为顶级命名空间(如Math)的全局变量,它为 ECMAScript 语言带来了现代日期/时间 API。

正如文档中所报告的那样,它基于“我们检查过的常见用例”,并且针对不同类型的数据具有多种类型:

  • Plain 类型没有时区
  • ZonedDateTime 类型有时区
  • 大多数类型都有日历
  • 许多有用的类型:Absolute, DateTime, Date, Time, TimeZone, ...

这是一个概述Temporal各种类型及其关系的模式 JS 临时提案类型

您可以在可用文档和漂亮的食谱中阅读有关它们的更多信息。或者探索当前的问题以寻找开放的问题。

Temporal 何时可用

213 月以来,它处于第 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
Run Code Online (Sandbox Code Playgroud)


Jon*_*ian 5

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

  • Java 日期/日历实现保持对某些日历的额外月份的支持。http://en.wikipedia.org/wiki/Undecimber (3认同)

Chr*_*lin 5

我知道这并不是对原始问题的真正答案,但我只是想向您展示我对这个问题的首选解决方案,我似乎从未记住它,因为它不时出现。

小函数 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;
}
Run Code Online (Sandbox Code Playgroud)

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