关于在Javascript中比较日期你应该知道的一切
与日期打交道是开发人员经常遇到的事情。从创建到存储和处理日期,Javascript中的日期操作在应用程序开发中有很多用例。在今天的教程中,我们想把重点放在其中一个方面:比较日期。
Javascript内置的日期对象为我们提供了足够的功能来比较日期,特别是为寻找快速和简单的解决方案。不过在本教程的最后,我们将稍微研究一下如何在第三方库的帮助下在Javascript中比较日期。
我们可以使用逻辑运算符进行日期比较吗?
Javascript的日期对象是否支持使用逻辑运算符(如<,>,===,==? )进行日期间的比较 这就是我们在本节中要找出的问题。
事实证明,使用小于(<)和大于(>)运算符来比较Javascript的日期是这个问题最直接的解决方案之一,正如下面的例子所示:
const date1 = new Date("2021-01-31")
const date2 = new Date("2021-04-21")
const date3 = new Date("2021-05-09")
console.log(date1 > date2) //false
console.log(date1 < date2) //true
console.log(date2 < date3) //true
console.log(date2 > date3) //false
但是当我们使用相等的运算符来检查两个日期是否相同时,对于两个相等的日期,== 或=== 都不会返回正确的结果:
const date1 = new Date("2021-01-31")
const date2 = new Date("2021-04-21")
const date3 = new Date("2021-01-31")
console.log(date1) //2021-01-31T00:00:00.000Z
console.log(date2) //2021-04-21T00:00:00.000Z
console.log(date3) //2021-01-31T00:00:00.000Z
console.log(date1 == date2) //false
console.log(date1 === date2) //false
console.log(date1 == date3) //false
console.log(date1 === date3) //false
console.log(date1 !== date3) //true
console.log(date1 != date3) //true
这种行为是由Javascript的基本性质造成的。在Javascript中,无论你使用的是严格 (===) 还是抽象平等 (==) 操作符,两个不同的对象都不可能相等。
因此,当你想涵盖日期比较的所有三个基础时,你必须使用不同于逻辑运算符的方法来获得正确的结果。
用getTime方法进行日期比较
因此,作为在Javascript中比较日期和时间的另一种方法,我们可以使用日期对象的内置方法,getTime 。getTime 方法返回从纪元时间(1970年1月1日00:00:00(UTC))到日期对象所代表的日期时间所经历的毫秒数。这为两个日期之间更简单的数字比较做了铺垫,我们可以使用所有的逻辑运算符而没有任何奇怪的行为。
下面是一个getTime方法的操作例子:
const date1 = new Date("2021-01-31")
const date2 = new Date("2021-04-21")
const date3 = new Date("2021-01-31")
console.log(date1.getTime() > date2.getTime()) //false
console.log(date1.getTime() < date2.getTime()) //true
console.log(date1.getTime() === date3.getTime()) //true
console.log(date1.getTime() !== date3.getTime()) //false
使用getTime方法而不是直接进行日期对象比较的一个好处是,它的工作速度比其他方法快。
使用valueOf的日期时间比较
Javascript中的另一个日期比较方法是valueOf。这个方法也会返回自纪元时间以来所经历的毫秒数。下面是我们如何在我们的代码中使用它:
console.log(date1.valueOf() > date2.valueOf()) //false
console.log(date1.valueOf() < date2.valueOf()) //false
console.log(date1.valueOf() === date3.valueOf()) //true
console.log(date1.valueOf() !== date3.valueOf()) //false
在Javascript中只进行日期比较
到目前为止,我们所有的例子在比较日期的时候都考虑了日期的时间部分。但是我们可以在Javascript中只比较日期对象的日期部分吗?答案是肯定的。
但是,由于Javascript没有提供一个内置的方法来直接进行这种类型的比较,我们必须从其他一些函数中得到帮助,以达到我们所要的最终结果。
简而言之,我们必须从初始对象中分别提取年、月、日的成分,以便在没有时间的情况下比较日期。
在下面的例子中,我们分享一个方法,在getFullYear, getMonth, getDate内置的Javascript方法的帮助下,检查两个日期之间的相等关系:
function isDateEqual(date1, date2) {
return date1.getFullYear() === date2.getFullYear() &&
date1.getMonth() === date2.getMonth() &&
date1.getDate() === date2.getDate()
}
const date1 = new Date("2021-01-31T09:11:12Z")
const date2 = new Date("2021-04-21T12:10:34Z")
const date3 = new Date("2021-01-31T03:34:23Z")
console.log(isDateEqual(date1, date2))
console.log(isDateEqual(date1, date3))
作为上述解决方案的替代方案,我们可以在使用getTime或valueOf方法比较日期之前,将日期对象的时间部分改为共享值,这样可以防止其时间值影响结果。
如果你的用例是不会受到初始数据变化的影响,你可以很容易地进行比较,就像下面的例子所示。否则,你可以选择克隆初始对象,并继续进行这种实现:
const date1 = new Date("2021-01-31T09:11:12Z")
const date2 = new Date("2021-04-21T12:10:34Z")
const date3 = new Date("2021-01-31T03:34:23Z")
date1.setHours(0, 0, 0, 0)
date2.setHours(0, 0, 0, 0)
date3.setHours(0, 0, 0, 0)
console.log(date1.getTime() > date2.getTime()) //false
console.log(date1.getTime() < date2.getTime()) //true
console.log(date1.getTime() === date3.getTime()) //true
console.log(date1.getTime() !== date3.getTime()) //false
我们也可以使用toDateString方法只提取一个对象的日期部分,来比较没有时间的日期。下面是你如何实现的:
date1 = new Date(date1.toDateString())
date2 = new Date(date2.toDateString())
date3 = new Date(date3.toDateString())
console.log(date1.getTime() > date2.getTime()) //false
console.log(date1.getTime() < date2.getTime()) //true
console.log(date1.getTime() === date3.getTime()) //true
console.log(date1.getTime() !== date3.getTime()) //false
将时区纳入考虑范围
在Javascript中处理日期时,有一件事我们必须非常小心,就是时区差异。即使我们在比较日期时也是如此。那么,时区对我们到目前为止所做的一切有什么影响呢?
在使用getTime和valueOf方法进行比较时,Javascript测量的时间与它的纪元时间有关,即UTC。因此,即使我们比较在两个时区创建的两个日期,这些方法也能输出我们期望看到的正确结果:
const date1 = new Date("2021-01-31T09:11:12+05:00")
const date2 = new Date("2021-01-31T05:11:12+01:00")
console.log(date1.getTime() === date2.getTime()) //true
但是,当我们在有选择地挑选年、月、日(如isDateEqual函数)后比较没有时间成分的日期时,我们必须意识到时区对这个过程的影响。在这种情况下,如果不直接从对象中提取日期成分,首先,我们必须将它们转换为UTC:
let date1 = new Date("2021-01-31T09:11:12+05:00")
let date2 = new Date("2021-01-31T05:11:12+01:00")
date1 = new Date(Date.UTC(date1.getUTCFullYear(), date1.getUTCMonth(), date1.getUTCDate()))
date2 = new Date(Date.UTC(date2.getUTCFullYear(), date2.getUTCMonth(), date2.getUTCDate()))
console.log(date1.getTime() === date2.getTime()) //true
console.log(date1.getTime() !== date2.getTime()) //false
用date-fns比较日期
到目前为止,我们只依靠Javascript的本地日期对象来比较日期。尽管它提供了足够的方法来执行基本的比较,但我们不得不使用几行代码来实现更高级的东西,比如不含时间的日期比较。
然而,像date-fns这样的第三方日期操作库有专门的方法,允许我们用一行代码就能解决这些问题。因此,我们认为这是一个好主意,看看如何在日期-fns库的帮助下,在Javascript中执行日期比较。
我们可以使用date-fns的isAfter、isBefore、isEqual方法来检查两个日期是否相等、大于或小于,正如下面的例子所示:
let date1 = new Date("2021-01-31T09:11:12Z")
let date2 = new Date("2021-04-21T12:10:34Z")
let date3 = new Date("2021-01-31T05:11:12Z")
//Is first date after the second one
console.log(datefns.isAfter(date1, date2)) //false
console.log(datefns.isAfter(date2, date1)) //true
//Is first date before the second one
console.log(datefns.isAfter(date1, date3)) //true
console.log(datefns.isAfter(date3, date1)) //false
//Is first date equal to second one
console.log(datefns.isEqual(date1, date3)) //true
console.log(datefns.isEqual(date1, date2)) //false
对于不考虑时间的比较,我们可以使用isSameDay函数,像这样。
console.log(datefns.isSameDay(date1, date3)) //true
console.log(datefns.isSameDay(date1, date2)) //false
就是这样!我们可以通过调用一个函数找到问题的答案。
摘要
在今天的教程中,我们带领大家学习了如何在Javascript中比较日期。虽然原生的Javascript对象给了我们足够的功能来处理这项任务,但如果你必须在你的应用程序中进行不同的比较操作,使用第三方库可以简化你的实现,并清理代码。
无论你喜欢哪种日期比较方式,我们希望你喜欢我们的文章,并在今天学到一些新的东西,你会发现在你的下一个项目中很有用。
谢谢您的阅读!