乔达时间
至于添加依赖项,恐怕 java.util.Date 和 .Calendar 真的太糟糕了,以至于我对任何新项目做的第一件事就是添加 Joda-Time 库。在 Java 8 中,您可以使用受 Joda-Time 启发的新 java.time 包。
Joda-Time 的核心是DateTime 类。与 java.util.Date 不同,它了解其分配的时区 (DateTimeZone)。从 j.u.Date 转换时,分配一个区域。
DateTimeZone zone = DateTimeZone.forID( "America/Montreal" );
DateTime dateTimeQuébec = new DateTime( date , zone );
LocalDate
验证两个日期时间是否在同一日期的一种方法是转换为LocalDate 对象。
该转换取决于指定的时区。要比较 LocalDate 对象,它们必须已转换为相同的区域。
这是一个实用的小方法。
static public Boolean sameDate ( DateTime dt1 , DateTime dt2 )
{
LocalDate ld1 = new LocalDate( dt1 );
// LocalDate determination depends on the time zone.
// So be sure the date-time values are adjusted to the same time zone.
LocalDate ld2 = new LocalDate( dt2.withZone( dt1.getZone() ) );
Boolean match = ld1.equals( ld2 );
return match;
}
最好是另一个参数,指定时区而不是假设应该使用第一个 DateTime 对象的时区。
static public Boolean sameDate ( DateTimeZone zone , DateTime dt1 , DateTime dt2 )
{
LocalDate ld1 = new LocalDate( dt1.withZone( zone ) );
// LocalDate determination depends on the time zone.
// So be sure the date-time values are adjusted to the same time zone.
LocalDate ld2 = new LocalDate( dt2.withZone( zone ) );
return ld1.equals( ld2 );
}
字符串表示
另一种方法是创建每个日期时间的日期部分的字符串表示,然后比较字符串。
同样,指定的时区至关重要。
DateTimeFormatter formatter = ISODateTimeFormat.date(); // Static method.
String s1 = formatter.print( dateTime1 );
String s2 = formatter.print( dateTime2.withZone( dt1.getZone() ) );
Boolean match = s1.equals( s2 );
return match;
时间跨度
通用的解决方案是定义一个时间跨度,然后询问该跨度是否包含您的目标。此示例代码在 Joda-Time 2.4 中。请注意,“午夜”相关的类已被弃用。而是使用withTimeAtStartOfDay 方法。 Joda-Time 提供三个类以各种方式表示时间跨度:Interval、Period 和 Duration。
使用“半开”方法,其中跨度的开头包含在内,结尾不包含在内。
目标的时区可以与区间的时区不同。
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );
DateTime target = new DateTime( 2012, 3, 4, 5, 6, 7, timeZone );
DateTime start = DateTime.now( timeZone ).withTimeAtStartOfDay();
DateTime stop = start.plusDays( 1 ).withTimeAtStartOfDay();
Interval interval = new Interval( start, stop );
boolean containsTarget = interval.contains( target );
java.time
Java 8 及更高版本附带java.time 框架。受 Joda-Time 启发,由 JSR 310 定义,并由 ThreeTen-Extra 项目扩展。见Tutorial。
Joda-Time 的制造者已指示我们所有人在方便时尽快迁移到 java.time。与此同时,Joda-Time 继续作为一个积极维护的项目。但预计未来的工作只会发生在 java.time 和 ThreeTen-Extra 而不是 Joda-Time。
简单总结一下 java.time……Instant 是 UTC 时间线上的一个时刻。应用时区 (ZoneId) 以获取 ZonedDateTime 对象。要离开时间线,要获得日期时间的模糊不确定概念,请使用“本地”类:LocalDateTime、LocalDate、LocalTime。
本答案的 Joda-Time 部分中讨论的逻辑适用于 java.time。
旧的 java.util.Date 类有一个新的 toInstant 方法用于转换为 java.time。
Instant instant = yourJavaUtilDate.toInstant(); // Convert into java.time type.
确定日期需要时区。
ZoneId zoneId = ZoneId.of( "America/Montreal" );
我们将该时区对象应用于Instant 以获得ZonedDateTime。从中我们提取一个仅日期值(LocalDate),因为我们的目标是比较日期(不是小时、分钟等)。
ZonedDateTime zdt1 = ZonedDateTime.ofInstant( instant , zoneId );
LocalDate localDate1 = LocalDate.from( zdt1 );
对我们需要比较的第二个java.util.Date 对象执行相同的操作。我将只使用当前时刻。
ZonedDateTime zdt2 = ZonedDateTime.now( zoneId );
LocalDate localDate2 = LocalDate.from( zdt2 );
使用特殊的isEqual 方法来测试相同的日期值。
Boolean sameDate = localDate1.isEqual( localDate2 );