Java 中日期比较:教程

导航至

您很难找到一个完全没有时间操作的应用程序。特别是日期比较,在调度、事件管理、供应和物流等领域至关重要,仅举几例。无论编程语言如何,情况都是如此,但在本文中,我们将为您提供 Java 日期比较指南。

我们将以简要介绍 Java 中用于日期和时间的两个可用 API 以及为什么在 Java 8 发布时发布了新 API 来开始这篇博客。然后,我们将深入学习本教程,您将在其中学习如何在 Java 中比较日期。

让我们开始吧。

两个日期/时间 API 的故事

在 Java 中,您有两个 API——两组类和方法——用于执行时间操作。旧的 API 由来自 java.util 包的类组成,例如 DateCalendar。新的 API——Java Time API——提供了一系列属于 java.time 包的类,以更全面、更稳健地处理时间。

为什么 Java 创建者引入了新的 API?简而言之,旧的 API 存在许多问题,包括:

  • 类是可变的,因此不是线程安全的。
  • 设计不足,缺乏处理时间时必要的常见概念的类型。
  • 缺乏对时区处理逻辑的支持。

正如我们提到的,Java Time API 是在 Java 8 发布时引入的,并且从那时起一直是 Java 中处理时间的推荐方法。在本教程中,我们将在大多数示例中使用新的 API。在撰写本文时,我的机器上安装了 Java 21,这是最新的 LTS(长期支持)版本。

为了内容的完整性,我们将简要讨论 java.util.Datejava.util.Calendar 类,但不应将它们用于新的开发。

闲话少说,让我们深入了解。

如何在 Java 中比较两个日期?

Java Time API 的一个有趣的方面是它提供了许多不同的类型,每种类型代表日期和时间的不同方面。因此,我们将一次教您一种 Java 日期比较类型。

Java LocalDate 类

LocalDate 类表示不带时间组件的日期。“local”后缀表示它与创建它的上下文有关。例如,它没有关于时区的信息。

让我们看看如何创建两个实例并比较它们

var a = LocalDate.of(2024, 2, 5);

var b = LocalDate.of(2024, 2, 6);

System.out.println(a.isEqual(b) ? "相同" : "不同");

if (a.isBefore(b)) {

` System.out.println(“‘a’ 在 ‘b’ 之前”);`

}

为了解释上面的代码

  • 首先,我们实例化两个 LocalDate 对象,将它们分别设置为 2024 年 2 月 5 日和 2 月 6 日。
  • 然后,我们使用 isEqual() 方法比较它们的相等性,结果显示“不同”。
  • 最后,我们使用 isBefore() 方法验证其中一个日期是否在另一个日期之前。

不出所料,还有一个我们可以使用的 isAfter() 方法。

Java LocalTime 类

LocalTime 类类似于 LocalDate 类;它仅表示本地时间,不带日期组件。与其日期对应类相似,它也没有时区意识。

让我们看看如何实例化这个类。

var t1 = LocalTime.of(8, 0, 0);

var t2 = LocalTime.of(8, 0, 1);

比较呢?相同的方法可用(isEqual()、 isBefore()isAfter())。

Java LocalDateTime 类

LocalDateTime 类存储日期和时间数据。让我们看看如何获取一个全新的 LocalDateTime 对象

var now = LocalDateTime.now();

var tomorrow = now.plusDays(1);

var date = LocalDateTime.of(2024, 2, 5, 8, 0, 1);

var date2 = LocalDateTime.of(2024, 2, 5, 8, 0, 1);

对于比较?相同的方法集也适用于这里。

Java Duration 类

Duration 类表示一段时间的持续时间,例如 5 分钟、10 小时等。以下是一些实例化两个对象的代码

Duration sixtyMinutes = Duration.ofMinutes(60);

Duration oneHour = Duration.ofHours(1);

这次我克制住了自己 C# 程序员的本性,没有使用类型推断。正如您所看到的,我们使用 ofMinutes() 静态工厂方法创建一个对象,并使用 ofHours() 方法创建另一个对象。这两个对象是等效的,我们应该能够比较它们以证明这一点。与之前的类不同,Duration 类没有 isEqual() 方法。

因此,我们必须求助于默认的 equals() 方法

if (oneHour.equals(sixtyMinutes)) {

` System.out.println(“相等”);`

} else {

` System.out.println(“不同”);`

}

太棒了,但是如果您比较两个持续时间以确定哪个更长怎么办?这就是 compareTo() 方法的用武之地。如果值相等,该方法返回 0;如果调用该方法的值更长,则返回 1;如果作为参数传递的值更长,则返回 -1。您想要一个例子吗?

Duration someDuration = Duration.ofMinutes(60);

Duration anotherDuration = Duration.ofMinutes(70);

