Python字符串转换为Django时区(感知日期时间)

34

TL;DR;

如何将 2016-01-01 转换为 Django 的 timezone?收到来自表单的查询字符串参数后,想要获取该字符串并将其用作Django中的日期时间过滤器。 问题是,当将字符串转换为日期时间时,它没有成为感知日期时间,因此由于时区不同而丢失了几个小时。

例子:

from datetime import date
# Example from what I receive as GET querystring parameter
start_date, end_date = '15-01-2016', '16-01-2016'
DATE_FORMAT = '%Y-%m-%d'
start_date = start_date.split('-')
start_date = date(int(start_date[2]), int(start_date[1]), int(start_date[0]))
sd_filter = start_date.strftime(DATE_FORMAT)

end_date = end_date.split('-')
end_date = date(int(end_date[2]), int(end_date[1]), int(end_date[0]))
ed_filter = end_date.strftime(DATE_FORMAT)

#query
my_list = MyModel.objects.filter(created_at__range=(sd_filter, ed_filter))
问题出现在筛选器中。由于Django设置的时区问题,我浪费了几个小时。 更新:我不需要将datetime.now()转换为我的时间。我需要将一个字符串转换为datetime。

你的模型中使用了什么字段类型?是 DateField() 吗?如果是,你可以直接将两个 date 对象(start_dateend_date)传递给你的 created_at__range=() 过滤器。 - gtlambert
1
可能是 Python 时区转换 的重复问题。 - Lajos Arpad
@lambo477 这是一个 DateTimeField,我尝试过这样做了...但它仍然缺少几个小时的 UTC。 - jarussi
@LajosArpad 我尝试使用答案中提到的方法,但对我没有起作用 :( - jarussi
3个回答

67

我知道这已经过时了,但或许对你有所帮助,因为我也遇到了同样的情况:

使用 make_aware() 怎么样呢?

from datetime import datetime
from django.utils.timezone import make_aware

date = '22-05-2018'
aware = make_aware(datetime.strptime(date, '%d-%m-%Y'))

这将使用当前活动的时区(由timezone.activate激活)。 如果没有明确激活时区,则会使用默认时区--在settings.py中指定的TIME_ZONE


23

您正在将不带时区信息的Python Date对象与数据库中具有时区信息的DateTimeField字段进行比较。使用带有时区信息的DateTime对象可能更直观 - 并且可以通过以下方式轻松地使其具有时区感知能力:

import datetime
import pytz

start_date = '15-01-2016' 
end_date = '16-01-2016'
date_format = '%d-%m-%Y'

unaware_start_date = datetime.datetime.strptime(start_date, date_format)
aware_start_date = pytz.utc.localize(unaware_start_date)

unaware_end_date = datetime.datetime.strptime(end_date, date_format)
aware_end_date = pytz.utc.localize(unaware_end_date)

my_list = MyModel.objects.filter(created_at__range=(aware_start_date, aware_end_date))

使用 strptime() 创建 unaware_start_dateunaware_end_date DateTime 对象。然后使用 pytz.utc.localize 使这些对象具有时区意识(你需要将 utc 替换为你所在的时区)。

现在你可以拥有时区意识的 DateTime 对象 - aware_start_dateaware_end_date。将它们输入到过滤器中应该会产生所需的结果。


2
如果您没有安装pytz模块,请在命令行中运行pip install pytz - gtlambert

3
from django.utils import timezone
timestamp_raw = timezone.now() #current time, or use whatever time you have
date_format = '%Y-%m-%d %H:%M:%S' #time format day-month-year hour:minutes:seconds
timestamp = timezone.datetime.strftime(timestamp_raw, date_format)

或使用新的f-string格式化程序

f"{timezone:%Y-%m-%d %H:%M:%S %p}"

这适用于日期 ISO 字符串吗? - Gustavo Oliveira
是的,它可以。我还编辑了答案,包括使用新的f-string格式化程序的示例。 - salafi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接