两个范围[a1, b1)和[a2, b2) 如果 a1≥b2 则 不 重叠,或b1≤a2。我们可以否定这个表达式来知道两个区间何时重叠:a12和b1子>>a2.
这里start_date和end_date分别是a1和b1,而这两个因此,您编写的 '2018-09-15 03:00:00' 和 '2018-09-15 03:30:00' 的值分别是 a2 和 b2。
因此我们可以进行如下查询:
begin='2018-09-15 03:00:00'
end='2018-09-15 03:30:00'
Lines.objects.filter(
start_date__lt=end
end_date__gt=begin
)
因此不检查(begin, end)是否“包含”在(start_date, end_date)中,它检查是否至少有一个元素是两个范围的成员。
现在OVERLAP function in PostgreSQL有点复杂,因为它会自动交换时间以防end_date大于start_date,所以我们可能需要在这里使用.annotate(..):
from django.db.models import F
from django.db.models.functions import Greatest, Least
begin='2018-09-15 03:00:00'
end='2018-09-15 03:30:00'
Lines.objects.annotate(
d0=Least(F('start_date'), F('end_date')),
d1=Greatest(F('start_date'), F('end_date')),
).filter(
d0__lt=end
d1__gt=begin
)
这仍然不完全一样,因为如果d0 和d1 相同,那么范围是“包含”的,所以我们也应该考虑这种情况:
Lines.objects.annotate(
d0=Least(F('start_date'), F('end_date')),
d1=Greatest(F('start_date'), F('end_date')),
).filter(
Q(d0__lt=end, d1__gt=begin) |
Q(d0=F('d1'), d0__gte=begin, d0__lt=end)
)
它还需要“准备”begin 和end(你应该确保begin <= end,如果不交换这些,不是因为否则方法会失败,而是因为这些是“精确的”相当复杂的OVERLAP函数的规格说明)。