代码之家  ›  专栏  ›  技术社区  ›  Agnel Kurian

为什么在javascript的日期构造函数中,month参数的范围是0到11?

  •  86
  • Agnel Kurian  · 技术社区  · 14 年前

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

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

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

    8 回复  |  直到 7 年前
        1
  •  41
  •   leonbloy    14 年前

    在编程界,这是一个古老的(可能是不幸的,可能是正在消亡的)传统,参见旧标准(posix) 本地时间 C函数 http://linux.die.net/man/3/localtime

        2
  •  69
  •   Matt Johnson-Pint    8 年前

    这个问题的真正答案是 java.util.Date ,也有这种怪癖。证据可以在Twitter上找到,来自BrendanEich——最初实现JavaScript的人(包括 Date 对象):

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

    first tweet

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

    second tweet

    这发生在1995年,JDK1.0处于测试阶段。它于1996年推出。1997年,jdk 1.1问世,它否决了 日期类型 把他们转移到 java.util.Calendar ,但即便如此,也有零基月份。受够了这一点的开发人员创建了 Joda-Time 图书馆,最终导致 java.time 在Java 8(2014)中烘烤的包。

    简而言之,Java花了18年时间才得到了一个内置的正确的日期/时间API,但JavaScript仍然被困在黑暗时代。我们确实有很好的图书馆 Moment.js , date-fns js-joda . 但到现在为止 日期 内置于语言中。希望这在不久的将来会改变。

        3
  •  27
  •   Nick Craver    14 年前

    除了一个月中的某一天之外,其他的都是基于0的, see here for a full list including ranges :)

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

        4
  •  4
  •   Jonathan Julian    14 年前

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

        5
  •  3
  •   raj    14 年前

    它在Java中也是如此。 可能 为了将int转换成字符串(0-jan,1-feb),他们用这种方式编码。因为它们可能有一个字符串数组(从0开始索引),其中包含月份名称和这些月份编号(如果从0开始索引),所以映射到月份字符串要容易得多。

        6
  •  3
  •   Christof Kälin    7 年前

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

    小函数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时我笑了。

        7
  •  1
  •   user    8 年前

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

    或者更确切地说,他们认为一天的数字是一天的实际表示(就像在12/31这样的日期中,月被表示为数字一样),好像你可以用数字作为变量进行枚举,但实际上是基于0的。

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

    也许他们下意识地认为数月的计数是{1月,2月,},数天的计数是{1,2,3,…},除了你用数字而不是名字来访问一天的天数,比如1代表1等等,所以不可能从0开始……

        8
  •  0
  •   Rogier    9 年前

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

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