Python Django时区转换错误的时间为“US / Pacific'时区

时间:2015-10-02 17:52:42

标签: python django datetime pytz python-datetime

虽然我只阅读与时区转换相关的每篇帖子,但我仍然遇到一些问题而且转换时间不正确

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小时。

2 个答案:

答案 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。这与格式化本地化非常相似。

来自current time zone section

  

您应该使用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