Warum reicht das Monatsargument im Datumskonstruktor von JavaScript von 0 bis 11?

127

Beim Initialisieren eines neuen DateObjekts in JavaScript mit dem folgenden Aufruf habe ich festgestellt, dass das Argument month ab Null zählt.

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

Warum beginnt das Monatsargument bei 0? Andererseits ist das Argument für den Tag des Monats (letzter) eine Zahl von 1 bis 31. Gibt es dafür gute Gründe?

Agnel Kurian
quelle
96
Es ist nur, um dich auf Trab zu halten.
SeanJA
4
Eine, die auch null indiziert ist, ist the Day of the week (integer)0-6
SeanJA
Weil es für Maschinen und nicht für Menschen codiert wurde. Aber es ist immer noch eine große Quelle von Fehlern, weil viel Code (noch) von Menschen geschrieben wird :)
Christophe Roussy
4
@Christophe das gleiche Argument sollte auch für Tag und Jahr gelten.
Agnel Kurian
2
@ChristopheRoussy Ja, wenn es für Maschinen codiert wäre, warum dann Indextage von 1?
user151496

Antworten:

55

Es ist eine alte (wahrscheinlich unglückliche, wahrscheinlich sterbende) Tradition in der Programmierwelt, siehe die alte Standard- Localtime- C-Funktion (POSIX) http://linux.die.net/man/3/localtime

leonbloy
quelle
14
Das JS- DateObjekt wurde aus Java 1.0 portiert, deshalb. Alle seine Fehler erben ... stackoverflow.com/questions/344380/…
c69
1
Sie haben Recht, Traditionen sind normalerweise völlig inkonsistent und oftmals irrational und ich würde wirklich hoffen, dass solche "schlechten" Traditionen wirklich sterben ...
Henon
1
ist 2019 und ich behebe ein Problem im Zusammenhang mit diesem Verhalten. Solange Frameworks wie eckig und Sprachen wie Javascript dies nicht ablehnen, wird es immer noch passieren - zögern Sie nicht, im Jahr 2025 und danach zu kommentieren ;-)
Mauricio Gracia Gutierrez
Das ist eine Tradition, die mich immer dazu bringt, Probleme mit Daten zu debuggen ... Ich frage mich, wie viel Zeitverschwendung diese Tradition verursacht hat.
Vedmant
101

Die wirkliche Antwort auf diese Frage ist, dass sie kopiert wurde java.util.Date, was auch diese Eigenart hatte. Der Beweis kann auf Twitter von Brendan Eich gefunden werden - dem Typ, der ursprünglich JavaScript (einschließlich des DateObjekts) implementiert hat :

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

erster Tweet

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

zweiter Tweet

Dies geschah 1995 und JDK 1.0 befand sich in der Beta. Es wurde 1996 eingeführt. 1997 kam JDK 1.1 heraus, das die überwiegende Mehrheit der Funktionen java.util.Dateablehnte und auf diese verlagerte java.util.Calendar, aber selbst das hatte noch nullbasierte Monate. Entwickler, die es satt haben, haben die Joda-Time- Bibliothek erstellt, die letztendlich zu einem java.timePaket führte, das in Java 8 (2014) integriert ist.

Kurz gesagt, es dauerte 18 Jahre, bis Java eine korrekt gestaltete Datums- / Uhrzeit-API integriert hatte, aber JavaScript steckt immer noch im dunklen Zeitalter fest. Wir haben in der Tat ausgezeichnete Bibliotheken wie Moment.js , date-fns und js-joda . Aber ab sofort ist nichts mehr als Datein die Sprache eingebaut. Hoffentlich wird sich dies in naher Zukunft ändern.

Matt Johnson-Pint
quelle
24
Ah ... Gute alte demo-gesteuerte Entwicklungsmethode.
Álvaro González
@ ÁlvaroGonzález Ich würde dem ursprünglichen JDK 1.0-Entwickler die Schuld geben, der es überhaupt erst eingeführt hat.
Barell
30

Alles außer dem Tag des Monats basiert auf 0, eine vollständige Liste mit Bereichen finden Sie hier :)

Es sind tatsächlich die 1-basierten Tage, die hier die seltsamen Bälle sind ... seltsamerweise. Warum wurde das getan? Ich weiß nicht ... aber wahrscheinlich fand das gleiche Treffen statt, bei dem sie verputzt wurden, und entschied, dass Semikolons optional waren.

