Perché l'argomento del mese varia da 0 a 11 nel costruttore Date di JavaScript?


128

Quando si inizializza un nuovo Dateoggetto in JavaScript utilizzando la chiamata seguente, ho scoperto che l'argomento del mese conta a partire da zero.

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

Perché l'argomento del mese inizia da 0? D'altra parte, l'argomento del giorno del mese (l'ultimo) è un numero compreso tra 1 e 31. Ci sono buone ragioni per questo?


96
È solo per tenerti in punta di piedi.
SeanJA

4
Uno che è anche indicizzato a zero è the Day of the week (integer)0-6
SeanJA

Perché era codificato per le macchine e non per gli esseri umani. Ma è ancora un'enorme fonte di bug perché molto codice è (ancora) scritto da esseri umani :)
Christophe Roussy

4
@Christophe lo stesso argomento dovrebbe valere anche per giorno e anno.
Agnel Kurian

2
@ChristopheRoussy sì, se fosse codificato per macchine, perché allora indicizzare i giorni da 1?
user151496

Risposte:


55

È una vecchia (probabilmente sfortunata, probabilmente morente) tradizione nel mondo della programmazione, vedere la funzione localtime C del vecchio standard (POSIX) http://linux.die.net/man/3/localtime


14
L' Dateoggetto JS è stato portato da Java 1.0, ecco perché. Ereditando tutti i suoi difetti ... stackoverflow.com/questions/344380/...
C69

1
Hai ragione, le tradizioni sono di solito totalmente incoerenti e spesso irrazionali e spero davvero che tali tradizioni "cattive" stiano davvero morendo ...
henon

1
è il 2019 e sto risolvendo un problema relativo a questo comportamento, quindi fino a quando framework angolari e linguaggi come javascript non lo deprecano, ciò accadrà ancora - sentiti libero di commentare nell'anno 2025 e oltre ;-)
Mauricio Gracia Gutierrez

Questa è una tradizione che mi fa sempre passare il tempo su problemi di debug con le date ... Mi chiedo quante ore di lavoro sprecate questa tradizione abbia causato.
Vedmant

102

La vera risposta a questa domanda è che è stata copiata java.util.Date, il che aveva anche questa stranezza. La prova può essere trovata su Twitter da Brendan Eich, il ragazzo che originariamente ha implementato JavaScript (incluso l' Dateoggetto):

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

primo tweet

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

secondo tweet

Questo è successo nel 1995 e JDK 1.0 era in beta. È stato lanciato nel 1996. Nel 1997 è uscito JDK 1.1 che ha deprecato la stragrande maggioranza delle funzioni java.util.Date, spostandole su java.util.Calendar, ma anche quella aveva mesi a base zero. Gli sviluppatori stufi di questo hanno creato la libreria Joda-Time , che alla fine ha portato a un java.timepacchetto integrato in Java 8 (2014).

In breve, ci sono voluti 18 anni perché Java ottenesse un'API data / ora correttamente progettata, ma JavaScript è ancora bloccato nei secoli bui. Abbiamo davvero eccellenti librerie come Moment.js , date-fns e js-joda . Ma per ora, non c'è niente di più che Dateintegrato nella lingua. Si spera che questo cambierà nel prossimo futuro.


24
Ah ... La buona vecchia metodologia di sviluppo basato su demo.
Álvaro González

@ ÁlvaroGonzález Darei la colpa allo sviluppatore originale JDK 1.0 che lo ha introdotto in primo luogo.
barell

30

Tutto tranne il giorno del mese è basato su 0, vedi qui per un elenco completo degli intervalli :)

In realtà sono i giorni basati su 1 che sono le stranezze qui ... stranamente. Perché è stato fatto questo? Non lo so ... ma probabilmente è successo lo stesso incontro in cui sono stati ingessati e hanno deciso che il punto e virgola era facoltativo.


1
La questione dei giorni "basati su unità" è probabilmente dovuta al fatto che nessuno sano di mente creerebbe mai un array di nomi di stringhe per giorni (ad esempio { "first", "second", "third", ..., "twenty-seventh", ... }) e proverebbe a indicizzarlo per tm_mday. Poi di nuovo, forse hanno appena visto l'assoluta utilità nel far sì che un errore si verifichi regolarmente.
D.Shawley

Perché gli anni non sono basati su 0?
Vedmant

5

Ci sono sempre 12 mesi in un anno, quindi le prime implementazioni C potrebbero aver utilizzato un array statico a larghezza fissa con indici 0..11.


2
L'implementazione Java Date / Calendar mantiene il supporto per un mese in più per alcuni calendari. en.wikipedia.org/wiki/Undecimber
Pointy

4

È così anche in java .. Probabilmente per convertire int in stringa (0 - jan ,, 1-feb), hanno codificato in questo modo .. perché potrebbero avere un array di stringhe (indicizzate da 0) di nomi di mesi e questi mesi numeri se iniziano da 0, sarà molto più facile mappare le stringhe del mese ..


3

So che non è davvero una risposta alla domanda originale, ma volevo solo mostrarti la mia soluzione preferita a questo problema, che mi sembra di non memorizzare mai perché si apre di tanto in tanto.

La piccola funzione zerofill fa il trucco riempiendo gli zeri dove necessario, e il mese viene semplicemente +1aggiunto:

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

Ma sì, Date ha un'API piuttosto non intuitiva, stavo ridendo quando ho letto il Twitter di Brendan Eich.


2

Potrebbero aver considerato i mesi come un'enumerazione (il primo indice è 0) e i giorni no poiché non hanno un nome associato.

O meglio, pensavano che il numero del giorno fosse la rappresentazione effettiva del giorno (allo stesso modo in cui i mesi sono rappresentati come numeri in una data come 12/31), come se si potesse fare un'enumerazione con i numeri come variabili, ma in realtà 0-based.

Quindi, in realtà, per i mesi, forse hanno pensato che la corretta rappresentazione dell'enumerazione sarebbe stata quella di utilizzare il nome del mese, invece dei numeri, e avrebbero fatto lo stesso se i giorni avessero una rappresentazione del nome. Immagina se dicessimo 5 gennaio, 6 gennaio, invece di 5 gennaio, 6 gennaio, ecc., Allora forse avrebbero fatto un'enumerazione a base 0 anche per giorni ...

Forse inconsciamente hanno pensato a un'enumerazione per mesi come {gennaio, febbraio, ...} e per giorni come {Uno, Due, Tre, ...}, tranne i giorni in cui accedi al giorno come numero piuttosto che come nome, come 1 per uno, ecc., quindi impossibile iniziare da 0 ...


Dovresti fare la doppia classe allo psicologo. È ancora un errore che hanno fatto, ma almeno ora capiamo perché lo hanno fatto.
Zesty

0

Potrebbe essere un difetto, ma è anche molto utile quando vuoi rappresentare i mesi o il giorno della settimana come una stringa puoi semplicemente creare un array come ['jan,' feb '... ecc] [new Date () .getMonth ()] al posto di ['', 'jan', feb ... ecc] [new Date (). getMonth ()] o ['jan', 'feb' ... ecc] [new Date ( ) .getMonth () - 1]

i giorni del mese normalmente non sono nominati, quindi non creerai array con nomi per quelli. In questo caso 1-31 è più facile da gestire, quindi devi sottrarre 1 ogni volta ...


non proprio. Potresti facilmente sottrarne uno. Crea più problemi di quanti ne risolva perché ora quando fai i calcoli con le date, devi fare manipolazioni specifiche sul mese piuttosto spesso.
Rey
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.