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
作为过滤器。
为了准备部署,我从 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
作为过滤器。