Django:使用时区过滤月份(从 SQLite 切换到 PostgreSQL 后)

Django: Filter for month with timezone (after switching from SQLite to PostgreSQL)

为了准备部署,我从 SQLite 切换到 PostgreSQL(在 this advice 之后)。现在我在过滤某些项目的时间戳 by month 时遇到了一些麻烦,这是我以前使用 SQLite 时没有的。问题是,我得到的是 上一个 月份的项目,而不是当前月份的项目。看,我的代码基本上是这样的:

models.py
    class Dummy(models.Model):
        …
        timestamp = models.DateTimeField()
        …

views.py
    …
    current = datetime.date.today().replace(day=1)
    dummies = Dummy.objects.values(month=TruncMonth('timestamp')).
        filter(month__year=current.year).
        filter(month__month=current.month)
    …

我实际上有几个当月的虚拟条目(即 10),但 dummies 仍然是空的。如果我将 current.month 替换为 9,我将得到准确的这些条目。正如我之前所说,只有 PostgreSQL 才会出现这种情况。只要我用的是SQLite,就OK

经过一些研究,我明白了问题的根源:这些不同类型的数据库处理时区的方式似乎有所不同,例如参见this answer.

虚拟条目的时间戳在数据库本身中存储为 UTC。如果我查看 dummies 中的一项(如上所述,我使用 9 得到),它的月份值如下:

datetime.datetime(2020, 10, 1, 0, 0, tzinfo=<DstTzInfo 'Europe/Berlin' CEST+2:00:00 DST>)

current 的值为 datetime.date(2020, 10, 1),没有任何时区信息。因此,我假设使用 PostgreSQL 的 dummies 的月份值以某种方式转换为 UTC,并且日期更改类似于 2020、9、30。

我试了很多,但我仍然不知道如何解决这个问题,尽管我想这一定很容易。感谢任何帮助。

我走在了正确的轨道上,自己找到了问题的答案。此代码有效:

views.py
    from django.utils import timezone
    …
    current = timezone.now().replace(day=1, hour=0, minute=0, second=0, microsecond=0)
    dummies = Dummy.objects.values(month=TruncMonth('timestamp')).
        filter(month=current)

现在 current 不再是 date,而是包含时区的 datetime,因此非常适合 month 作为过滤器。