Почему django.utils.timezone.make_aware и pytz.localize возвращают разные результаты при работе с DST? - PullRequest
0 голосов
/ 25 октября 2018

Я использую 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 происходит, когда мы не на летнем времени. В конкретную дату я ожидал, что дата 2018-11-04 00:00:00-03:00 будет конвертирована в 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 до America/Sao_Paulo?

Пожалуйста, убедитесь, что у вас установлена ​​последняя версия pytz (pip install pytz --upgrade), прежде чем пытаться использовать этот код, потому что мы имелиизменение даты перехода на летнее время в этом году.

1 Ответ

0 голосов
/ 26 октября 2018

Разница в том, что параметр is_dst передан в localize.Когда вы сами это называете, но не используете, по умолчанию это False.В коде make_aware, который вы разместили, по умолчанию используется None.

...