分享技术 · 探索极限 · Code is Art
后端开发 发布 2024-12-30 955 阅读 约 2 分钟阅读

Django 日期聚合查询的时区坑

启用时区后,直接按时间字段做日期聚合可能导致日期提前 8 小时。本文记录问题原因,并给出使用 TruncDate 规避时区偏移的处理方式。

在 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 比直接截取时间字段更稳定,也更符合业务日期的预期。

发表回复