Comparación de objetos de fecha de JavaScript

86

Al comparar objetos de fecha en Javascript, descubrí que incluso comparar la misma fecha no devuelve verdadero.

 var startDate1 = new Date("02/10/2012");
 var startDate2 = new Date("01/10/2012");
 var startDate3 = new Date("01/10/2012");
 alert(startDate1>startDate2); // true
 alert(startDate2==startDate3); //false

¿Cómo comparar la igualdad de estas fechas? Estoy interesado en utilizar el Dateobjeto nativo de JS y no bibliotecas de terceros, ya que no es apropiado usar un JS de terceros solo para comparar las fechas.

Harshana
fuente
15
Excelente ejemplo de cómo esto está mal diseñado en JavaScript.
devios1

Respuestas:

131

Esto se debe a que en el segundo caso, los objetos de fecha reales se comparan y dos objetos nunca son iguales entre sí. Obligarlos a numerar:

 alert( +startDate2 == +startDate3 ); // true

Si desea una conversión más explícita a un número, use:

 alert( startDate2.getTime() == startDate3.getTime() ); // true

o

 alert( Number(startDate2) == Number(startDate3) ); // true

Oh, una referencia a la especificación: §11.9.3 El algoritmo de comparación de igualdad abstracta que básicamente dice que cuando se comparan objetos, obj1 == obj2es verdadero solo si se refieren al mismo objeto; de lo contrario, el resultado es falso.

RobG
fuente
5
@AndrewD. el uso de estrictos iguales en este caso particular no hace ninguna diferencia en los resultados, esto se debe a que el operador igual en los ejemplos, siempre está tratando con operandos del mismo tipo, @RobG está convirtiendo los valores explícitamente a Número (ejemplo 1 y 3) o en el ejemplo 2, sabemos que Date.prototype.getTimesiempre devolverá un Número ...
Christian C. Salvadó
12
Para su información, hay una diferencia de rendimiento significativa entre estos enfoques: jsperf.com/date-equality-comparison
Nick Zalutskiy
2
@ Nick: incluso la versión más lenta tarda menos de un microsegundo en ejecutarse, por lo que aunque existen diferencias comparativas, en términos absolutos, la diferencia de rendimiento es insignificante. El OP debería elegir el enfoque que mejor se adapte, probablemente el uso getTimesea ​​mejor para mayor claridad (y resulta que es más rápido en los navegadores que probé también).
RobG
2
@RobG Sabes, tienes toda la razón. =) Estaba escribiendo una biblioteca e hice una prueba "solo porque". En el software real no hay ninguna diferencia.
Nick Zalutskiy
1
@ Johannes: consulte ¿ Para qué se usa unary + en Javascript? y El operador unario + .
RobG
24

Compare las fechas utilizando el getTime()número de milisegundos de retorno de la época (es decir, un número):

var startDate1 = new Date("02/10/2012");
var startDate2 = new Date("01/10/2012");
var startDate3 = new Date("01/10/2012");
alert(startDate1.getTime() > startDate2.getTime()); // true
alert(startDate2.getTime() == startDate3.getTime()); //true

También considere usar el Dateconstructor tomando un número explícito de año / mes / fecha en lugar de confiar en la representación de cadena (ver: Date.parse () ). Y recuerde que las fechas en JavaScript siempre se representan usando la zona horaria del cliente (navegador).

Tomasz Nurkiewicz
fuente
1
+1 para el comentario sobre el uso de cadenas como argumento para Date ().
RobG
16

No es necesario utilizar el método getTime; puede restar un objeto de fecha de otro objeto de fecha. Devolverá la diferencia de milisegundos (negativo, si el segundo es una fecha posterior)

var startDate1 = new Date("02/10/2012");
var startDate2 = new Date("01/10/2012");

var diff= (startDate1 -startDate2)

// evalúa a 0 si las fechas tienen la misma marca de tiempo

Kennebec
fuente
+1 simple y elegante, solución preferida de imo: esto usa la funcionalidad de evaluación de fecha incorporada sin la necesidad de coerción a una marca de tiempo numérica
gdibble
5

puede comparar los milisegundos reales:

alert(startDate2.getTime() === startDate3.getTime());
gion_13
fuente
0

También puede utilizar la función valueOf ()

 var startDate1 = new Date("02/10/2012").valueOf();
 var startDate2 = new Date("01/10/2012").valueOf();
 var startDate3 = new Date("01/10/2012").valueOf();
 alert(startDate1>startDate2); // 1326150000000 > 1328828400000   true
 alert(startDate2==startDate3); // 1328828400000 > 1326150000000  false
PeteBaser
fuente