JavaScript日期对象比较

97

在 JavaScript 中比较日期对象时,我发现即使是比较相同的日期也不返回 true。

 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

我该如何比较这些日期的相等性?我希望利用 JS 的本地 Date 对象,而不是任何第三方库,因为使用第三方 JS 库来仅仅比较日期并不合适。


21
这是JavaScript设计不佳的一个很好的例子。 - devios1
7个回答

148

这是因为在第二种情况下,实际的日期对象会进行比较,而两个不同的对象永远不会相等。将它们强制转换成数字:

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

如果你想更明确地将值转换为数字,可以使用以下两种方法之一:

 alert( startDate2.getTime() == startDate3.getTime() ); // true
或者
 alert( Number(startDate2) == Number(startDate3) ); // true

噢,参考规范 §11.9.3 “抽象相等比较算法”,它基本上表明,在比较对象时,当且仅当obj1 == obj2引用同一对象时为true,否则结果为false。


5
在这种情况下使用严格相等运算符对结果没有任何影响,这是因为在示例中,相等运算符总是处理相同类型的操作数。@RobG 明确将值转换为数字(示例 1 和 3),或者在示例 2 中,我们知道 Date.prototype.getTime 总是返回一个数字... - Christian C. Salvadó
13
了解,这些方法之间存在显著的性能差异:http://jsperf.com/date-equality-comparison - Nick Zalutskiy
2
@Nick——即使最慢的版本运行时间不到一微秒,因此虽然存在比较差异,但在绝对意义上,性能差异是可以忽略不计的。OP应该选择最适合自己的方法,很可能使用getTime最清晰明了(并且在我测试的浏览器中也是最快的)。 - RobG
2
@RobG 你知道吗,你说得完全正确。=)我当时是在写一个库并进行了一次测试"只是因为感觉要测一下"。但在实际软件中,这完全没有任何区别。 - Nick Zalutskiy
显示剩余5条评论

30

使用getTime()比较日期,该函数返回自纪元以来的毫秒数(即一个数字):

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

还要考虑使用显式年/月/日数字的Date构造函数,而不是仅依赖于字符串表示(请参见:Date.parse())。并且请记住,JavaScript中的日期始终使用客户端(浏览器)时区表示。


1
对于在Date()中使用字符串作为参数的评论,我同意。 - RobG

18

您无需使用getTime方法-可以从另一个日期对象中减去一个日期对象。它将返回毫秒差异(如果第二个日期较晚,则为负数)

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

var diff= (startDate1 -startDate2)

// 如果两个日期的时间戳相同,则计算结果为0


+1 简单而优雅,我认为这是首选解决方案:它使用内置的日期评估功能,无需将其强制转换为数字时间戳。 - gdibble
1
日期的数字强制转换速度比读取 date.getTime() 慢得多(对我来说几乎慢了10倍),如果有人在阅读此内容时关心这个问题。这是一个性能比较:tinyurl.com/3c5svafe(它是一个 perf.link 链接,但 SO 不允许我使用 tinyurl 链接)。 - Jayant Bhawal

5

您可以比较实际的毫秒数:

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

3

简短概述

使用date.getTime()进行比较。
根据我的测试,它比下一个最快的替代方案(date.valueOf())至少快25%。

详细信息

我在2022年发现了这个。正如其他人已经说过的那样,像date1.getTime() === date2.getTime()这样进行比较是正确的方式。

有人在答案中分享了一个jsperf链接,但现在似乎已经失效了,所以我决定自己添加一些性能比较。

我创建了两个包含1000个日期的数组。所有日期都将是不同的实例(这意味着直接使用===检查会失败),因此这个基准测试的作用是测试将日期转换为原始值的最快方法。

以下是测试数据:

const data1 = Array.from({length: 1000}, () => new Date())
const data2 = Array.from({length: 1000}, () => new Date())

以下是测试用例(链接中还有更多):

// 1
data1.forEach((d1, i) => d1.getTime() === data2[i].getTime());

// 2
data1.forEach((d1, i) => d1.valueOf() === data2[i].valueOf());

// 3
data1.forEach((d1, i) => Number(d1) === Number(data2[i]));

// 4
data1.forEach((d1, i) => d1.toISOString() === data2[i].toISOString());

结果(使用date.getTime()

date.getTime()转换速度更快并不意外。它比date.valueOf()快约25%,比其他所有方法都要快10倍至100倍(据我所知)。

此外,引入可选链会使最佳情况变慢,在我的测试中减缓了近10%的速度。我发现这很有趣。date.valueOf()相对于其非可选链对应部分也降低了5%的速度。

data1.forEach((d1, i) => d1?.getTime() === data2[i]?.getTime());

Benchmark link: here

以下是一张图片,以防将来上面的链接失效。

基准测试图像


0

比较两个日期的另一种方法是在日期之前使用“+”运算符将日期转换为时间戳。

因此,假设我们有两个日期:

const dateOne = new Date("10 January 1986")
const dateTwo = new Date("10 December 2020")
if(+dateOne == +dateTwo){
  //do something
}

等等。

如果您正在排序日期对象,那么在排序回调函数中可以使用此功能非常方便。

0

你也可以使用函数 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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接