Por que o argumento do mês varia de 0 a 11 no construtor Date do JavaScript?

Ao inicializar um novo object Date em JavaScript usando a chamada abaixo, descobri que o argumento do mês conta começando do zero.

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

Por que o argumento do mês começa em 0? Por outro lado, o dia do argumento do mês (último) é um número de 1 a 31. Existem boas razões para isso?

É uma tradição antiga (provavelmente infeliz, provavelmente morrendo) no mundo da programação, veja a antiga function C localtime (POSIX) padrão http://linux.die.net/man/3/localtime

A verdadeira resposta para essa pergunta é que ela foi copiada de java.util.Date , que também tinha essa peculiaridade. Prova pode ser encontrada no Twitter de Brendan Eich – o cara que originalmente implementou JavaScript (incluindo o object Date ):

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

primeiro tweet

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

segundo tweet

Isso aconteceu em 1995, e o JDK 1.0 estava em beta. Ele foi lançado em 1996. Em 1997, o JDK 1.1 foi lançado, o que preteriu a grande maioria das funções em java.util.Date , movendo-as para o java.util.Calendar , mas mesmo assim elas ainda tinham meses baseados em zero. Desenvolvedores fartos disso criaram a biblioteca Joda-Time , que acabou levando ao pacote java.time que foi java.time ao Java 8 (2014).

Em suma, demorou 18 anos para o Java ter uma API de data / hora corretamente projetada, mas o JavaScript ainda está preso na idade das trevas. Na verdade, temos excelentes bibliotecas como Moment.js , date-fns e js-joda . Mas, a partir de agora, não há nada mais do que Date embutido na linguagem. Espero que isso mude no futuro próximo.

Tudo, exceto o dia do mês, é baseado em 0, veja aqui uma lista completa incluindo os intervalos 🙂

Na verdade, são os dias baseados em 1 que são os excêntricos aqui … por incrível que pareça. Por que isso foi feito? Eu não sei … mas provavelmente aconteceu a mesma reunião em que eles ficaram engessados ​​e decidiram que ponto e vírgula eram opcionais.

Há sempre 12 meses em um ano, portanto, as primeiras implementações de C podem ter usado uma matriz de largura fixa estática com índices 0.11.

É assim também em java .. Provavelmente para converter int em string (0 – jan ,, 1-feb), eles codificaram dessa forma .. porque eles podem ter uma matriz de string (indexada de 0) de nomes de meses e esses meses números se começarem a partir de 0, será muito mais fácil mapear as strings do mês.

Eu sei que não é realmente uma resposta para a pergunta original, mas eu só queria mostrar-lhe a minha solução preferida para este problema, que eu nunca pareço memorizar, uma vez que aparece de vez em quando.

A pequena function zerofill faz o truque de preencher os zeros quando necessário, e o mês é apenas +1 adicionado:

 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; } 

Mas sim, Date tem uma API bem pouco intuitiva, eu estava rindo quando li o Twitter de Brendan Eich.

Eles podem ter considerado meses para ser uma enumeração (primeiro índice sendo 0) e dias não, desde que não tenham um nome associado a eles.

Ou melhor, eles achavam que o número do dia era a representação real do dia (os mesmos meses são representados como números em uma data como 12/31), como se você pudesse fazer uma enumeração com números como variables, mas na verdade Baseado em 0.

Então, na verdade, durante os meses, talvez eles achassem que a representação de enumeração apropriada seria usar o nome do mês, em vez de números, e eles teriam feito o mesmo se os dias tivessem uma representação de nome. Imagine se disséssemos 5 de janeiro, 6 de janeiro, em vez de 5 de janeiro, 6 de janeiro etc., então talvez eles tivessem feito uma enumeração baseada em 0 também por dias …

Talvez subconscientemente eles pensassem em uma enumeração por meses como {janeiro, fevereiro, …} e por dias como {Um, Dois, Três, …}, exceto por dias que você acessa o dia como um número em vez do nome, como 1 para um, etc., tão impossível começar em 0 …

Pode ser uma falha, mas também é muito útil quando você quer representar os meses ou o dia da semana como uma string, você pode simplesmente criar uma matriz como [‘jan,’ feb ‘… etc] [new Date () .getMonth ()] em vez de [”, ‘jan’, fev … etc] [novo Date (). getMonth ()] ou [‘jan’, ‘feb’ … etc] [new Date ( ) .getMonth () – 1]

dias do mês normalmente não são nomeados, então você não estará criando matrizes com nomes para eles. Neste caso, o 1-31 é mais fácil de manusear, então você precisa subtrair 1 todas as vezes …