Pourquoi l'argument du mois est-il compris entre 0 et 11 dans le constructeur Date de JavaScript?

128

Lors de l'initialisation d'un nouvel Dateobjet en JavaScript à l'aide de l'appel ci-dessous, j'ai découvert que l'argument du mois compte à partir de zéro.

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

Pourquoi l'argument du mois commence-t-il à 0? Par contre, l'argument du jour du mois (le dernier) est un nombre compris entre 1 et 31. Y a-t-il de bonnes raisons à cela?

Agnel Kurian
la source
96
C'est juste pour vous garder sur vos orteils.
SeanJA
4
Celui qui est également indexé à zéro est the Day of the week (integer)0-6
SeanJA
Parce qu'il a été codé pour les machines et non pour les humains. Mais c'est toujours une énorme source de bugs car beaucoup de code est (encore) écrit par des humains :)
Christophe Roussy
4
@Christophe le même argument devrait s'appliquer également au jour et à l'année.
Agnel Kurian
2
@ChristopheRoussy ouais, si c'était codé pour les machines, pourquoi indexer les jours à partir de 1 alors?
user151496

Réponses:

55

C'est une vieille tradition (probablement malheureuse, probablement mourante) dans le monde de la programmation, voir l'ancienne fonction C localtime standard (POSIX) http://linux.die.net/man/3/localtime

Leonbloy
la source
14
L' Dateobjet JS a été porté à partir de Java 1.0, c'est pourquoi. Héritant de toutes ses failles ... stackoverflow.com/questions/344380/…
c69
1
Vous avez raison, les traditions sont généralement totalement incohérentes et souvent irrationnelles et j'espère vraiment que ces "mauvaises" traditions sont vraiment en train de mourir ...
henon
1
est 2019 et je corrige un problème lié à ce comportement, donc tant que les frameworks angulaires et les langages comme javascript ne le déconseillent pas, cela se produira toujours - n'hésitez pas à commenter en 2025 et plus ;-)
Mauricio Gracia Gutierrez
C'est une tradition qui me fait toujours passer du temps sur les problèmes de débogage avec les dates ... Je me demande combien d'heures de travail gaspillées cette tradition a causé.
Vedmant le
102

La vraie réponse à cette question, c'est qu'elle a été copiée java.util.Date, qui avait aussi cette bizarrerie. La preuve peut être trouvée sur Twitter de Brendan Eich - le gars qui a initialement implémenté JavaScript (y compris l' Dateobjet):

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

premier tweet

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

deuxième tweet

Cela s'est produit en 1995, et JDK 1.0 était en version bêta. Il a été lancé en 1996. En 1997, le JDK 1.1 est sorti qui a désapprouvé la grande majorité des fonctions java.util.Date, les déplaçant vers java.util.Calendar, mais même cela avait encore des mois à base zéro. Les développeurs en ont marre de cela ont créé la bibliothèque Joda-Time , qui a finalement conduit à un java.timepackage intégré à Java 8 (2014).

En bref, il a fallu 18 ans à Java pour obtenir une API de date / heure intégrée correctement conçue, mais JavaScript est toujours coincé à l'âge sombre. Nous avons en effet d'excellentes bibliothèques comme Moment.js , date-fns et js-joda . Mais pour l'instant, il n'y a rien de plus que Dateintégré à la langue. Espérons que cela changera dans un proche avenir.

Matt Johnson-Pint
la source
24
Ah ... Bonne vieille méthodologie de développement piloté par démo.
Álvaro González
@ ÁlvaroGonzález Je blâmerais le développeur JDK 1.0 original qui l'a introduit en premier lieu.
barell
30

Tout sauf le jour du mois est basé sur 0, voir ici pour une liste complète comprenant les plages :)

Ce sont en fait les jours basés sur 1 qui sont les bizarres ici ... assez curieusement. Pourquoi cela a-t-il été fait? Je ne sais pas ... mais il s'est probablement produit la même réunion, ils ont été plâtrés et ont décidé que les points-virgules étaient facultatifs.

