Comparação de objetos de data JavaScript

86

Ao comparar objetos de data em Javascript, descobri que mesmo comparando a mesma data não retorna verdadeiro.

 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

Como posso comparar a igualdade dessas datas? Estou interessado em utilizar o Dateobjeto nativo de JS e não quaisquer bibliotecas de terceiros, pois não é apropriado usar um JS de terceiros apenas para comparar as datas.

Harshana
fonte
15
Excelente exemplo de como isso é mal projetado em JavaScript.
devios1

Respostas:

131

Isso ocorre porque, no segundo caso, os objetos de data reais são comparados e dois objetos nunca são iguais um ao outro. Forçá-los a numerar:

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

Se você quiser uma conversão mais explícita em número, use:

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

ou

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

Oh, uma referência à especificação: §11.9.3 O Algoritmo de Comparação de Igualdade Abstrata que basicamente diz ao comparar objetos, obj1 == obj2é verdadeiro apenas se eles se referem ao mesmo objeto, caso contrário, o resultado é falso.

RobG
fonte
5
@AndrewD. usar igual estrito neste caso particular não faz nenhuma diferença nos resultados, isso porque o operador igual nos exemplos, está sempre lidando com operandos do mesmo tipo, @RobG está convertendo os valores explicitamente em Número (exemplo 1 e 3) ou no exemplo 2, sabemos que Date.prototype.getTimesempre retornará um Número ...
Christian C. Salvadó
12
Para sua informação, há uma diferença significativa de desempenho entre essas abordagens: jsperf.com/date-equality-comparison
Nick Zalutskiy
2
@ Nick - mesmo a versão mais lenta leva menos de um microssegundo para ser executada, portanto, embora haja diferenças comparativas, em termos absolutos a diferença de desempenho é insignificante. O OP deve apenas escolher a abordagem mais adequada, provavelmente usando getTimeé o melhor para maior clareza (e acontece de ser mais rápido nos navegadores que testei também).
RobG
2
@RobG Você sabe, você está absolutamente certo. =) Eu estava escrevendo uma biblioteca e fiz um teste "just cuz." No software real, não faz diferença alguma.
Nick Zalutskiy de
24

Compare as datas usando o getTime()número de retorno de milissegundos da época (ou seja, um 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

Considere também o uso do Dateconstrutor usando um número explícito de ano / mês / data em vez de confiar na representação de string (consulte: Date.parse () ). E lembre-se de que as datas em JavaScript são sempre representadas usando o fuso horário do cliente (navegador).

Tomasz Nurkiewicz
fonte
1
+1 para o comentário sobre o uso de strings como argumento para Date ().
RobG
16

Você não precisa usar o método getTime - você pode subtrair um objeto de data de outro objeto de data. Ele retornará a diferença de milissegundos (negativo, se o segundo for uma data posterior)

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

var diff= (startDate1 -startDate2)

// avalia como 0 se as datas tiverem o mesmo carimbo de data / hora

kennebec
fonte
+1 simples e elegante, solução preferida da IMO: usa a funcionalidade de avaliação de Data integrada sem a necessidade de coerção para um carimbo de data
gdibble
5

você pode comparar os milissegundos reais:

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

Você também pode usar a função 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
fonte