如何检查时间段与java中的另一个时间段重叠

时间:2013-06-14 10:44:29

标签: java time

如何检查时间段与同一天的另一个时间段重叠。

例如,

  1. 上午7:00至上午10:30与上午10:00至11:30重叠
  2. 上午7:00至上午10:30与上午8:00至上午9:00重叠
  3. 上午7:00至上午10:30与上午5:00至上午8:00重叠

5 个答案:

答案 0 :(得分:29)

有一个简单的解决方案,在此表示为实用方法:

public static boolean isOverlapping(Date start1, Date end1, Date start2, Date end2) {
    return start1.before(end2) && start2.before(end1);
}

此代码要求在两个句点之间共享至少一毫秒才能返回true

如果相邻的时间段被认为是“重叠”(例如10:00-10:30和10:30-11:00),逻辑需要稍微调整一下:

public static boolean isOverlapping(Date start1, Date end1, Date start2, Date end2) {
    return !start1.after(end2) && !start2.after(end1);
}

这种逻辑经常出现在数据库查询中,但同样的方法适用于任何上下文。

一旦你意识到它有多简单,你首先要自己踢,然后把它放在银行里!

答案 1 :(得分:4)

JOda时间有functionality baked in。它是非常精心构建的,并且在JSR路由上替换损坏的Java Calendar API。您应该考虑使用它。

答案 2 :(得分:3)

TL;博士

( startA.isBefore( stopB ) ) && ( stopA.isAfter( startB ) ) 

LocalTime

如果您确实希望使用没有日期和时区上下文的通用时间,请使用LocalTime类。

LocalTime startA = LocalTime.of( 7 , 0 );
LocalTime stopA = LocalTime.of( 10 , 30 );

LocalTime startB = LocalTime.of( 10 , 0 );
LocalTime stop2B = LocalTime.of( 11 , 30 );

验证数据,确保结束在开头之后(或相等)。一种简单的说法是“开始不是在结束之后”。

Boolean validA = ( ! startA.isAfter( stopA ) ) ;
Boolean validB = ( ! startB.isAfter( stop2B ) ) ;

this AnswerMeno Hochschild,使用半开方法定义开头包含的时间范围,而结尾为 exclusive ,我们可以使用这个逻辑:

  

(StartA< EndB)和(EndA> StartB)

Boolean overlaps = ( 
    ( startA.isBefore( stopB ) ) 
    && 
    ( stopA.isAfter( startB ) ) 
) ;

请注意,LocalTime仅限于24小时通用。时间不能超过午夜,不能缠绕到另一个。其他日子还有

ZonedDateTime

如果要测试时间轴上的实际时刻,则必须将这些时间对象调整为日期和时区的上下文。应用ZoneId获取ZonedDateTime对象。

ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( z );
ZonedDateTime zdt = ZonedDateTime.of( today , startA , z);

关于java.time

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

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore

答案 3 :(得分:1)

如果打开间隔(例如,某些进程尚未完成),结束日期可能为null:

public static boolean isOverlapping(Date start1, Date end1, Date start2, Date end2)
{
    return
            ((null == end2) || start1.before(end2)) &&
            ((null == end1) || start2.before(end1)) ;
}

答案 4 :(得分:1)

编辑:

以下是工作方法:

public boolean isOverlapping(Date von1, Date bis1, Date von2, Date bis2) {
    return von1.compareTo(bis2) <= 0 && bis1.compareTo(von2) >= 0;
}

这是每个人都可以尝试的证明:

@Test
public void isOverlapping_base() {
    Assert.assertTrue(isOverlapping(getDate(2014, 1, 1),
            getDate(2014, 3, 31), getDate(2014, 1, 2),
            getDate(2014, 4, 1)));

    Assert.assertTrue(isOverlapping(getDate(2014, 1, 2),
            getDate(2014, 4, 1), getDate(2014, 1, 1),
            getDate(2014, 3, 31)));

    Assert.assertTrue(isOverlapping(getDate(2014, 1, 1),
            getDate(2014, 4, 1), getDate(2014, 1, 2),
            getDate(2014, 3, 31)));

    Assert.assertTrue(isOverlapping(getDate(2014, 1, 2),
            getDate(2014, 3, 31), getDate(2014, 1, 1),
            getDate(2014, 4, 1)));

    Assert.assertFalse(isOverlapping(getDate(2014, 1, 1),
            getDate(2014, 1, 31), getDate(2014, 3, 1),
            getDate(2014, 3, 31)));

    Assert.assertFalse(isOverlapping(getDate(2014, 3, 1),
            getDate(2014, 3, 31), getDate(2014, 1, 1),
            getDate(2014, 1, 31)));
}

Date getDate(int year, int month, int date) {
    Calendar working = Calendar.getInstance();
    working.set(year, month - 1, date, 0, 0, 0); 
    working.set(Calendar.MILLISECOND, 0);
    return working.getTime();
}