Nick Craver
la source
1
Le problème des jours «basés sur les unités» est probablement dû au fait qu'aucune personne saine d'esprit ne créerait jamais un tableau de noms de chaînes pendant des jours (par exemple, { "first", "second", "third", ..., "twenty-seventh", ... }) et essaierait de l'indexer par tm_mday. Là encore, peut-être qu'ils ont juste vu l'utilité absolue de faire disparaître par une erreur une occurrence régulière.
D.Shawley
Pourquoi les années ne sont-elles pas basées sur 0?
Vedmant le
5

Il y a toujours 12 mois dans une année, donc les premières implémentations C auraient pu utiliser un tableau statique de largeur fixe avec des index 0..11.

Jonathan Julian
la source
2
L'implémentation Java Date / Calendar assure la prise en charge d'un mois supplémentaire pour certains calendriers. en.wikipedia.org/wiki/Undecimber
Pointy
4

C'est comme ça en java aussi .. Probablement pour convertir un int en chaîne (0 - jan ,, 1-feb), ils ont codé de cette façon .. parce qu'ils pourraient avoir un tableau de chaînes (indexées à partir de 0) des noms de mois et ces mois les nombres s'ils commencent à 0, il sera beaucoup plus facile de mapper aux chaînes de mois.

raj
la source
3

Je sais que ce n'est pas vraiment une réponse à la question initiale, mais je voulais juste vous montrer ma solution préférée à ce problème, que je ne semble jamais mémoriser car il apparaît de temps en temps.

La petite fonction zerofill fait l'affaire en remplissant les zéros là où c'est nécessaire, et le mois est simplement +1ajouté:

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

Mais oui, Date a une API assez peu intuitive, je riais en lisant le Twitter de Brendan Eich.

Christof Kälin
la source
2

Ils ont peut-être considéré les mois comme une énumération (le premier index étant 0) et les jours non, car ils n'ont pas de nom associé.

Ou plutôt, ils pensaient que le nombre du jour était la représentation réelle du jour (de la même manière que les mois sont représentés sous forme de nombres dans une date comme le 31/12), comme si vous pouviez faire une énumération avec des nombres comme variables, mais en fait Basé sur 0.

Donc, en fait, pour les mois, peut-être pensaient-ils que la représentation appropriée du dénombrement serait d'utiliser le nom du mois, au lieu des chiffres, et ils auraient fait la même chose si les jours avaient une représentation du nom. Imaginez si nous disions 5 janvier, 6 janvier, au lieu du 5 janvier, 6 janvier, etc., alors peut-être qu'ils auraient fait une énumération basée sur 0 pendant des jours aussi ...

Peut-être inconsciemment ont-ils pensé à une énumération pendant des mois comme {janvier, février, ...} et pendant des jours comme {un, deux, trois, ...}, sauf pour les jours où vous accédez au jour sous forme de nombre plutôt que de nom, comme 1 pour One, etc., donc impossible de commencer à 0 ...

Pat-Rire
la source
Vous devriez faire un double cours avec le psychologue. C'est toujours une erreur qu'ils ont faite, mais au moins nous comprenons maintenant pourquoi ils l'ont fait.
Zesty
0

Cela peut être une faille, mais c'est aussi très pratique lorsque vous voulez représenter les mois ou le jour de la semaine sous forme de chaîne, vous pouvez simplement créer un tableau comme ['jan,' feb '... etc] [new Date () .getMonth ()] au lieu de ['', 'jan', feb ... etc] [new Date (). getMonth ()] ou ['jan', 'feb' ... etc] [new Date ( ) .getMonth () - 1]

les jours du mois ne sont normalement pas nommés, vous ne ferez donc pas de tableaux avec des noms pour ceux-ci. Dans ce cas, 1-31 est plus facile à gérer, vous devez donc soustraire 1 à chaque fois ...

Rogier
la source
pas vraiment. Vous pouvez facilement en soustraire un. Cela crée plus de problèmes que cela n'en résout car maintenant, lorsque vous faites des calculs avec des dates, vous devez faire des manipulations spécifiques sur le mois assez souvent.
Rey