Java 中日期比较:教程
作者:社区 / 开发者
2024 年 4 月 3 日
导航至
您很难找到一个完全没有时间操作的应用程序。特别是日期比较,在调度、事件管理、供应和物流等领域至关重要,仅举几例。无论编程语言如何,情况都是如此,但在本文中,我们将为您提供 Java 日期比较指南。
我们将以简要介绍 Java 中用于日期和时间的两个可用 API 以及为什么在 Java 8 发布时发布了新 API 来开始这篇博客。然后,我们将深入学习本教程,您将在其中学习如何在 Java 中比较日期。
让我们开始吧。
两个日期/时间 API 的故事
在 Java 中,您有两个 API——两组类和方法——用于执行时间操作。旧的 API 由来自 java.util 包的类组成,例如 Date 和 Calendar。新的 API——Java Time API——提供了一系列属于 java.time 包的类,以更全面、更稳健地处理时间。
为什么 Java 创建者引入了新的 API?简而言之,旧的 API 存在许多问题,包括:
- 类是可变的,因此不是线程安全的。
- 设计不足,缺乏处理时间时必要的常见概念的类型。
- 缺乏对时区处理逻辑的支持。
正如我们提到的,Java Time API 是在 Java 8 发布时引入的,并且从那时起一直是 Java 中处理时间的推荐方法。在本教程中,我们将在大多数示例中使用新的 API。在撰写本文时,我的机器上安装了 Java 21,这是最新的 LTS(长期支持)版本。
为了内容的完整性,我们将简要讨论 java.util.Date 和 java.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 天。它只是代表了以人为中心的、基于日历的月份概念。来自 LocalDate 的 plus() 方法足够智能,可以确定在生成新值时它应该有效添加多少天。
在上面的所有警告之后,您如何比较期间?没有什么太令人惊讶的: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 日期比较:以正确的方式进行
处理时间是编程中的日常任务,但它比许多开发人员认为的要困难。这在所有编程语言中都是如此:Python、C#、Java——它们都很复杂。
在本文中,我们探讨了时间处理的一个特定方面:Java 日期比较。Java 8 带来了丰富的新时间 API,提供了许多类来表示日期和时间的不同方面。正如您所看到的,使用 Java Time API 比较日期非常容易。如果您正在处理时间戳数据作为应用程序的关键部分,那么值得查看 InfluxDB 和 Java 客户端库,这使得在 Java 中存储和查询数据变得容易。
这篇文章由 Carlos Schults 撰写。Carlos 是一位技术精湛的软件工程师,也是众多客户的优秀技术作家。他的热情是深入了解事物的本质(原始来源),并以平易近人且信息丰富的技术内容吸引读者。