JavaScript 中比较两个日期:指南
作者:社区 / 开发者
2024 年 6 月 26 日
导航至
在 JavaScript 中比较两个日期——这听起来像是应该轻而易举的任务。但实际上,这样的比较可能很棘手。原因有两方面。
首先,时间处理是一项比许多开发者认为的更难的任务。其次,JavaScript 是一种以其...嗯,怪癖而闻名的语言。
因此,如果您对 JavaScript 中的日期比较感到有些困惑,请知道 (a) 您并不孤单,并且 (b) 这篇文章是为您而作的。我们将首先简要解释 JavaScript 中的日期对象及其工作原理。之后,我们将深入学习一个教程,您将在其中学习如何使用多种方法在 JavaScript 中执行日期比较。
让我们深入了解。
JavaScript 日期:基础知识
JavaScript 中日期和时间操作的基本工作原理很容易理解。一切都围绕 Date 展开,这是一个内置的 JavaScript 对象。尽管名称如此,Date 对象存储日期和时间信息。
让我们看一个快速示例。
let now = new Date();
console.log(now);
如果我使用 Node.js 运行上面的代码,它会显示如下结果:2024-02-24T14:39:56.879Z。当我们实例化一个新的 Date 对象而不带任何参数时,该对象将根据系统时钟设置为当前日期和时间。显示的日期根据 ISO-8601 标准格式化,并且采用 UTC 时间。UTC 也称为祖鲁时间,因此末尾带有 Z。
使用 Google Chrome DevTools,行为有所不同。这是一个屏幕截图: 在这种情况下,结果是 Sat Feb 24 2024 11:55:12 GMT-0300 (Horário Padrão de Brasília)。它以我的时区(巴西标准时间)显示日期。为了澄清,Date 对象本身不包含有关时区名称的任何信息。它确实包含与 UTC 的偏移量——即,我们与 UTC 相差多少小时。
我可以通过对之前的示例稍作修改来展示这一点
let now = new Date();
console.log(now.getTimezoneOffset());
运行上面的代码后,我得到的结果是 180。这个数字表示我们与 UTC 相差的分钟数——换句话说,三个小时。然而,非常违反直觉的是,如果我们落后于 UTC,它会返回一个正数,如果我们超前于 UTC,则返回一个负数。
Date 在 JavaScript 中的另一个相关特征是,与许多其他语言的等价物不同,此对象是可变的——换句话说,它可以更改
let date = new Date('2024-02-01T14:20:10Z');
console.log(date);
date.setHours(15);
console.log(date);
date.setFullYear(2025);
console.log(date);
以及结果
2024-02-01T14:20:10.000Z
2024-02-01T18:20:10.000Z
2025-02-01T18:20:10.000Z2024-02-01T14:20:10.000Z
2024-02-01T18:20:10.000Z
2025-02-01T18:20:10.000Z
因此,总结一下,Date JavaScript 对象
- 尽管名称如此,但包含有关日期和时间的信息
- 不知道它属于哪个时区,但包含与 UTC 的偏移量
- 是可变的
现在,让我们继续进行日期比较!
如何在 JavaScript 中比较两个日期?
首先,回答这个问题:以下代码将显示什么?
let date1 = new Date('2024-02-01T14:20:10Z');
let date2 = new Date('2024-02-01T14:20:10Z');
console.log(date1 == date2 ? "Equal" : "Not Equal");
您可能会感到惊讶,但答案是 Not Equal。这种行为的解释很简单:Date 是一个对象,因此是一种引用类型。当用于对象时,相等 (==) 运算符评估它们存储的引用是否指向内存中的同一对象。在上面的代码中,我们实例化 Date 两次,这意味着内存中有两个对象,每个对象都有其唯一的引用,分配给一个变量。
我们将必须使用 getTime() 方法来正确执行此操作。此方法返回一个整数数字,它是自 Unix 纪元(即 1970 年 1 月 1 日 00:00:00 UTC)以来的毫秒数。然后,您可以使用此数字执行比较
let date1 = new Date('2024-02-01T14:20:10Z');
let date2 = new Date('2024-02-01T14:20:10Z');
console.log(date1.getTime() == date2.getTime() ? "Equal" : "Not Equal");
Number 是一种原始类型,因此相等运算符的行为符合您的预期,代码显示 Equal。
使用运算符比较日期
您刚刚看到,使用相等运算符在 JavaScript 中比较日期不起作用——除非您尝试比较它们的引用。但是其他运算符呢?您可以使用大于 (>) 和小于 (<) 运算符来评估一个 Date 是否在另一个 Date 之前或之后吗?是的,绝对可以。
let januaryFirst = new Date(2024, 0, 1);
let februaryFirst = new Date(2024, 1, 1);
if (februaryFirst > januaryFirst) {
` console.log(“是的,确实二月在正月之后。”);`
}
if (januaryFirst < februaryFirst) {
` console.log(“是的,正月也确实在二月之前。”);`
}
是的,上面的代码是正确的。当您在 JavaScript 中将月份值作为参数传递时,它必须是基于零的。当我运行上面的代码时,它显示了预期的消息
是的,确实二月在正月之后。
是的,正月也确实在二月之前。
好的,太棒了。但是,以下代码片段呢?在不运行它的情况下,您能告诉我将显示什么吗?
let first = new Date(2024, 1, 10, 14, 5, 25);
let second = new Date(2024, 1, 10, 14, 5, 25);
if (first >= second) {
` console.log(“第一个日期在第二个日期之后,或者它们相同。”);`
} else {
` console.log(“第一个日期在第二个日期之前。”);`
}
别卖关子了。这是答案
第一个日期在第二个日期之后,或者它们相同。
嗯,在这种情况下,相等运算符确实有效。这里发生了什么?请记住,JavaScript 不仅是一种动态语言,而且是一种弱类型语言。它经常代表您进行类型强制转换,结果可能会令人困惑,但有时非常有用。
在这种情况下,当您对 Date 对象使用大于等于或小于等于运算符时,JavaScript 会将其值转换为数字,调用 getTime() 方法。然后,就只是像往常一样比较数字的问题了。
您可以在 JavaScript 中将字符串转换为日期以进行比较吗?
有时,您的日期和时间存储为字符串,您需要比较它们。此处的推荐方法是将它们转换为 Date 对象,然后进行比较。当然,这种方法的成功与否取决于字符串的格式。
如果您幸运的话,字符串中的值将使用 ISO-8601 标准格式化,在这种情况下,比较轻而易举
let first = new Date('2024-02-24T13:02:05Z');
let second = new Date('2024-02-25T13:02:05Z');
console.log(first.getTime() == second.getTime() ? "Equal": "Different");
如果您的字符串不是这种格式怎么办?好吧,在原生 JavaScript 支持方面,您就没那么幸运了。在这种情况下,您可以依赖第三方库或编写自己的解析实用程序。因此,这里的技巧是尽可能坚持使用 ISO-8601!
您可以比较没有时间组件的日期吗?
如您所见,Date 对象存储日期和一天中的时间。但通常,您希望可以比较两个 Date 对象,而忽略时间组件。您该怎么做呢?
有两种主要解决方案。一种是利用 Date 的可变性,将其小时设置为 0,然后执行比较
let first = new Date('2024-02-24T13:02:05Z');
let second = new Date('2024-02-24T18:02:05Z');
first.setHours(0, 0, 0);
second.setHours(0, 0, 0);
console.log(first.getTime() === second.getTime() ? 'Same' : 'Different');
上面的解决方案有效。它的优点是简单且不需要大量代码。它的最大缺点是会改变值,这可能会带来意想不到的后果,因此,在大多数情况下应避免这样做。
另一种选择是将日期分解为其年、月和日的值,然后比较这些值
function compareDatesOnly(date1, date2) {
` const d1 = new Date(date1);`
` const d2 = new Date(date2);`
` const year1 = d1.getFullYear();`
` const month1 = d1.getMonth();`
` const day1 = d1.getDate();`
` const year2 = d2.getFullYear();`
` const month2 = d2.getMonth();`
` const day2 = d2.getDate();`
` return year1 === year2 && month1 === month2 && day1 === day2;`
}
let date1 = '2024-02-24T13:02:05Z';
let date2 = '2024-02-24T18:02:05Z';
console.log(compareDatesOnly(date1, date2) ? 'Same' : 'Different');
在上面的代码中,我们使用 getFullYear()、getMonth() 和 getDate() 方法从两个对象中提取单独的日期组件,然后逐个比较它们。
第二个解决方案使用了更多代码,但它是一种更好的方法,因为它不会改变原始对象。
JavaScript 日期处理总结
在这篇文章中,您学习了如何在 JavaScript 中比较日期。您了解了 Date 对象、如何实例化它以及它的工作原理。您了解了一些应避免的陷阱。
让我们回顾一下它们并添加更多内容
- 请记住,月份作为参数值传递时是基于零的。
- 不要使用相等运算符比较两个 Date 对象;相反,使用 getCurrentTime() 转换它们,然后再进行比较。
- 当您使用无效值(例如 3 月 31 日)实例化 Date 时,它不会失败;相反,它会静默地“溢出”到下一个有效值。请注意这一点,并始终验证外部输入。
- 存储日期值时,请坚持使用 UTC 和 ISO-8601。
时间和日期操作是一个引人入胜且混乱的主题。这篇文章只是触及了表面。作为下一步,请继续探索 Date 对象,然后开始探索 JavaScript 国际化 API。您还可以考虑使用 InfluxDB 的时间序列数据,使用 JS 客户端库。
这篇文章由 Carlos Schults 撰写。Carlos 是一位技术娴熟的软件工程师,也是众多客户的杰出技术作家。他的热情在于探究事物的本质(原始来源),并以平易近人且信息丰富的技术内容吸引读者。