Determine Whether Two Date Ranges Overlap

Given two date ranges, what is the simplest or most efficient way to determine whether the two date ranges overlap?

As an example, suppose we have ranges denoted by DateTime variables StartDate1 to EndDate1 and StartDate2 to EndDate2 .


(StartA <= EndB) and (EndA >= StartB)

Proof:
Let ConditionA Mean that DateRange A Completely After DateRange B
_ |---- DateRange A ------| |---Date Range B -----| _
(True if StartA > EndB )

Let ConditionB Mean that DateRange A is Completely Before DateRange B
|---- DateRange A -----| _ _ |---Date Range B ----|
(True if EndA < StartB )

Then Overlap exists if Neither A Nor B is true -
(If one range is neither completely after the other,
nor completely before the other, then they must overlap.)

Now one of De Morgan's laws says that:

Not (A Or B) <=> Not A And Not B

Which translates to: (StartA <= EndB) and (EndA >= StartB)


NOTE: This includes conditions where the edges overlap exactly. If you wish to exclude that,
change the >= operators to > , and <= to <


NOTE2. Thanks to @Baodad, see this blog, the actual overlap is least of:
{ endA-startA , endA - startB , endB-startA , endB - startB }

(StartA <= EndB) and (EndA >= StartB) (StartA <= EndB) and (StartB <= EndA)


NOTE3. Thanks to @tomosius, a shorter version reads:
DateRangesOverlap = max(start1, start2) < min(end1, end2)
This is actually a syntactical shortcut for what is a longer implementation, which includes extra checks to verify that the start dates are on or before the endDates. Deriving this from above:

If start and end dates can be out of order, ie, if it is possible that startA > endA or startB > endB , then you also have to check that they are in order, so that means you have to add two additional validity rules:
(StartA <= EndB) and (StartB <= EndA) and (StartA <= EndA) and (StartB <= EndB) or:
(StartA <= EndB) and (StartA <= EndA) and (StartB <= EndA) and (StartB <= EndB) or,
(StartA <= Min(EndA, EndB) and (StartB <= Min(EndA, EndB)) or:
(Max(StartA, StartB) <= Min(EndA, EndB)

But to implement Min() and Max() , you have to code, (using C ternary for terseness),:
(StartA > StartB? Start A: StartB) <= (EndA < EndB? EndA: EndB)


我相信只要说两个范围重叠就足够了:

(StartDate1 <= EndDate2) and (StartDate2 <= EndDate1)

This article Time Period Library for .NET describes the relation of two time periods by the enumeration PeriodRelation :

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

在这里输入图像描述

链接地址: http://www.djcxy.com/p/9220.html

上一篇: 任何人都知道缺乏枚举通用约束的一个很好的解决方法?

下一篇: 确定两个日期范围是否重叠