var result = someDuration.compareTo(anotherDuration);

switch (result)

{

` case 0:`

` System.out.println(“它们相等。”);`

` break;`

` case 1:`

` System.out.println(“第一个持续时间更长。”);`

` break;`

` case -1:`

` System.out.println(“第二个持续时间更长。”);`

` break;`

}

运行上面的代码,您将看到它显示“第二个持续时间更长。”

Java Period 类

Period 类与 Duration 类类似,表示时间间隔。但是它们之间有什么区别呢?简而言之,Period 类表示基于日历的时间间隔,例如“两个月”、“一年”等等。

一个例子将有助于澄清。在以下代码中,我将:

  • 实例化一个 LocalDate 对象
  • 创建一个表示一个月的 Period 对象
  • Period 对象添加到 LocalDate 并验证结果

LocalDate januaryFirst = LocalDate.of(2024, 1, 1);

Period oneMonth = Period.ofMonths(1);

LocalDate janFirstPlusOneMonth = januaryFirst.plus(oneMonth);

System.out.println(janFirstPlusOneMonth); // displays "2024-02-01"

我想您会同意上面的结果并不令人惊讶。现在让我们调整示例,将开始日期设为 2 月 1 日。

LocalDate febFirst = LocalDate.of(2024, 2, 1);

Period oneMonth = Period.ofMonths(

LocalDate febFirstPlusOneMonth = febFirst.plus(oneMonth);

System.out.println(febFirstPlusOneMonth); // displays "2024-03-01"

也许您对上面的结果感到惊讶,也许您没有。也许不清楚我想表达什么,所以我将明确说明。从 1 月 1 日到 2 月 1 日,我们有 31 天。从 2 月 1 日到 3 月 1 日,我们有 29 天——当然,通常是 28 天,但 2024 年是闰年。

正在发生的事情是我们上面创建的 Period 对象不关心一个月是否有 28、29、30 或 31 天。它只是代表了以人为中心的、基于日历的月份概念。来自 LocalDateplus() 方法足够智能,可以确定在生成新值时它应该有效添加多少天。

在上面的所有警告之后,您如何比较期间?没有什么太令人惊讶的:equals()compareTo() 方法可用,并且可以按预期工作。

Period p1 = Period.ofMonths(1);

Period p2 = Period.parse("P1M");

if (p1.equals(p2)) {

` System.out.println(“当然它们是相等的”);`

}

对于上面示例中的第二个值,我使用了一种不同的方法创建了实例:我根据 ISO-8601 标准化的格式 解析了期间的文本表示形式。我这样做只是为了增加一些变化,但结果是相同的。

旧时代:Date 和 Calendar 类

正如您在本文中学到的,Java 8 引入了改进的日期和时间 API。从那时起已经十年了,我建议您将新类用于所有的时间处理需求。

尽管如此,您仍然可能会偶然发现以旧 API 方式编写的遗留代码,因此熟悉 java.util 类可能会派上用场。

让我们看一个比较两个日期的例子

Calendar feb10Calendar = new GregorianCalendar(2024, Calendar.FEBRUARY, 10);

Calendar feb15Calendar = new GregorianCalendar(2024, Calendar.FEBRUARY, 15);

Date date1 = feb10Calendar.getTime();

Date date2 = feb15Calendar.getTime();

if (date1.equals(date2)) {

` System.out.println(“它们是相同的”);`

} else {

` System.out.println(“它们不相同”);`

}

var comp = date1.compareTo(date2);

switch (comp)

{

` case 0:`

` System.out.println(“它们是相同的”);`

` break;`

` case 1:`

` System.out.println(“第一个日期在第二个日期之后”);`

` break;`

` case -1:`

` System.out.println(“第二个日期在第一个日期之后”);`

` break;`

}

上面的代码不需要解释,因为比较看起来与之前的一些示例相同,除了创建日期本身需要更多的 仪式

Java 日期比较:以正确的方式进行

处理时间是编程中的日常任务,但它比许多开发人员认为的要困难。这在所有编程语言中都是如此:PythonC#、Java——它们都很复杂。

在本文中,我们探讨了时间处理的一个特定方面:Java 日期比较。Java 8 带来了丰富的新时间 API,提供了许多类来表示日期和时间的不同方面。正如您所看到的,使用 Java Time API 比较日期非常容易。如果您正在处理时间戳数据作为应用程序的关键部分,那么值得查看 InfluxDBJava 客户端库,这使得在 Java 中存储和查询数据变得容易。

这篇文章由 Carlos Schults 撰写。Carlos 是一位技术精湛的软件工程师,也是众多客户的优秀技术作家。他的热情是深入了解事物的本质(原始来源),并以平易近人且信息丰富的技术内容吸引读者。