Python 日期区间交集
出于一般兴趣,我想知道有没有更优雅或更高效的方法来实现这个功能。我有一个函数,它比较两个日期的开始和结束时间,如果它们有交集就返回真。
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
等等。
我很好奇,是否有更符合Python风格、更优雅、更高效、代码更简洁的方法来实现这个功能,可能可以用mxDateTime库,或者用timedelta或set()做一些聪明的处理?
另外,如果函数能返回交集的开始和结束时间的元组,那也是一种有用的形式。
谢谢!
7 个回答
7
这里有一个版本,可以让你看到两个范围的交集。依我看,这可能不是条件数量最优的写法,但它清楚地展示了 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
20
这里有一个替代方案,希望能更容易理解:
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 可能等于 earliest_end。
还要说明的是,这个假设是 a_start <= a_end
和 b_start <= b_end
。
30
这其实并不是更符合Python风格,但你可以稍微简化一下判断两个区间是否相交的逻辑。这个问题经常会出现:
return (t1start <= t2start <= t1end) or (t2start <= t1start <= t2end)
要理解为什么这样做有效,可以想想两个区间相交的不同情况,发现其中一个区间的起始点必须总是在另一个区间的范围内。