**(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, i.e., 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)`