Два диапазона [a 1 , b 1 ) и [a 2 , b 2 ) делать не перекрываться, если a 1 ≥b 2 или b 1 ≤a 2 .Мы можем отрицать это выражение, чтобы знать, когда два интервала перекрываются: a 1 a 2 .
Здесь start_date
и end_date
являются a 1 и b 1 соответственно, и два значения, которые вы написали '2018-09-15 03:00:00'
и '2018-09-15 03:30:00'
, составляют, таким образом, a 2 и b 2 соответственно.
Таким образом, мы можем сделать запрос, например:
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
в 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
).