虽然我只阅读与时区转换相关的每篇帖子,但我仍然遇到一些问题而且转换时间不正确
settings.py
TIME_ZONE = 'UTC'
USE_TZ = True
views.py
utc = datetime.utcnow()
instance_time_zone = pytz.timezone(instance.timezone) # 'US/Pacific'
start_date = instance_time_zone.localize(datetime.utcnow(), is_dst=None)
template.html
utc: Oct. 2, 2015, 5:32 p.m. #correct time
start_date: Oct. 3, 2015, 1:32 a.m. #incorrect time
由于某种原因,转换时间错误,比太平洋时间提前15小时,比UTC时间提前8小时。
答案 0 :(得分:3)
timezone.localize()
应该用于天真 datetime
对象(没有自己时区的对象)。时区附加到datetime
,就好像该时区的日期和时间 一样。因此,在您的情况下,您将“本地化”UTC定义为没有DST的本地时间,将其向错误的方向移动8小时。
您使用的是UTC时间戳,因此您需要将UTC时区附加到该时区,然后将时间戳移动到所需的时区:
utc = pytz.utc.localize(datetime.utcnow())
instance_time_zone = pytz.timezone(instance.timezone) # 'US/Pacific'
start_date = utc.astimezone(instance_time_zone)
请注意,utc
值现在是带有时区的datetime
对象,因此您可以使用datetime.astimezone()
method从中生成所需目标时区的值。
演示:
>>> from datetime import datetime
>>> utc = pytz.utc.localize(datetime.utcnow())
>>> utc
datetime.datetime(2015, 10, 2, 17, 58, 10, 168575, tzinfo=<UTC>)
>>> instance_time_zone = pytz.timezone('US/Pacific')
>>> utc.astimezone(instance_time_zone)
datetime.datetime(2015, 10, 2, 10, 58, 10, 168575, tzinfo=<DstTzInfo 'US/Pacific' PDT-1 day, 17:00:00 DST>)
现在,生成的datetime
已从UTC中删除了5个小时。
但是,如果要将这些值输出到Django模板中,请注意Django 还会转换时区。请参阅Django timezone documentation,特别是section on using aware datetime objects in templates:
当您启用时区支持时,Django会在模板中呈现时将感知日期时间对象转换为current time zone。这与格式化本地化非常相似。
您应该使用
activate()
将当前时区设置为最终用户的实际时区。否则,使用默认时区。
然后将datetime
对象移动到的时区并不重要;它将使用当前时区的任何内容来显示该值。您通常希望在UTC时区中使用感知datetime
个对象,然后使用activate()
来切换显示的所有时区。
所以在 Django 中,只需在任何地方使用timezone.now()
,让模板系统担心将其转换为给定的时区。
答案 1 :(得分:3)
要获取django中的当前时间,请使用timezone.now()
:
from django.utils import timezone
start_date = timezone.now()
如果instance.timezone
引用与timezone.get_current_timezone()
(default is TIME_ZONE
)相同的时区,那么就是您需要的所有内容(timezone.now()
返回已转换的UTC中的知晓日期时间对象(如果USE_TZ=True
)在渲染到当前时区时。)
否则,您可以致电timezone.activate(instance.timezone)
来设置当前时区。
如果您需要(您不需要),您可以明确转换时区:
import pytz
from django.utils import timezone
now = timezone.localtime(timezone.now(), pytz.timezone(instance.timezone))
在django代码之外,您可以通过明确传递tzinfo来获取给定时区的当前时间:
from datetime import datetime
import pytz
start_date = datetime.now(pytz.timezone('America/Los_Angeles'))
It works even during ambiguous local times.
转换表示给定pytz时区中时间的现有天真日期时间对象:
start_date = instance_time_zone.localize(datetime_in_instance_time_zone,
is_dst=None)
此代码引发实例时区中模糊/不存在时间的异常(例如,在DST转换期间)。如果可以在某些情况下返回不精确的结果而不是例外,那么就不要通过is_dst=None
:
tz = instance_time_zone
start_date = tz.normalize(tz.localize(datetime_in_instance_time_zone))
有关is_dst
的详细信息,请参阅"Can I just always set is_dst=True?" section。