python date interval intersection

Viewed 16218

As a matter of general interest I'm wondering if there's a more elegant/efficient way to do this. I have a function that compares two start/end tuples of dates returning true if they intersect.

from datetime import date
def date_intersection(t1, t2):
    t1start, t1end = t1[0], t1[1]
    t2start, t2end = t2[0], t2[1]

    if t1end < t2start: return False
    if t1end == t2start: return True
    if t1start == t2start: return True
    if t1start < t2start and t2start < t1end: return True
    if t1start > t2start and t1end < t2end: return True
    if t1start < t2start and t1end > t2end: return True
    if t1start < t2end and t1end > t2end: return True
    if t1start > t2start and t1start < t2end: return True
    if t1start == t2end: return True
    if t1end == t2end: return True 
    if t1start > t2end: return False

so if:

d1 = date(2000, 1, 10)
d2 = date(2000, 1, 11)
d3 = date(2000, 1, 12)
d4 = date(2000, 1, 13)

then:

>>> date_intersection((d1,d2),(d3,d4))
False
>>> date_intersection((d1,d2),(d2,d3))
True
>>> date_intersection((d1,d3),(d2,d4))
True

etc.

I'm curious to know if there's a more pythonic/elegant/more efficient/less verbose/generally better, way to do this with maybe mxDateTime or some clever hack with timedelta or set()?

An alternative and useful form would be for the function to return a start/end tuple of the intersection if one is found

Thanks

7 Answers
intersection_length = min(t1end, t2end) - max(t1start, t2start)
return intersection_length >= 0 

This will accept an intersection consisting of a single point; otherwise use > 0.

The intuition is that an intersected interval, if it exists, starts at the highest start and ends at the lowest end. There are two possibilities:

  1. It is a correct interval, possibly of length zero.

  2. The start and end points end up being switched. This means there is a gap between the two intervals, which you might call a "negative intersection".

Very late answer, but it seems to me that the simplest and least head-scratching solution is:

def date_intersection(t1, t2):
    t1, t2 = sorted([t1, t2], key=lambda t: t[0])
    t1end = t1[1]
    t2start = t2[0]
    return t1 end <= t2start

I would probably also be looking at expressing the idea of a "time interval" as a class, so I could do something more like:

def date_intersection(interval1, interval2):
    i1, i2 = sorted([interval1, interval2], key=lambda i: i.start)
    return i1.end <= i2.start
Related