¿Por qué el argumento del mes varía de 0 a 11 en el constructor Date de JavaScript?

128

Al inicializar un nuevo Dateobjeto en JavaScript usando la siguiente llamada, descubrí que el argumento del mes cuenta a partir de cero.

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

¿Por qué el argumento del mes comienza desde 0? Por otro lado, el argumento del día del mes (el último) es un número del 1 al 31. ¿Hay buenas razones para esto?

Agnel Kurian
fuente
96
Es solo para mantenerte alerta.
SeanJA
4
Uno que también tiene un índice cero es the Day of the week (integer)0-6
SeanJA
Porque estaba codificado para máquinas y no para humanos. Pero sigue siendo una gran fuente de errores porque una gran cantidad de código (todavía) está escrito por humanos :)
Christophe Roussy
4
@Christophe, el mismo argumento debería aplicarse al día y al año también.
Agnel Kurian
2
@ChristopheRoussy sí, si estuviera codificado para máquinas, ¿por qué indexar días desde 1 entonces?
user151496

Respuestas:

55

Es una tradición antigua (probablemente desafortunada, probablemente agonizante) en el mundo de la programación, consulte la función C de localtime estándar antiguo (POSIX) http://linux.die.net/man/3/localtime

Leonbloy
fuente
14
El Dateobjeto JS fue portado desde Java 1.0, por eso. Heredando todos sus defectos ... stackoverflow.com/questions/344380/…
c69
1
Tienes razón, las tradiciones suelen ser totalmente inconsistentes y, a menudo, irracionales y realmente espero que esas tradiciones "malas" estén realmente muriendo ...
henon
1
es 2019 y estoy solucionando un problema relacionado con este comportamiento, por lo que siempre que marcos como angulares y lenguajes como javascript no desaprueben esto, aún sucederá; siéntase libre de comentar en el año 2025 en adelante ;-)
Mauricio Gracia Gutierrez
Esa es una tradición que siempre me hace dedicar tiempo a depurar problemas con las fechas ... Preguntarme cuántas horas de trabajo desperdiciadas causó esta tradición.
Vedmant
102

La verdadera respuesta a esta pregunta es que fue copiada java.util.Date, que también tenía esta peculiaridad. La prueba se puede encontrar en Twitter de Brendan Eich, el tipo que implementó originalmente JavaScript (incluido el Dateobjeto):

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

primer tweet

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

segundo tweet

Esto sucedió en 1995 y JDK 1.0 estaba en beta. Se lanzó en 1996. En 1997, salió JDK 1.1, que desaprobó la gran mayoría de funciones java.util.Date, moviéndolas a java.util.Calendar, pero incluso eso todavía tenía meses de base cero. Los desarrolladores hartos de esto crearon la biblioteca Joda-Time , que finalmente dio lugar a un java.timepaquete integrado en Java 8 (2014).

En resumen, Java tardó 18 años en obtener una API de fecha / hora correctamente diseñada, pero JavaScript todavía está atrapado en la edad oscura. De hecho, tenemos excelentes bibliotecas como Moment.js , date-fns y js-joda . Pero a partir de ahora, no hay nada más Dateintegrado en el lenguaje. Con suerte, esto cambiará en un futuro próximo.

Matt Johnson-Pinta
fuente
24
Ah ... Buena metodología de desarrollo basado en demostración.
Álvaro González
@ ÁlvaroGonzález Yo culparía al desarrollador original de JDK 1.0 que lo introdujo en primer lugar.
barell
30

Todo menos el día del mes se basa en 0, consulte aquí para obtener una lista completa que incluye rangos :)

En realidad, los días basados ​​en 1 son los extraños aquí ... por extraño que parezca. ¿Por qué se hizo esto? No lo sé ... pero probablemente sucedió en la misma reunión en la que se enyesaron y decidieron que el punto y coma era opcional.

Nick Craver
fuente
1
La cuestión de los días "basados ​​en unos" probablemente se deba a que nadie en su sano juicio crearía una matriz de nombres de cadenas para días (por ejemplo, { "first", "second", "third", ..., "twenty-seventh", ... }) e intentaría indexarla por tm_mday. Por otra parte, tal vez solo vieron la absoluta utilidad de hacer que uno de los errores sea una ocurrencia regular.
D.Shawley
¿Por qué los años no se basan en 0?
Vedmant
5

Siempre hay 12 meses en un año, por lo que las primeras implementaciones de C podrían haber usado una matriz estática de ancho fijo con índices 0..11.

Jonathan Julian
fuente
2
La implementación de Java Date / Calendar mantiene el soporte durante un mes adicional para algunos calendarios. en.wikipedia.org/wiki/Undecimber
Pointy
4

Es así en Java también ... Probablemente para convertir int a string (0 - jan ,, 1-feb), codificaron de esta manera ... porque podrían tener una matriz de cadenas (indexadas desde 0) de nombres de meses y estos meses números si comienzan desde 0, será mucho más fácil asignarlos a las cadenas del mes.

raj
fuente
3

Sé que en realidad no es una respuesta a la pregunta original, pero solo quería mostrarte mi solución preferida para este problema, que parece que nunca memorizo ​​ya que aparece de vez en cuando.

La pequeña función zerofill hace el truco llenando los ceros donde sea necesario, y se acaba de +1agregar el mes :

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

Pero sí, Date tiene una API bastante poco intuitiva, me estaba riendo cuando leí el Twitter de Brendan Eich.

Christof Kälin
fuente
2

Es posible que hayan considerado meses como una enumeración (el primer índice es 0) y días no, ya que no tienen un nombre asociado.

O más bien, pensaban que el número del día era la representación real del día (de la misma manera que los meses se representan como números en una fecha como el 31/12), como si pudiera hacer una enumeración con números como variables, pero en realidad Basado en 0.

Entonces, en realidad, durante los meses, tal vez pensaron que la representación de enumeración adecuada sería usar el nombre del mes, en lugar de números, y habrían hecho lo mismo si los días tuvieran una representación de nombre. Imagínese si dijéramos cinco de enero, seis de enero, en lugar de 5 de enero, 6 de enero, etc., entonces quizás también hubieran hecho una enumeración basada en 0 durante días ...

Quizás inconscientemente pensaron en una enumeración durante meses como {enero, febrero, ...} y durante días como {Uno, Dos, Tres, ...}, excepto los días en los que accedes al día como un número en lugar del nombre, como 1 por uno, etc., por lo que es imposible comenzar en 0 ...

Pat-Laugh
fuente
Deberías de clase dual a psicólogo. Sigue siendo un error que cometieron, pero al menos ahora entendemos por qué lo cometieron.
Zesty
0

Puede ser una falla, pero también es muy útil cuando desea representar los meses o el día de la semana como una cadena, puede crear una matriz como ['jan,' feb '... etc] [new Date () .getMonth ()] en lugar de ['', 'jan', feb ... etc] [new Date (). getMonth ()] o ['jan', 'feb' ... etc] [new Date ( ) .getMonth () - 1]

Los días del mes normalmente no tienen nombre, por lo que no creará matrices con nombres para ellos. En este caso, 1-31 es más fácil de manejar, por lo que debes restar 1 cada vez ...

Rogier
fuente
realmente no. Fácilmente podría restar uno. Crea más problemas de los que resuelve porque ahora, cuando haces cálculos con fechas, tienes que hacer manipulaciones específicas en el mes con bastante frecuencia.
Rey