Django 4.2中如何创建时区感知的当日最小/最大时间用于查询?
Django 4.2 时区感知的当日最小/最大时间创建方案
问题背景
已在settings.py中设置TIME_ZONE='UTC',目标模型包含两个时区感知的日期时间字段:
open_to_readers = models.DateTimeField(auto_now=False, verbose_name="Campaign Opens") close_to_readers = models.DateTimeField(auto_now=False, verbose_name="Campaign Closes")
需要查询满足open_to_readers__lte=当日最小时间且close_to_readers__gt=当日最大时间的记录,但之前尝试的方案均存在问题:
- 生成的是无时区信息(naive)的datetime,触发Django时区错误
- 获取的是当前时间而非当日起止时间
- 错误生成了datetime类型的全局最小/最大时间范围
正确实现方式
使用Django内置的timezone模块,生成带UTC时区信息的当日起止时间:
from django.utils import timezone from datetime import datetime, time # 获取当前UTC日期 today_utc = timezone.now().date() # 创建当日最小时间(UTC 00:00:00),并添加时区信息 today_min = timezone.make_aware( datetime.combine(today_utc, time.min), timezone.get_default_timezone() ) # 创建当日最大时间(UTC 23:59:59.999999),并添加时区信息 today_max = timezone.make_aware( datetime.combine(today_utc, time.max), timezone.get_default_timezone() ) # 执行查询 allcampaigns = Campaigns.objects.filter( open_to_readers__lte=today_min, close_to_readers__gt=today_max )
简化写法
如果不需要精确到微秒,也可以直接构造datetime对象并添加时区:
today_min = timezone.localize(datetime(today_utc.year, today_utc.month, today_utc.day)) today_max = timezone.localize(datetime(today_utc.year, today_utc.month, today_utc.day, 23, 59, 59))
错误方案原因解析
失败方案1:
datetime.combine()生成的是不带时区信息的naive datetime,而Django开启时区支持后,DateTimeField强制要求传入时区感知的对象,因此触发报错。只需通过timezone.make_aware()为其添加时区即可解决。部分可行方案:
timezone.now()返回的是当前UTC时间,并非当日的起始或结束时间,因此查询范围不符合需求。失败方案2:
now.min和now.max是datetime对象的内置属性,返回的是该类型的全局最小(0001-01-01)和最大(9999-12-31)时间,并非当日的起止时间,完全误解了属性用途。
内容的提问来源于stack exchange,提问作者Byte Insight
相关产品推荐
相关产品推荐

