Java - 比较两个日期值的月份和年份

4

我有一个需求,需要比较两个日期,如果它们的月份/年份相同,则返回true,否则返回false。根据我的搜索,我找到了以下解决方案。是否有更好的方法来进行此比较?

Calendar cal1 = Calendar.getInstance();
    Calendar cal2 = Calendar.getInstance();
    cal1.setTime(date1);
    cal2.setTime(date2);
    boolean sameDay = cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&
                      cal1.get(Calendar.MONTH) == cal2.get(Calendar.MONTH);

1
这个问题应该重新开放,因为它并不是“不清楚”。这个问题问如何判断一对日期是否共享相同的年份和月份。非常简单的问题,也是一个合理的问题。例如,两张信用卡是否共享相同的到期年月。 - Basil Bourque
3个回答

11

简述

比较两个日期,如果它们的月份/年份相同

有没有其他更好的方法来进行比较?

是的,更好的方式使用现代的 java.time 类。

YearMonth.from(                                   // Represent the year-month without a day-of-month, without a time-of-day, and without a time zone.
    LocalDate.of( 2018 , Month.JANUARY , 23 ) ,   // Represent a date-only, without a time-of-day and without a time zone.
)                                                 // Returns a `YearMonth` object.
.equals(                                          // Compare one `YearMonth` object to another.
    YearMonth.now()                               // Capture today’s year-month as seen in the JVM’s current default time zone.
)

详情

是的,有一种更好的方式。

您正在使用最早版本Java捆绑的旧日期时间类。这些类被证明设计不佳、令人困惑和麻烦。请避免使用它们,包括java.util.Date。

java.time

那些旧的类已经被内置于Java 8及以后版本的java.time框架所取代。

Instant

将给定的java.util.Date对象转换为Instant对象,在UTC时间轴上表示一个时刻。

Instant i1 = myJavaUtilDate1.toInstant();
Instant i2 = myJavaUtilDate2.toInstant();

我们的目标是获取YearMonth对象,因为您只关心年份和月份。但要达到这个目标,我们需要应用时区。年份和月份只有在特定时区的情况下才有意义,除非您来自冰岛,否则我怀疑您不想要UTC的年/月上下文。

ZoneId

因此,我们需要指定所需/期望的时区(ZoneId)。
ZoneId zoneId = ZoneId.of( "America/Montreal" );

ZonedDateTime

将该时区应用于每个Instant,生成ZonedDateTime对象。

ZonedDateTime zdt1 = ZonedDateTime.ofInstant( i1 , zoneId );
ZonedDateTime zdt2 = ZonedDateTime.ofInstant( i2 , zoneId );

YearMonth

现在提取 YearMonth 对象。

YearMonth ym1 = YearMonth.from( zdt1 );
YearMonth ym2 = YearMonth.from( zdt2 );

比较。

Boolean same = ym1.equals( ym2 );

顺便提一下,您可能还有其他与年份和月份相关的业务逻辑。请记住,java.time类现在已经内置到Java中。因此,您可以在整个代码库中使用和传递YearMonth对象,而不是重新计算或传递字符串。


关于 java.time

java.time 框架内置于 Java 8 及以上版本。这些类代替了老旧的 遗留 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

Joda-Time 项目现在处于 维护模式,建议迁移到 java.time 类。

了解更多信息,请参阅 Oracle 教程。并搜索 Stack Overflow 获取许多示例和解释。规范是 JSR 310

您可以直接与数据库交换 java.time 对象。使用符合 JDBC 4.2 或更高版本的 JDBC 驱动程序。无需字符串,也无需 java.sql.* 类。

如何获取 java.time 类?

ThreeTen-Extra 项目扩展了 java.time 的附加类。该项目是 java.time 可能未来增加的类的试验场。您可以在这里找到一些有用的类,例如 Interval, YearWeek, YearQuarter更多


1

快速方法: 使用JodaTime库。

  • 首先,请确保您已经下载/实现了它。
  • 然后导入。
import org.joda.time.LocalDate;
import java.util.Date;

这是您需要的:
Date Date1 = new Date();
Date Date2 = new Date();

if (new LocalDate(Date1).getYear() == new LocalDate(Date2).getYear()) {
 // Year Matches
 if (new LocalDate(Date1).getMonthOfYear() == new LocalDate(Date2).getMonthOfYear()) {
  // Year and Month Matches
 }
}

0

您可以使用 date1.getYear() == date2.getYear() && date1.getMonth() == date2.getMonth()


3
getYear()等已被弃用。 - Keith Loughnane
getYear()getMonth() 不仅已经被弃用,自 1997 年 2 月起就已被弃用,因为它们在跨时区的情况下工作不可靠。而且整个 Date 类设计不佳,早已过时。如果无法避免使用 Date 类,可以按照 Basil Bourque 的答案将其转换为 ZonedDateTime - Ole V.V.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接