如何使用时区感知日期过滤模型?

Posted

技术标签:

【中文标题】如何使用时区感知日期过滤模型?【英文标题】:How to filter models using timezone aware dates? 【发布时间】:2013-10-10 08:38:10 【问题描述】:

所以我试图按日期过滤 django 模型。仅使用年、年+月或年+月+day_of_month。我现在使用的策略是这样的:

n.filter(create_date__year=q)
n.filter(create_date__year=q[:4],create_date__month=q[4:6])
n.filter(create_date__year=q[:4],create_date__month=q[4:6],create_date__day=q[6:8])

其中 'q' 是日期字符串,格式分别为 'yyyy'、'yyyymm' 或 'yyyymmdd'。

这工作得很好但是 django 没有考虑时区。 Django 基于 UTC 时间而不是 EDT 进行搜索,这是实际的 datetime 对象设置的。

有没有办法根据特定时区搜索年/月/日?

【问题讨论】:

q 是日期时间对象还是实际字符串? 变量 q 现在是一个字符串 您可能应该使用日期对象,然后使用像 pytz 这样的时区模块来查询数据库。数据库的时区模型自动使用时区,您可以在设置文件中进行设置。 【参考方案1】:

是的,当启用时区支持时,Django 以 UTC 格式将日期和时间信息存储在数据库中,在内部使用时区感知的日期时间对象,并在模板和表单中将它们转换为最终用户的时区。

在你的设置文件中设置USE_TZ = True

创建一个可识别时区的日期时间,首先将其转换为 utc 并在您的过滤器中使用它。

>>> import datetime
>>> import pytz
>>> 
>>> unaware = datetime.datetime.strptime("20131103", "%Y%m%d")
>>> amsterdam = pytz.timezone('Europe/Amsterdam')
>>> aware = unaware.replace(tzinfo=amsterdam)
>>> d = aware.astimezone(pytz.UTC)
>>> 
>>> unaware
datetime.datetime(2013, 11, 3, 0, 0)
>>> amsterdam
<DstTzInfo 'Europe/Amsterdam' AMT+0:20:00 STD>
>>> aware
datetime.datetime(2013, 11, 3, 0, 0, tzinfo=<DstTzInfo 'Europe/Amsterdam' AMT+0:20:00 STD>)
>>> d
datetime.datetime(2013, 11, 2, 23, 40, tzinfo=<UTC>)
>>> 

现在您可以使用 d 过滤您的对象。

objs = SomeModel.objects.all() 

objs.filter(date__year=d.year)
objs.filter(date__year=d.year, date_month=d.month)
objs.filter(date=d.date)

【讨论】:

20 分钟的时间变化应该会让你产生怀疑。查看此线程以获得正确答案:***.com/questions/24856643/… 这适用于这样的日期时间吗? d.replace(hour=8); objs.filter(datetime__hour__gte=d.hour)【参考方案2】:

为了获取给定时区的当前日期,我使用了以下 utils 函数,该函数在您使用 pytz.timezone("America/New_York") 参数调用的情况下可能很有用。

from django.utils.timezone import now

def timezone_today(tz=utc):
    """
    Return the current date in the given timezone :param:`tz`.
    """
    return now().astimezone(tz).date()

【讨论】:

以上是关于如何使用时区感知日期过滤模型?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 django 中获取时区感知日期?

如何在 SqlAlchemy / Mysql 中存储时区感知日期时间值?

如何在python中获取时区感知午夜日期时间? [复制]

Python - 给定一个时区感知的日期时间对象,我如何获得一个时区朴素的 UTC 日期时间对象?

如何在 Python 中结合时区感知日期和时间?

python - 如何在没有dateutil的情况下将时区感知字符串转换为Python中的日期时间?