Nick Craver
quelle
1
Die Sache mit den "Einsen-basierten" Tagen liegt wahrscheinlich daran, dass niemand, der bei klarem Verstand ist, jemals ein Array von Zeichenfolgennamen für Tage (z. B. { "first", "second", "third", ..., "twenty-seventh", ... }) erstellen und versuchen würde, diese nach zu indizieren tm_mday. Andererseits sahen sie vielleicht nur den absoluten Nutzen darin, durch einen Fehler ein regelmäßiges Ereignis auszulösen.
D.Shawley
Sie, warum Jahre nicht 0 basieren?
Vedmant
5

Ein Jahr hat immer 12 Monate, daher haben frühe C-Implementierungen möglicherweise ein statisches Array mit fester Breite mit den Indizes 0..11 verwendet.

Jonathan Julian
quelle
2
Die Java Date / Calendar-Implementierung unterstützt einige Kalender für einen zusätzlichen Monat. en.wikipedia.org/wiki/Undecimber
Pointy
4

Dies ist auch in Java so. Wahrscheinlich , um int in einen String (0 - jan ,, 1-feb) umzuwandeln, haben sie auf diese Weise codiert Zahlen, wenn sie bei 0 beginnen, ist es viel einfacher, die Monatszeichenfolgen zuzuordnen.

Raj
quelle
3

Ich weiß, dass es nicht wirklich eine Antwort auf die ursprüngliche Frage ist, aber ich wollte Ihnen nur meine bevorzugte Lösung für dieses Problem zeigen, die ich mir nie zu merken scheint, da sie von Zeit zu Zeit auftaucht.

Die kleine Funktion zerofill erledigt den Trick, die Nullen bei Bedarf zu füllen, und der Monat wird einfach +1hinzugefügt:

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

Aber ja, Date hat eine ziemlich unintuitive API. Ich habe gelacht, als ich Brendan Eichs Twitter gelesen habe.

Christof Kälin
quelle
2

Sie haben Monate möglicherweise als Aufzählung betrachtet (erster Index ist 0) und Tage nicht, da ihnen kein Name zugeordnet ist.

Oder besser gesagt, sie dachten, die Nummer des Tages sei die tatsächliche Darstellung des Tages (genauso wie Monate in einem Datum wie dem 31.12. Als Zahlen dargestellt werden), als könnten Sie eine Aufzählung mit Zahlen als Variablen vornehmen, aber tatsächlich 0-basiert.

Tatsächlich dachten sie für die Monate vielleicht, die richtige Aufzählungsdarstellung würde darin bestehen, den Namen des Monats anstelle von Zahlen zu verwenden, und sie hätten dasselbe getan, wenn Tage eine Namensdarstellung gehabt hätten. Stellen Sie sich vor, wir würden sagen, der 5. Januar, der 6. Januar, anstatt der 5. Januar, der 6. Januar usw., dann hätten sie vielleicht auch tagelang eine 0-basierte Aufzählung durchgeführt ...

Vielleicht haben sie unbewusst über eine Aufzählung für Monate als {Januar, Februar, ...} und für Tage als {Eins, Zwei, Drei, ...} nachgedacht, außer für Tage, an denen Sie auf den Tag als Zahl und nicht als Namen zugreifen. wie 1 für Eins usw., so unmöglich, bei 0 zu beginnen ...

Pat-Laugh
quelle
Sie sollten zwei Klassen zum Psychologen. Es ist immer noch ein Fehler, den sie gemacht haben, aber zumindest verstehen wir jetzt, warum sie es gemacht haben.
Zesty
0

Es mag ein Fehler sein, aber es ist auch sehr praktisch, wenn Sie die Monate oder den Wochentag als Zeichenfolge darstellen möchten. Sie können einfach ein Array wie ['jan,' feb '... etc] [new Date () erstellen. .getMonth ()] anstelle von ['', 'jan', feb ... etc] [neues Datum (). getMonth ()] oder ['jan', 'feb' ... etc] [neues Datum ( ) .getMonth () - 1]

Tage des Monats werden normalerweise nicht benannt, sodass Sie keine Arrays mit Namen für diese erstellen. In diesem Fall ist 1-31 einfacher zu handhaben, daher müssen Sie jedes Mal 1 subtrahieren ...

Rogier
quelle
nicht wirklich. Sie könnten leicht nur einen subtrahieren. Es schafft mehr Probleme als es löst, denn wenn Sie jetzt mit Datumsangaben rechnen, müssen Sie den Monat ziemlich oft gezielt manipulieren.
Rey