在 Django 项目启用时区后,如果直接使用时间字段做日期聚合,查询结果可能会出现日期提前 8 小时的问题。这个坑通常出现在按天统计、报表汇总、趋势图聚合等场景里。
问题现象
数据库里保存的是带时区语义的时间,但聚合时如果直接截取时间字段,最终分组日期可能和业务预期不一致,表现为统计结果被归到前一天。
处理方式
不要直接拿时间字段做日期聚合。先使用 TruncDate 将时间转换成日期字段,再基于转换后的日期字段进行分组统计。
from django.db.models import Count
from django.db.models.functions import TruncDate
daily_stats = (
queryset.annotate(day=TruncDate("created_at"))
.values("day")
.annotate(total=Count("id"))
)结论
启用时区后,日期统计要显式处理时区转换。对报表类查询而言,使用 TruncDate 比直接截取时间字段更稳定,也更符合业务日期的预期。