Pesquisa de site

datetime - Por que o argumento month varia de 0 a 11 no construtor Date do JavaScript?


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

Resposta #1

A resposta real para esta pergunta é que ela foi copiada de java.util.Date, que também tinha essa peculiaridade. A prova pode ser encontrada no Twitter de Brendan Eich - o cara que originalmente implementou o JavaScript:

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

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

Brendan também indica que foi Ken Smith da Netscape quem fez a portabilidade do Java.

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

Isso aconteceu em 1995, e o JDK 1.0 estava em versão beta. Ele foi lançado em 1996. Em 1997, o JDK 1.1 foi lançado, que depreciou a grande maioria das funções em java.util.Date, movendo-as para java.util.Calendar, mas mesmo assim ainda tinha meses baseados em zero. Desenvolvedores cansados disso criaram a biblioteca Joda-Time, que eventualmente levou ao pacote java.time, que vem incorporado no Java 8 (2014).

Em resumo, levaram 18 anos para o Java ter uma API de data/hora corretamente projetada incorporada, mas o JavaScript ainda está preso na Idade das Trevas. De fato, temos bibliotecas excelentes como Luxon, Moment.js, date-fns, js-joda e outras. Mas, até agora, não há nada mais do que Date incorporado na linguagem. Esperançosamente, isso mudará em um futuro próximo com a proposta Temporal do TC39.

Resposta #2

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

Resposta #3

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

Na verdade, são os dias baseados em 1 que são os estranhos aqui... curiosamente. Por que isso foi feito? Não sei... mas provavelmente aconteceu na mesma reunião em que eles ficaram bêbados e decidiram que os ponto e vírgulas eram opcionais.

Resposta #4

Em 2024, a verdadeira pergunta é:

Se Date estava quebrado desde o primeiro dia do JS, por que depois de 29 anos (28 se contar a partir do zero) ele ainda está aqui?

JS tem muitas partes/peculiaridades ruins e a pior coisa é que algumas delas não foram corrigidas em décadas (curiosidade: estamos falando sobre Date datas).

Mas temos sorte, parece que o fim de Date está próximo.

Spoiler

new Temporal.PlainDate(2020, 11, 26); // => 2020-11-26

Temporal (proposta)

Da introdução da proposta:

Date tem sido um ponto problemático de longa data no ECMAScript. Esta é uma proposta para Temporal, um Object global que atua como um namespace de nível superior (como Math), que traz uma API moderna de data/hora para a linguagem ECMAScript.

É baseado, conforme relatado nos documentos, "em casos de uso comuns que examinamos" e possui múltiplos tipos para diferentes tipos de dados:

  • Tipos Plain não têm fuso horário
  • Tipos ZonedDateTime possuem um fuso horário
  • a maioria dos tipos tem um calendário
  • muitos tipos úteis: Absolute, DateTime, Date, Time, TimeZone, ...

Este é um esquema que descreve vários tipos Temporal e suas relações

Você pode ler mais sobre eles na documentação disponível e no bom livro de receitas. Ou explorar os problemas atuais para os que estão abertos.

Quando o Temporal estará disponível

Desde março de '21, está no Estágio 3/Rascunho (veja a referência de estágios do TC39). Veja os slides do TC39 de março de '21.

Agora isso pode ser incluído no TypeScript em breve, já que a política deles é:

Quando novos recursos atingem o estágio 3, então eles estão prontos para inclusão no TypeScript.

Provavelmente para Node e os principais navegadores teremos que esperar mais.

Comece a experimentar hoje

Enquanto isso, você pode experimentá-lo usando o polyfill do Temporal.

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

Artigos relacionados