在Joda时间包含日期范围检查tl;博士java.time半开式关于 java.time

2022-09-01 16:40:03

我正在使用Joda Time 2.1库。

我已经编写了一个方法来比较给定日期是否在日期范围之间。我希望它包括开始日期和结束日期。我已经使用,因为我不想考虑时间部分只有日期部分。LocalDate

下面是它的代码。

isDateBetweenRange(LocalDate start,LocalDate end,LocalDate target){

       System.out.println("Start Date : "
              +start.toDateTimeAtStartOfDay(DateTimeZone.forID("EST"));

       System.out.println("Target Date : "
              +targettoDateTimeAtStartOfDay(DateTimeZone.forID("EST"));

       System.out.println("End Date : "
              +end.toDateTimeAtStartOfDay(DateTimeZone.forID("EST"));

       System.out.println(target.isAfter(start));

       System.out.println(target.isBefore(end));
}

上述方法的输出为:

Start Date: 2012-11-20T00:00:00.000-05:00
Target Date: 2012-11-20T00:00:00.000-05:00
End Date : 2012-11-21T00:00:00.000-05:00
target.isAfter(start) : false
target.isBefore(end) : true

我的问题是假的,即使日期和具有相同的值。target.isAfter(start)targetstart

我想要这样,但在这里它只考虑.
我希望它包容。target >= starttarget > start

这是否意味着该方法仅查找匹配项?isAfter

我已经浏览了Joda Time的javadoc,但没有找到任何关于它的信息。


答案 1

是的,是排他性的,否则它应该被命名或类似的东西。isAfterisEqualOrAfter

解决方案:使用“不在之前”而不是“之后”,使用“不在之后”而不是“之前”。

boolean isBetweenInclusive(LocalDate start, LocalDate end, LocalDate target) {
    return !target.isBefore(start) && !target.isAfter(end);
}

答案 2

tl;博士

Joda-Time已被java.time类和ThreeTen-Extra项目所取代。

表示时间跨度的 和 类使用半开定义。因此,询问是否包含开头返回 。LocalDateRangeIntervaltrue

LocalDateRange.of(                     // `org.threeten.extra.LocalDateRange` class represents a pair of `LocalDate` objects as a date range.
    LocalDate.of( 2018, 8 , 2 ) ,      // `java.time.LocalDate` class represents a date-only value, without time-of-day and without time zone.
    LocalDate.of( 2018 , 8 , 20 ) 
)                                      // Returns a `LocalDateRange` object.
.contains(
    LocalDate.now()                    // Capture the current date as seen in the wall-clock time used by the people of the JVM’s current default time zone.
)

java.time

仅供参考,Joda-Time项目现在处于维护模式,团队建议迁移到java.time类。请参阅 Oracle 的教程

仅日期

显然,您可能关心日期而不是一天中的时间。如果是这样,请使用 LocalDate 类。

要管理日期范围,请将 ThreeTen-Extra 库添加到项目中。这使您可以访问 LocalDateRange 类。

该类提供了几种比较方法:、 包含、重叠、和 。abutsenclosesequalsintersectionisBeforeisAfterisConnectedspanunion

LocalDateRange r = 
    LocalDateRange.of( 
        LocalDate.of( 2018, 8 , 2 ) , 
        LocalDate.of( 2018 , 8 , 20 ) 
    ) 
;

LocalDate target = LocalDate.now( ZoneId.of( "Africa/Tunis" ) ) ;  // Capture the current date as seen in the wall-clock time used by the people of a particular time zone.
boolean contains = r.contains( target ) ;

日期时间

如果您关心特定时区的日期和时间,请使用类。ZonedDateTime

从你的 开始,让该类决定一天中的第一刻。由于夏令时 (DST) 等异常情况,一天并不总是从 00:00:00 开始。LocalDate

以 的格式指定适当的时区名称,例如 美国/蒙特利尔非洲/卡萨布兰卡或 。切勿使用3-4个字母的缩写,例如或因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。continent/regionPacific/AucklandESTIST

ZoneId z = ZoneId.of( "America/Montreal" ) ;  // Or "America/New_York", etc.
ZonedDateTime zdtStart = LocalDate.of( 2018, 8 , 2 ).atStartOfDay( z ) ;
ZonedDateTime zdtStop = LocalDate.of( 2018, 8 , 20 ).atStartOfDay( z ) ;
ZonedDateTime zdtTarget = ZonedDateTime.now( z ) ;

ThreeTen-Extra 表示一个范围。此类表示一对对象。An 是 UTC 中的一个时刻,始终处于 UTC 状态。我们可以通过简单地提取一个 .相同的时刻,时间轴上的相同点,不同的挂钟时间。IntervalInstantInstantInstant

Instant instantStart = zdtStart.toInstant() ;
Instant instantStop = zdtStop.toInstant() ;
Instant instantTarget = zdtTarget.toInstant() ;

Interval interval = Interval.of( instantStart , intervalStop ) ;
boolean contains = interval.contains( instantTarget ) ;

半开式

定义时间跨度的最佳方法通常是半开式方法。这意味着开始是包容性的,而结局是排他性的

上面看到的范围类中的比较( &)都使用半开方法。因此,询问开始日期或开始时刻是否包含在范围中会导致 .ThreeTen-ExtraLocalDateRangeIntervaltrue


关于 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的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuarter