如何按日期过滤datetime字段?

时间:2019-05-15 14:02:44

标签: python django

我有模特:

class Account(models.Model):
    contract_date = models.DateTimeField()

字段contract_date以UTC时区存储在db中。我需要选择contract_date__date == date的所有帐户。但是日期存储在MSK时区(+3)中。例如:

Account.objects.create(contract_date='2010-01-01 21:00:00')
Account.objects.filter(contract_date__date=date(2010, 1, 2)).all()

查询返回一个空列表。

2 个答案:

答案 0 :(得分:1)

如果启用了时区(在设置中为USE_TZ = True),那么django将确保所有日期时间都保存在UTC时区中并在UTC时区中检索。

显示它们时,它将使用当前时区(settings.TIME_ZONE或激活时区的另一个时区)在适当的时区中显示它们。从表单接收输入时,它将转换为UTC。

还请注意,date(2019-01-02)无法识别时区,只有datetime可以识别时区,因为没有时间,时区就没有意义。

因此,在您的情况下,您需要告诉Django您要使用MKS时区中的日期进行过滤。您可以为此使用Trunc

from django.db.models.functions import Trunc
from django.db.models import DateTimeField
import pytz
from datetime import datetime

mks_filter_day = pytz.timezone("Europe/Moscow").localize(datetime(2010, 1, 2))
Account.objects.exclude(contract_date__isnull=True).annotate(
    mks_day=Trunc('contract_date', 'day', output_field=DateTimeField(), tzinfo=pytz.timezone("Europe/Moscow")))\
    .filter(mks_day=mks_filter_day)
# or in Django 1.11 the above doesn't work due to a bug
Account.objects.exclude(contract_date__isnull=True).annotate(
    mks_day=Trunc('contract_date', 'day', output_field=DateTimeField(), tzinfo=pytz.timezone("Europe/Moscow")))\
    .filter(mks_day__contains=datetime.date(2010, 1, 2))

这告诉数据库将日期时间转换为MKS,并在与参考日期比较之前将日期截断。我确保contract_date不为null,否则会出现错误。

答案 1 :(得分:0)

您要查询的是没有时间的日期...请改用datetime:

datetime(2010,1,2,21,0,0)