Dateutil и pytz дают разные результаты - программирование
Подтвердить что ты не робот

Dateutil и pytz дают разные результаты

У меня проблема с выводом результатов с dateutil и pytz. Я создаю объект datetime, знакомый с данными (UTC), а затем преобразовываю его в данный часовой пояс, но получаю разные ответы. Я подозреваю, что dateutil иногда дает неправильные результаты, потому что у него есть проблемы с учетом летнего времени (по крайней мере, я прочитал комментарий об этом), но я не могу найти подтверждение или исправить эту проблему. Это код:

import dateutil

u = dateutil.tz.tzutc()
date1 = datetime.datetime(2010, 5, 2, 11, 10, tzinfo=u)
# 2010-05-02 11:10:00+00:00

u2 = dateutil.tz.gettz('America/Chicago')
date2 = datetime.datetime(2010, 5, 2, 11, 10, tzinfo=u2)
# 2010-05-02 11:10:00-05:00


import pytz
u = pytz.timezone('UTC')
date1 = datetime.datetime(2010, 5, 2, 11, 10, tzinfo=u)

# 2010-05-02 11:10:00+00:00
u2 = pytz.timezone('America/Chicago')
date2 = datetime.datetime(2010, 5, 2, 11, 10, tzinfo=u2)

# 2010-05-02 11:10:00-06:00

Итак, что может быть проблемой здесь?

UPDATE:

Я просто попробовал это:

print u2.normalize(date1.astimezone(u2))
# 2010-05-02 06:10:00-05:00

Итак, pytz нуждается в normalize, чтобы рассмотреть DST?

ОБНОВЛЕНИЕ 2:

Казалось, что pytz и dateutil не дают ответа для Америки/Аргентины/San_Luis, но это работает:

import pytz, dateutil, datetime

now = datetime.datetime.now() 

for zone in pytz.all_timezones:
    utc_dateutil = dateutil.tz.tzutc()
    utcdate_dateutil = datetime.datetime(now.year, now.month, now.day, now.hour, now.minute, tzinfo=utc_dateutil)
    zone_dateutil = dateutil.tz.gettz(zone)
    newzone_dateutil = utcdate_dateutil.astimezone(zone_dateutil)

    utc_pytz = pytz.timezone('UTC')
    utcdate_pytz = datetime.datetime(now.year, now.month, now.day, now.hour, now.minute, tzinfo=utc_pytz)
    zone_pytz = pytz.timezone(zone)
    newzone_pytz = utcdate_pytz.astimezone(zone_pytz)
    assert newzone_dateutil == newzone_pytz

Я что-то пропустил?

Спасибо

4b9b3361

Ответ 1

Изменить: Расхождение, обсуждаемое ниже, больше не существует при использовании

>>> dateutil.__version__
'1.5'

>>> pytz.__version__
'2012c'

Модуль pytz предупреждает,

эта библиотека отличается от документированного API Python для tzinfo реализации; если вы хотите создать локальные часы для использования метода localize()

и далее

Эта библиотека поддерживает только два способа построения локализованного времени. сначала следует использовать метод localize(), предоставляемый библиотекой pytz.

In [61]: u4 = pytz.timezone('America/Chicago')
In [62]: print(u4.localize(datetime.datetime(2010, 5, 2, 11, 10)))
2010-05-02 11:10:00-05:00

Другим способом является использование метода astimezone, который используется для преобразования даты и времени, зависящего от часового пояса, в другое время и время, относящиеся к часовому поясу.

И чтобы быть полностью явным, предупреждает против о создании дат-времени, учитывающего часовой пояс, с использованием аргумента tzinfo:

К сожалению, использование аргумента tzinfo стандартного времени datetime конструкторы 'не работают с pytz для многих часовых поясов.


Пусть проверяется гипотеза о том, что

datetime.datetime(year, month, day, hour, minute, tzinfo = dateutil_tz)

равно

pytz_tz.localize(datetime.datetime(year, month, day, hour, minute))

с помощью этого кода:

import dateutil.tz
import datetime
import pytz

now  = datetime.datetime.now()

for name in pytz.all_timezones:
    dateutil_tz = dateutil.tz.gettz(name)
    pytz_tz = pytz.timezone(name)
    dateutil_date = datetime.datetime(
        now.year, now.month, now.day, now.hour, now.minute, tzinfo = dateutil_tz)
    pytz_date = pytz_tz.localize(datetime.datetime(
        now.year, now.month, now.day, now.hour, now.minute))

    try:
        assert dateutil_date.isoformat() == pytz_date.isoformat()
    except AssertionError:
        print(name)
        print(dateutil_date.isoformat())
        print(pytz_date.isoformat())           

Код дает:

America/Argentina/San_Luis
2012-12-18T22:32:00-04:00 <-- dateutil datetime
2012-12-18T22:32:00-03:00 <-- pytz datetime

Итак, моя гипотеза была неправильной: dateutil и pytz возвращают разные результаты.

Итак, какой из них правильный? Я не уверен, но согласно этот сайт, в настоящее время

America/Argentina/San_Luis time zone offset is: 
UTC / GMT -03:00 hours

значит, pytz верен.