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

128

Ao inicializar um novo Dateobjeto em JavaScript usando a chamada abaixo, descobri que o argumento do mês conta a partir 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 argumento do dia do mês (último) é um número de 1 a 31. Existem boas razões para isso?

Agnel Kurian
fonte
96
É apenas para mantê-lo alerta.
SeanJA
4
Um que também é zero indexado é the Day of the week (integer)0-6 #
593 SeanJA
Porque foi codificado para máquinas e não para humanos. Mas ainda é uma enorme fonte de erros, porque um monte de código (ainda) é escrito por seres humanos :)
Christophe Roussy
4
@Christophe o mesmo argumento deve se aplicar também ao dia e ao ano.
precisa saber é o seguinte
2
@ChristopheRoussy sim, se foi codificado para máquinas, por que indexar dias a partir de 1 então?
user151496

Respostas:

55

É uma tradição antiga (provavelmente lamentável, provavelmente moribunda) no mundo da programação; veja a função C localtime do padrão antigo (POSIX) http://linux.die.net/man/3/localtime

leonbloy
fonte
14
O Dateobjeto JS foi portado do Java 1.0, é por isso. Herdando todas as suas falhas ... stackoverflow.com/questions/344380/…
c69
1
Você está certo, as tradições são geralmente totalmente inconsistentes e muitas vezes irracional e eu realmente espero que essas tradições "maus" são realmente morrendo ...
Henon
1
é 2019 e estou corrigindo um problema relacionado a esse comportamento, desde que estruturas como angulares e linguagens como javascript não depreciem isso ainda acontecerá - sinta-se à vontade para comentar no ano de 2025 em diante ;-)
Mauricio Gracia Gutierrez
Essa é uma tradição que sempre me faz gastar tempo em problemas de depuração com datas ... Pensando em quantas horas de trabalho desperdiçadas essa tradição causou.
Vedmant 03/07
102

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

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 na versão beta. Foi lançado em 1996. Em 1997, foi lançado o JDK 1.1, que depreciava a grande maioria das funções java.util.Date, passando-as para java.util.Calendar, mas mesmo isso ainda tinha meses com base zero. Os desenvolvedores fartos disso criaram a biblioteca Joda-Time , que finalmente levou ao java.timepacote que foi incorporado ao Java 8 (2014).

Em resumo, demorou 18 anos para o Java obter uma API de data / hora projetada corretamente, mas o JavaScript ainda está preso na idade das trevas. De fato, temos excelentes bibliotecas como Moment.js , date-fns e js-joda . Mas, a partir de agora, não há nada além de Dateembutido no idioma. Espero que isso mude no futuro próximo.

Matt Johnson-Pint
fonte
24
Ah ... Boa e antiga metodologia de Desenvolvimento Orientado a Demonstrações.
Álvaro González
@ ÁlvaroGonzález Eu culparia o desenvolvedor original do JDK 1.0 que o introduziu em primeiro lugar.
#
30

Tudo, exceto o dia do mês, é 0, veja aqui uma lista completa, incluindo os intervalos :)

Na verdade, são os dias 1 que são os excêntricos aqui ... curiosamente. Por que isso foi feito? Eu não sei ... mas provavelmente aconteceu na mesma reunião em que eles foram colados e decidiram que o ponto e vírgula era opcional.

Nick Craver
fonte
1
A coisa dos dias "baseados em um" é provavelmente porque ninguém em sã consciência jamais criaria uma matriz de nomes de strings por dias (por exemplo, { "first", "second", "third", ..., "twenty-seventh", ... }) e tentaria indexá-lo tm_mday. Por outro lado, talvez eles tenham visto a utilidade absoluta em fazer com que um erro ocorresse regularmente.
D.Shawley
Eles por que os anos não são baseados em zero?
Vedmant 03/07
5

Sempre existem 12 meses em um ano, portanto, as implementações iniciais do C podem ter usado uma matriz estática de largura fixa com índices 0..11.

Jonathan Julian
fonte
2
A implementação Java Date / Calendar mantém o suporte por um mês extra para alguns calendários. en.wikipedia.org/wiki/Undecimber
Pointy 31/03
4

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

raj
fonte
3

Sei que não é realmente uma resposta para a pergunta original, mas só queria mostrar a minha solução preferida para esse problema, que eu nunca memorizo, pois aparece de vez em quando.

A pequena função zerofill faz o truque preenchendo os zeros quando necessário, e o mês é apenas +1adicionado:

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, o Date tem uma API pouco intuitiva, eu estava rindo quando li o Twitter de Brendan Eich.

Christof Kälin
fonte
2

Eles podem ter considerado meses uma enumeração (o primeiro índice é 0) e dias desde que não têm um nome associado a eles.

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

Então, na verdade, durante os meses, talvez eles pensassem que a representação de enumeração adequada seria usar o nome do mês, em vez de números, e 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 por dias também ...

Talvez subconscientemente pensassem em uma enumeração por meses como {janeiro, fevereiro, ...} e por dias como {um, dois, três, ...}, exceto nos dias em que você acessa o dia como um número, e não como o nome, como 1 para um, etc., é impossível iniciar em 0 ...

Pat-Laugh
fonte
Você deve ter aula dupla para psicólogo. Ainda é um erro que eles cometeram, mas pelo menos agora entendemos por que eles cometeram.
Zesty
0

Pode ser uma falha, mas também é muito útil quando você deseja representar os meses ou o dia da semana como uma string, basta criar uma matriz como ['jan,' feb '... etc] [new Date () .getMonth ()] em vez de ['', 'jan', fev ... etc] [nova Data (). getMonth ()] ou ['jan', 'feb' ... etc] [nova Data ( ) .getMonth () - 1]

os dias do mês normalmente não são nomeados, portanto você não criará matrizes com nomes para eles. Nesse caso, 1-31 é mais fácil de manusear, portanto, você precisa subtrair 1 toda vez ...

Rogier
fonte
Na verdade não. Você pode facilmente subtrair um. Isso cria mais problemas do que resolve, porque agora, quando você faz contas com datas, precisa manipular especificamente o mês com bastante frequência.
Rey