如何检查日期是否在特定范围内?

新手上路,请多包涵

我有一系列包含开始日期和结束日期的范围。我想检查日期是否在该范围内。

Date.before() 和 Date.after() 使用起来似乎有点别扭。我真正需要的是这样的伪代码:

 boolean isWithinRange(Date testDate) {
    return testDate >= startDate && testDate <= endDate;
}

不确定它是否相关,但我从数据库中提取的日期有时间戳。

原文由 Mike Sickler 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答
boolean isWithinRange(Date testDate) {
   return !(testDate.before(startDate) || testDate.after(endDate));
}

对我来说似乎并不尴尬。请注意,我是这样写的,而不是

return testDate.after(startDate) && testDate.before(endDate);

因此即使 testDate 正好等于其中一个最终案例,它也能正常工作。

原文由 Paul Tomblin 发布,翻译遵循 CC BY-SA 2.5 许可协议

tl;博士

ZoneId z = ZoneId.of( "America/Montreal" );  // A date only has meaning within a specific time zone. At any given moment, the date varies around the globe by zone.
LocalDate ld =
    givenJavaUtilDate.toInstant()  // Convert from legacy class `Date` to modern class `Instant` using new methods added to old classes.
                     .atZone( z )  // Adjust into the time zone in order to determine date.
                     .toLocalDate();  // Extract date-only value.

LocalDate today = LocalDate.now( z );  // Get today’s date for specific time zone.
LocalDate kwanzaaStart = today.withMonth( Month.DECEMBER ).withDayOfMonth( 26 );  // Kwanzaa starts on Boxing Day, day after Christmas.
LocalDate kwanzaaStop = kwanzaaStart.plusWeeks( 1 );  // Kwanzaa lasts one week.
Boolean isDateInKwanzaaThisYear = (
    ( ! today.isBefore( kwanzaaStart ) ) // Short way to say "is equal to or is after".
    &&
    today.isBefore( kwanzaaStop )  // Half-Open span of time, beginning inclusive, ending is *exclusive*.
)

半开

日期时间工作通常采用“半开”方法来定义时间跨度。开始是 包容 的,结束是 排他 的。因此,从星期一开始的一周会一直持续到(但不包括)下一个星期一。

java.time

Java 8 及更高版本带有内置的 java.time 框架。补充了旧的麻烦类,包括 java.util.Date/.CalendarSimpleDateFormat 。受成功的 Joda-Time 库的启发。由 JSR 310 定义。由 ThreeTen-Extra 项目扩展。

InstantUTC 时间轴上的一个时刻,分辨率为纳秒级。

Instant

将您的 java.util.Date 对象转换为 Instant 对象。

 Instant start = myJUDateStart.toInstant();
Instant stop = …

如果从数据库中通过JDBC获取 java.sql.Timestamp 对象,同样 转换为java.time.Instant 。 A java.sql.Timestamp 已经在 UTC 中,因此无需担心时区。

 Instant start = mySqlTimestamp.toInstant() ;
Instant stop = …

获取当前时刻进行比较。

 Instant now = Instant.now();

使用方法 isBefore、isAfter 和 equals 进行比较。

 Boolean containsNow = ( ! now.isBefore( start ) ) && ( now.isBefore( stop ) ) ;

LocalDate

也许您只想处理日期,而不是一天中的时间。

LocalDate 类表示仅日期值,没有时间和时区。

 LocalDate start = LocalDate.of( 2016 , 1 , 1 ) ;
LocalDate stop = LocalDate.of( 2016 , 1 , 23 ) ;

要获取当前日期,请指定时区。在任何给定时刻,今天的日期因时区而异。例如,巴黎的新一天比蒙特利尔早。

 LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) );

我们可以使用 isEqualisBeforeisAfter 方法进行比较。在日期时间工作中,我们通常使用半开方法,其中时间跨度的开始是 包含 的,而结束是 包含的。

 Boolean containsToday = ( ! today.isBefore( start ) ) && ( today.isBefore( stop ) ) ;

Interval

如果您选择将 ThreeTen-Extra 库添加到您的项目中,则可以使用 Interval 类来定义时间跨度。该类提供了测试间隔是否 包含邻接包围重叠 其他日期时间/间隔的方法。

Interval 类适用于 Instant 对象。 Instant 类表示 UTC 时间轴上的一个时刻,分辨率为 纳秒(最多九 (9) 位小数)。

我们可以将 LocalDate 调整为特定时刻,一天中的第一时刻,通过指定时区得到 ZonedDateTime 。从那里我们可以通过提取 Instant 返回到 UTC。

 ZoneId z = ZoneId.of( "America/Montreal" );
Interval interval =
    Interval.of(
        start.atStartOfDay( z ).toInstant() ,
        stop.atStartOfDay( z ).toInstant() );
Instant now = Instant.now();
Boolean containsNow = interval.contains( now );


关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

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

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

在哪里获得 java.time 类?

ThreeTen-Extra 项目扩展了 java.time 附加类。该项目是未来可能添加到 java.time 的试验场。您可能会在这里找到一些有用的类,例如 IntervalYearWeekYearQuarter 等等

原文由 Basil Bourque 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题