Python 如何按日期筛选datetime字段?

Python 如何按日期筛选datetime字段?,python,django,Python,Django,我有一个模型: class Account(models.Model): contract_date = models.DateTimeField() 现场合同日期存储在UTC时区的db中。我需要选择合同日期=日期的所有帐户。但日期存储在MSK时区(+3)。例如: Account.objects.create(contract_date='2010-01-01 21:00:00') Account.objects.filter(contract_date__date=date(2010

我有一个模型:

class Account(models.Model):
    contract_date = models.DateTimeField()
现场合同日期存储在UTC时区的db中。我需要选择合同日期=日期的所有帐户。但日期存储在MSK时区(+3)。例如:

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

查询返回一个空列表。

您正在使用没有时间的日期进行查询。。。改用datetime:

datetime(2010,1,2,21,0,0)
如果启用了时区(
在设置中使用_TZ=True
),django将确保所有日期时间都保存在UTC时区中,并在UTC时区中检索

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

还要注意,
日期(2019-01-02)不能识别时区,只有
日期时间可以识别时区,因为没有时间,时区就没有意义

所以,在您的情况下,您需要告诉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))

这会告诉数据库将datetime转换为MKS,并截断与参考日期进行比较的前一天。我确保
contract\u date
不为空,否则会出现错误。

然后需要首先将MSK datetime转换为UTC datetime。因为正如您所说,数据库中的日期是以时区感知和UTC格式存储(并由django检索)的,假设您有
设置。请使用_TZ=True
。我按日期过滤。不是按日期时间。我只有筛选的日期。非常感谢!我的解决方案不够优雅:将msk_日期转换为msk_日期时间转换为utc_日期时间(2010-01-01 21:00:00)
Account.objects.filter(合同日期范围=(utc_日期时间,utc_日期时间+时间增量(day=1))。all()
不一定不那么优雅。对于阅读代码的人来说,比我的解决方案更容易理解。