JavaScript 中比较两个日期:指南

导航到

在 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 也称为 Zulu 时间,因此末尾有 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,它返回一个负数。

JavaScript中Date对象的另一个相关特征是,与其他许多语言中的等效对象不同,这个对象是可变的——换句话说,它可以改变。

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

所以,总结一下,JavaScript的Date对象

  • 尽管其名称,但包含有关日期和时间的详细信息
  • 不知道它属于哪个时区,但包含相对于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中的日期不起作用——除非你试图比较它们的引用。但是其他运算符呢?你能使用大于号(>)和小于号(<)运算符评估一个日期是否在另一个日期之前吗?是的,绝对可以。

let januaryFirst = new Date(2024, 0, 1);

let februaryFirst = new Date(2024, 1, 1);

if (februaryFirst > januaryFirst) {

` console.log(“Yes, indeed February comes after January.”);`

}

if (januaryFirst < februaryFirst) {

` console.log(“Also, indeed January comes before February.”);`

}

是的,上面的代码是正确的。当你在JavaScript中将值month作为参数传递时,它必须是零基的。当我运行上面的代码时,它会显示预期的消息

是的,确实二月是在一月之后。

同样,确实一月是在二月之前。

好的,太棒了。但是,以下代码段会显示什么?在不运行它的情况下,你能告诉我会显示什么吗?

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(“The first date is after the second, or they’re the same.”);`

} else {

` console.log(“The first date comes before the second one.”);`

}

不再神秘了。这是答案

第一个日期在第二个日期之后,或者它们是相同的。

在这种情况下,等号运算符确实是工作的。这里发生了什么?请记住,JavaScript不仅仅是一种动态语言,它还是一种弱类型语言。它经常会自动转换类型,有时结果可能令人困惑,但有时也非常有用。

在这种情况下,当你在Date对象上使用大于等于或小于等于运算符时,JavaScript会将其值转换为数字,调用< strong>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');

在上面的代码中,我们使用< strong>getFullYear()、< strong>getMonth()和< strong>getDate()方法从两个对象中提取单个日期组件,然后逐个进行比较。

第二种方法使用的代码更多,但它是一种更好的方法,因为它不会改变原始对象。

JavaScript日期处理总结

在这篇文章中,你学习了如何在JavaScript中比较日期。你了解了Date对象、如何实例化它以及它是如何工作的。你还了解了一些应该避免的陷阱。

让我们回顾一下,并添加一些更多的内容

  • 记住,当作为参数传递时,月份是零基的。
  • 不要使用等号运算符来比较两个Date对象;相反,使用< strong>getCurrentTime()将其转换为当前时间,然后进行比较。
  • 当你使用无效值创建Date对象时(例如,3月31日),它不会失败;相反,它会静默地“溢出”到下一个有效值。请留意这一点,并始终验证外部输入。
  • 存储日期值时请坚持使用UTC和ISO-8601。

时间和日期操作是一个既迷人又复杂的话题。本文仅触及了表面。作为下一步,继续探索日期对象,然后开始探索JavaScript 国际化API。您还可以考虑使用JS客户端库来处理时间序列数据。

本文由Carlos Schults撰写。Carlos是一位技术娴熟的软件工程师,同时也是一位经验丰富的技术作家,为多家客户提供服务。他热衷于深入探究事物本质(原始来源),并以其亲切且信息丰富的技术内容吸引读者。