给定两个日期范围,确定两个日期是否重叠的最简单或最有效的方法是什么?

例如,假设我们有由DateTime变量StartDate1到EndDate1和StartDate2到EndDate2表示的范围。


当前回答

这是我的Java解决方案,它也适用于无限区间

private Boolean overlap (Timestamp startA, Timestamp endA,
                         Timestamp startB, Timestamp endB)
{
    return (endB == null || startA == null || !startA.after(endB))
        && (endA == null || startB == null || !endA.before(startB));
}

其他回答

本文《.NET时间段库》通过枚举PeriodRelation描述了两个时间段之间的关系:

// ------------------------------------------------------------------------
public enum PeriodRelation
{
    After,
    StartTouching,
    StartInside,
    InsideStartTouching,
    EnclosingStartTouching,
    Enclosing,
    EnclosingEndTouching,
    ExactMatch,
    Inside,
    InsideEndTouching,
    EndInside,
    EndTouching,
    Before,
} // enum PeriodRelation

答案对我来说太简单了,所以我创建了一个更通用的动态SQL语句,用于检查某人是否有重叠的日期。

SELECT DISTINCT T1.EmpID
FROM Table1 T1
INNER JOIN Table2 T2 ON T1.EmpID = T2.EmpID 
    AND T1.JobID <> T2.JobID
    AND (
        (T1.DateFrom >= T2.DateFrom AND T1.dateFrom <= T2.DateTo) 
        OR (T1.DateTo >= T2.DateFrom AND T1.DateTo <= T2.DateTo)
        OR (T1.DateFrom < T2.DateFrom AND T1.DateTo IS NULL)
    )
    AND NOT (T1.DateFrom = T2.DateFrom)

使用Java util.Date,这里是我所做的。

    public static boolean checkTimeOverlaps(Date startDate1, Date endDate1, Date startDate2, Date endDate2)
    {
        if (startDate1 == null || endDate1 == null || startDate2 == null || endDate2 == null)
           return false;

        if ((startDate1.getTime() <= endDate2.getTime()) && (startDate2.getTime() <= endDate1.getTime()))
           return true;

        return false;
    }

此处发布的解决方案不适用于所有重叠范围。。。

----------------------|-------A-------|----------------------
    |----B1----|
           |----B2----|
               |----B3----|
               |----------B4----------|
               |----------------B5----------------|
                      |----B6----|
----------------------|-------A-------|----------------------
                      |------B7-------|
                      |----------B8-----------|
                         |----B9----|
                         |----B10-----|
                         |--------B11--------|
                                      |----B12----|
                                         |----B13----|
----------------------|-------A-------|----------------------

我的工作解决方案是:

AND (
  ('start_date' BETWEEN STARTDATE AND ENDDATE) -- caters for inner and end date outer
  OR
  ('end_date' BETWEEN STARTDATE AND ENDDATE) -- caters for inner and start date outer
  OR
  (STARTDATE BETWEEN 'start_date' AND 'end_date') -- only one needed for outer range where dates are inside.
) 

如果您使用的日期范围尚未结束(仍在进行中),例如未设置endDate='0000-00-00'您不能使用BETWEEN,因为0000-00-00不是有效日期!

我使用了这个解决方案:

(Startdate BETWEEN '".$startdate2."' AND '".$enddate2."')  //overlap: starts between start2/end2
OR (Startdate < '".$startdate2."' 
  AND (enddate = '0000-00-00' OR enddate >= '".$startdate2."')
) //overlap: starts before start2 and enddate not set 0000-00-00 (still on going) or if enddate is set but higher then startdate2

如果startdate2高于enddate,则没有重叠!