繁体   English   中英

python日期间隔交集

[英]python date interval intersection

出于普遍兴趣,我想知道是否有更优雅/更有效的方法来做到这一点。 我有一个函数比较两个日期的开始/结束元组,如果它们相交则返回 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

等等

我很想知道是否有更 pythonic/优雅/更高效/更简洁/通常更好的方法,可以使用 mxDateTime 或使用 timedelta 或 set() 的一些聪明的技巧来做到这一点?

另一种有用的形式是函数在找到交集时返回交集的开始/结束元组

谢谢

它并不是真的更 Pythonic,但你可以简单地确定一个交叉点的逻辑。 这个特殊问题经常出现:

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

要了解为什么这有效,请考虑两个区间相交的不同可能方式,并了解一个区间的起点必须始终在另一个区间的范围内。

另一种希望更容易理解的解决方案:

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_endb_start <= b_end

这是一个为您提供交集范围的版本。 恕我直言,它可能不是最优化的条件数,但它清楚地显示了 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
intersection_length = min(t1end, t2end) - max(t1start, t2start)
return intersection_length >= 0 

这将接受由单个点组成的交叉点; 否则使用> 0

直觉是相交区间(如果存在)从最高点开始到最低点结束。 有两种可能性:

  1. 这是一个正确的区间,可能长度为零。

  2. 起点和终点最终被交换。 这意味着两个间隔之间存在间隙,您可以将其称为“负交集”。

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_finishother_start <= finish需要为真才能返回重叠。

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

这不会涵盖所有相交的集合吗?

很晚的答案,但在我看来,最简单和最不令人头疼的解决方案是:

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

我可能还会考虑将“时间间隔”的想法表达为一个类,因此我可以做更多类似的事情:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM