【问题标题】:Django-Postgres: how to group by DATE a datetime field with timezone enabledDjango-Postgres:如何按日期对启用时区的日期时间字段进行分组
【发布时间】:2026-02-01 22:00:01
【问题描述】:

我在使用 prostgresql 和 django 时遇到了这个问题:

我有很多在某个日期在某个时间创建的事件,这些事件存储在日期时间字段 created 中。

  • 我想根据created 字段的日期部分进行聚合。最简单的例子是:how many event are in each day of this month?
  • created 字段可识别时区。所以结果应该根据用户所在的时区而改变。例如,如果您在 2017 年 10 月 2 日 23:30 UTC 时间创建了 2 个事件,如果您从 UTC-1 查看它们,您应该在 10 月 3 日看到它们00:30,总数应添加到第 3 天。

我正在努力寻找一个适用于大量数据的解决方案。因此,每天都做 SQL 语句不是一种选择。我想要的东西可以翻译成:

SELECT count(*) from table GROUP BY date

现在我找到了解决第一部分问题的方法:

from django.db import connection
truncate_date = connection.ops.date_trunc_sql('day', 'created')
queryset = queryset.extra({'day': truncate_date})
total_list = list(queryset.values('day').annotate(amount=Count('id')).order_by('day'))

有没有办法添加 date_trunc_sql 函数应该使用的时区来计算日期?或者 date_trunc_sql 之前的一些其他函数,然后链接那个。

谢谢!

【问题讨论】:

    标签: django postgresql orm


    【解决方案1】:

    Django 2.2+ 支持TruncDate 带时区的数据库函数

    您现在可以执行以下操作:

    import pytz
    
    east_coast = pytz.timezone('America/New_York')
    queryset.annotate(created_date=TruncDay("created", tzinfo=east_coast))
        .values("created_date")
        .order_by("created_date")
        .annotate(count=Count("created_date"))
        .order_by("-created_date")
    

    【讨论】:

      【解决方案2】:

      您可能正在寻找这个:timezone aware date_trunc function

      但是请记住,这可能与您的 django 配置方式相冲突。 https://docs.djangoproject.com/en/1.11/topics/i18n/timezones/

      【讨论】:

      • 谢谢。这些链接很有用,我找到了一种使用 date_trunc_sql 解决问题的方法。这个评论也有帮助。 *.com/questions/25385370/…
      • 我看到有一个 connection.ops.datetime_trunc_sql 函数将时区作为参数,但我无法使其工作。对如何做到这一点有任何想法吗?之后它正在关闭连接,在线queryset = queryset.extra({'day': truncate_date})
      • AFAIK 此特定行不应调用 SQL 查询。不过我可能是错的。我会尝试的一件事是将其包装在交易中。 docs.djangoproject.com/en/1.11/topics/db/transactions/…
      最近更新 更多