为什么在JavaScript';s日期构造函数?

为什么在JavaScript';s日期构造函数?,javascript,datetime,date,Javascript,Datetime,Date,使用下面的调用在JavaScript中初始化新的Date对象时,我发现month参数从零开始计数 new Date(2010, 3, 1); // that's the 1st April 2010! 为什么月份参数从0开始?另一方面,月日参数(最后一个)是1到31之间的数字。有什么好的理由吗?一年中总有12个月,所以早期的C实现可能使用了索引为0..11的静态固定宽度数组。除了一个月的日期是以0为基础之外,其他一切都是:) 事实上,1天是这里的怪胎…够奇怪的了。为什么要这样做?我不知道……

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

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

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

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

除了一个月的日期是以0为基础之外,其他一切都是:)


事实上,1天是这里的怪胎…够奇怪的了。为什么要这样做?我不知道……但可能是在同一次会议上,他们被涂上了石膏,决定分号是可选的。

这是编程界的一个古老(可能很不幸,可能正在消亡)的传统,请参阅旧标准(POSIX)localtime C函数

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

这可能是一个缺陷,但当您想将一周中的月份或日期表示为字符串时,它也非常方便,您只需创建一个数组,如['jan,'feb'…等][new Date().getMonth()]而不是['''jan',feb…等][new Date().getMonth()]或['jan','feb'…等][new Date().getMonth()-1]


一个月中的几天通常不命名,因此您不会使用这些天的名称创建数组。在这种情况下,1-31更容易处理,因此您需要每次减去1…

他们可能会将月视为枚举(第一个索引为0),而将天视为非枚举,因为他们没有与之关联的名称

或者更确切地说,他们认为一天的数字是一天的实际表示形式(与12/31这样的日期中月份表示为数字的方式相同),好像你可以用数字作为变量进行枚举,但实际上是以0为基础的

所以实际上,对于月份,也许他们认为正确的枚举表示法应该是使用月份的名称,而不是数字,如果days有名称表示法,他们也会这样做。想象一下,如果我们说1月5日,1月6日,而不是1月5日,1月6日等等,那么也许他们也会做一个以0为基础的数日计数


也许他们下意识地认为,数月的计数是{1月,2月,…},数天的计数是{1,2,3,…},除了以数字而不是名称的形式访问日期外,例如1代表1等,因此不可能从0开始…

这个问题的真正答案,它是从
java.util.Date
复制而来的,它也有这个怪癖。在Twitter上可以找到来自Brendan Eich的证据——他最初实现了JavaScript:

Brendan还指出是Netscape的Ken Smith从Java进行了移植

这发生在1995年,JDK1.0处于测试阶段。它于1996年启动。1997年,JDK1.1问世,它不推荐使用
java.util.Date
上的绝大多数函数,将它们移到
java.util.Calendar
,但即使这样,也仍然有零个月。受够了这一点的开发人员创建了这个库,最终导致了
java.time
包,该包被烘焙到Java8(2014)中


简言之,Java花了18年时间才获得了一个设计正确的内置日期/时间API,但JavaScript仍然停留在黑暗时代。我们确实有优秀的图书馆,如、、等。但到目前为止,该语言只内置了
Date
。希望在不久的将来,这种情况会有所改变。

我知道这并不是对原来问题的回答,但我只是想向您展示我对这个问题的首选解决方案,因为它不时会弹出,我似乎从来没有记住过

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

函数零填充(i){
返回(i<10?'0':'')+i;
}
函数getDateString(){
const date=新日期();
const year=date.getFullYear();
const month=zerofill(date.getMonth()+1);
const day=zerofill(date.getDate());
返回年份+'-'+月份+'-'+天;
}

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

2021年,真正的问题是:

如果
Date
从JS的第一天起就被打破了,为什么在26年后(如果从零算起是25年)它仍然在这里

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

但我们很幸运,看来日期快结束了

扰流器
临时(提案) 从提案导言中:

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

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

  • Plain
    类型没有时区
  • zoneDateTime
    类型有一个时区
  • 大多数类型都有日历
  • 许多有用的类型:
    绝对值
    日期时间
    日期
    时间
    时区
这是一个概述各种
时态
类型及其关系的模式

您可以在可用的和nice中阅读更多关于它们的信息。或探索
new Temporal.PlainDate(2020, 11, 26); // => 2020-11-26
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