我有一个对象保存在db中,时间范围为(t1): 11:45-00:15
。现在,我有另一个请求时间范围:(t2) 00:05-00:10
。查找此新时间范围t2
是否与时间范围t1
的已保存对象重叠的最佳方法是什么。午夜就是这种情况,那是一天在变的地方。对于同一天,我可以成功找到重叠的时间范围。我没有datetime
字段,而是只有time
字段,因此我必须处理已有的内容。
在模型t1中,其存储为:
start_time = TimeField(null=True, blank=True, db_index=True)
end_time = TimeField(null=True, blank=True, db_index=True)
因此11:45将存储在start_time
中,而00:15将存储在end_time
答案 0 :(得分:1)
这个逻辑应该可以:
if (d1.start_time < d2.start_time < d1.end_time) or (d1.start_time < d2.end_time < d1.end_time) or (d2.start_time <= d1.start_time and d2.end_time >= d1.end_time): return True
说明:
首先,检查 d2 的开始和结束时间是否与 w d1 的时间范围重叠。如果是,则返回 True。
接下来,查看 d2 是否大于或与 d1 相同。如果是,则返回 True。
否则,这些日期不会重叠。
答案 1 :(得分:0)
我假设在start_time
大于end_time
的情况下,时间范围应该只是重叠,因为时间是周期性的,我们只是不在乎日期(换句话说,这些范围代表每天发生的事件,我们想检测是否有任何事件与其他任何事件重叠
基于此假设,这里是快速答案:
if t2.start_time > t2.end_time:
condition = (
Q(start_time__gt=F('end_time')) |
Q(start_time__lt=t2.end_time) |
Q(end_time__gt=t2.start_time)
)
else:
condition = (
Q(start_time__gt=F('end_time'), start_time__lt=t2.end_time) |
Q(start_time__gt=F('end_time'), end_time__gt=t2.start_time) |
Q(start_time__lt=t2.end_time, end_time__gt=t2.start_time)
)
有24种安排每个事件的开始时间和结束时间的情况(不包括两个日期相等的情况)。在这24个案例中,其中20个表示存在重叠,而其中4个表示没有重叠。由于没有重叠包含的情况要少得多,所以让我们仔细看一下,下面是这4种情况:
t1.end_time < t2.start_time < t2.end_time < t1.start_time
t1.start_time < t1.end_time < t2.start_time < t2.end_time
t2.start_time < t2.end_time < t1.start_time < t1.end_time
t2.end_time < t1.start_time < t1.end_time < t2.start_time
您可以按以下方式在python代码中表示这些情况(添加了多余的空格以显示如何将它们分组):
( t1.start_time > t2.end_time and t2.start_time > t1.end_time and t2.start_time < t2.end_time) or \ # 1.
(t1.start_time < t1.end_time and t2.start_time > t1.end_time and t2.start_time < t2.end_time) or \ # 2.
(t1.start_time < t1.end_time and t1.start_time > t2.end_time and t2.start_time < t2.end_time) or \ # 3.
(t1.start_time < t1.end_time and t1.start_time > t2.end_time and t2.start_time > t1.end_time ) # 4.
我们可以看到,如果这4个条件中的任何3个条件适用,则可以简化判断项是否重叠:
(
t1.start_time < t1.end_time,
t1.start_time > t2.end_time,
t2.start_time > t1.end_time,
t2.start_time < t2.end_time,
)
如果要确定2个项目是否重叠,则必须逆转此条件。因此,如果这4个条件中的2个条件中的任何一个满足条件,则项目是重叠的:
(
t1.start_time > t1.end_time,
t1.start_time < t2.end_time,
t2.start_time < t1.end_time,
t2.start_time > t2.end_time,
)
因此完整状态如下:
t1.start_time > t1.end_time and t1.start_time < t2.end_time or \
t1.start_time > t1.end_time and t2.start_time < t1.end_time or \
t1.start_time > t1.end_time and t2.start_time > t2.end_time or \
t1.start_time < t2.end_time and t2.start_time < t1.end_time or \
t1.start_time < t2.end_time and t2.start_time > t2.end_time or \
t2.start_time < t1.end_time and t2.start_time > t2.end_time
在Django queryset中对其进行修饰,因为在执行它之前我们可以检查1个条件(我们可以检查start_time
的{{1}}是否低于{{1}的t2
}),我们可以将其分为两种情况,并简化两种情况。
end_time
是的...我们已经跳过了这一点...我们需要做出3个决定才能将它们包括在内。
第一个条件和第二个条件不能都为是。如果您对所有这些问题的回答均为“否”,则说明您已完成,上面显示的代码将适用于您的情况。如果您对任何问题的回答是“是”,请从下面的列表中进行相应的修改:
t2
,并假设if t2.start_time > t2.end_time:
condition = (
Q(start_time__gt=F('end_time')) |
Q(start_time__lt=t2.end_time) |
Q(end_time__gt=t2.start_time)
)
else:
condition = (
Q(start_time__gt=F('end_time'), start_time__lt=t2.end_time) |
Q(start_time__gt=F('end_time'), end_time__gt=t2.start_time) |
Q(start_time__lt=t2.end_time, end_time__gt=t2.start_time)
)
与.exclude(start_time=F('end_time'))
没有任何其他重叠,只需跳过检查即可t2
,并假设t2.start_time == t2.end_time
与| Q(start_time=F('end_time')
与其他所有元素重叠,并跳过检查t2
而不是{时,在两种情况下都用t2.start_time == t2.end_time
替换每个__gt
,用__gte
替换每个__lt
{1}}功能。