我们可以使用以下日期时间范围:
from datetime import timedelta
from django.db.models import Q
def filter_query(start_date, end_date):
a = am, ad = start_date.month, start_date.day
b = bm, bd = end_date.month, end_date.day
end_date2 = end_date + timedelta(days=1)
c = end_date2.month, end_date2.day
if c == (2, 29) and a == (3, 1):
return ~Q(birthday__month=2, birthday__day__gt=28)
if a == c:
return Q()
if a <= b:
if am == bm:
return Q(birthday__month=am, birthday__day__range=(ad, bd))
else:
return (Q(birthday__month=am, birthday__day__gte=ad) |
Q(month__range=(am+1, bm-1)) |
Q(birthday__month=bm, birthday__day__lte=bd))
else:
return ~filter_query(end_date+timedelta(days=1), start_date-timedelta(days=1))
这将返回一个Q 对象,然后可以通过过滤查询集来使用该对象,例如:
Sample.objects.filter(<strong>filter_query(</strong>date(2020, 12, 15), date(2021, 1, 16)<strong>)</strong>)
基本上有五种情况:
- 如果
end_date 是 2 月 28 日,开始日期是 3 月 1 日,那么我们排除 2 月 29 日。
- 如果
end_date加一天与开始日期相同,那么我们就不用过滤了;
- 如果
start_date 小于end_date 并且月份匹配,那么我们过滤该月份,并检查日期范围;
- 如果
start_date 小于end_date 并且月份不匹配,那么我们查找范围:
- 具有相同月份
start_date 且日期大于 start_date 月份的项目;
- 在
start_date 的下个月和end_date 的上个月之间的月份的项目;和
- 与
end_date 相同月份且日期小于或等于end_date 日期的项目。
- 如果结束日期小于开始日期,那么我们返回一个否定的
end_date 加一天,start_date 减一天。