在处理DST时,为什么django.utils.timezone.make_aware和pytz.localize返回不同​​的结果?

时间:2018-10-25 20:50:59

标签: python django datetime timezone pytz

我正在使用Django 1.11和pytz 2018.6

我在理解django如何处理DST时遇到了一些问题。

我的主要问题是将2018-11-04 00:00:00时区中的日期America/Sao_Paulo本地化。根据最新的pytz版本,这是DST在该时区于2018年开始的日期。

好吧,在我的应用程序上尝试本地化提到的日期时,我开始看到pytz.exceptions.NonExistentTimeError异常。以下代码重现了此异常:

import os
import datetime
import django
import pytz
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myproject.settings")
django.setup()
from django.utils.timezone import make_aware

sp = pytz.timezone('America/Sao_Paulo')
dst_start_date = datetime.datetime(2018, 11, 4, 0, 0, 0)
make_aware(dst_start_date, sp)
# Exception raised: pytz.exceptions.NonExistentTimeError: 2018-11-04 00:00:00

但是,如果我尝试使用pytz.localize而不是make_aware进行本地化,则会得到不同的结果:

sp.localize(dst_start_date) # Returns 2018-11-04 00:00:00-03:00

我希望在尝试本地化时会收到相同的异常。但这并没有引发异常,实际上返回了错误的结果(-03:00偏移量是当我们不在DST上的时间。在特定日期,我希望将2018-11-04 00:00:00-03:00日期转换为{ {1}}。

这使我感到困惑,因为读取2018-11-04 00:00:00-02:00中的make_aware代码后,我知道调用了相同的django.utils.timezone方法。

pytz.tzinfo.localize

为什么两个结果都不同?手动尝试将日期# django.utils.timezone def make_aware(value, timezone=None, is_dst=None): """ Makes a naive datetime.datetime in a given time zone aware. """ if timezone is None: timezone = get_current_timezone() if hasattr(timezone, 'localize'): # This method is available for pytz time zones. return timezone.localize(value, is_dst=is_dst) else: # Check that we won't overwrite the timezone of an aware datetime. if is_aware(value): raise ValueError( "make_aware expects a naive datetime, got %s" % value) # This may be wrong around DST changes! return value.replace(tzinfo=timezone) 本地化为2018-11-04 00:00:00时为什么没有出现异常?

在尝试使用此代码之前,请确保您具有最新的pytz版本(America/Sao_Paulo),因为我们今年的夏令时日期已更改。

1 个答案:

答案 0 :(得分:2)

区别在于传递到is_dst的{​​{1}}参数。当您自己调用它却将其保留时,它默认为localize。在您发布的False代码中,其默认值为make_aware