пересечение интервала даты Python - PullRequest
13 голосов
/ 15 сентября 2010

Что касается общего интереса, мне интересно, есть ли более элегантный / эффективный способ сделать это.У меня есть функция, которая сравнивает два кортежа начала / конца дат, возвращающих true, если они пересекаются.

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

, поэтому если:

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

затем:

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

и т. д.

Мне любопытно узнать, есть ли более питонический / элегантный / более эффективный / менее многословный / вообще лучший способ, сделать это с помощью, возможно, mxDateTime или какого-нибудь хитрого хака с помощью timedelta или set ()?

Альтернативной и полезной формой для функции будет возврат начального / конечного кортежа пересечения, если он найден

Спасибо

Ответы [ 5 ]

20 голосов
/ 15 сентября 2010

Это на самом деле не более Pythonic, но вы можете просто логика, чтобы определиться с пересечением несколько. Эта конкретная проблема всплывает много:

return (t1start <= t2start <= t1end) or (t2start <= t1start <= t2end)

Чтобы понять, почему это работает, подумайте о различных возможных способах пересечения двух интервалов и убедитесь, что начальная точка одного всегда должна находиться в пределах диапазона другого.

7 голосов
/ 15 ноября 2012

Альтернативное и, надеюсь, более понятное решение:

def has_overlap(A_start, A_end, B_start, B_end):
    latest_start = max(A_start, B_start)
    earliest_end = min(A_end, B_end)
    return latest_start <= earliest_end:

Мы можем легко получить интервал перекрытия, это (latest_start, earliest_end).Обратите внимание, что latest_start может быть равен ранее.

Следует отметить, что это предполагает, что A_start <= A_end и B_start <= B_end.

6 голосов
/ 16 сентября 2010

Вот версия, которая дает вам диапазон пересечения. ИМХО, это может быть не самое оптимальное число условий, но оно четко показывает, когда t2 перекрывается с t1. Вы можете изменить на основе других ответов, если вы просто хотите, чтобы истина / ложь.

if (t1start <= t2start <= t2end <= t1end):
    return t2start,t2end
elif (t1start <= t2start <= t1end):
    return t2start,t1end
elif (t1start <= t2end <= t1end):
    return t1start,t2end
elif (t2start <= t1start <= t1end <= t2end):
    return t1start,t1end
else:
    return None
3 голосов
/ 11 февраля 2016
Final Comparison: start <= other_finish and other_start <= finish

# All of the conditions below result in overlap I have left out the non overlaps

start <= other_start | start <= other_finish | other_start <= finish | finish <= other_finish 

      0                        1                        1                        0                   
      0                        1                        1                        1
      1                        1                        1                        0          
      1                        1                        1                        1

Только start <= other_finish </strong> и other_start <= finish </strong> должны иметь значение true, чтобы вернуть перекрытие.

0 голосов
/ 15 сентября 2010
if t1end < t2start or t1start > t2end: return False
if t1start <= t2end or t2start <= t1start: return True
return False

Разве это не распространяется на все пересекающиеся множества?

...