неправильное преобразование часового пояса python с использованием pytz

Я написал следующий скрипт на python для преобразования даты и времени из любого заданного часового пояса в EST.

from datetime import datetime, timedelta  
from pytz import timezone  
import pytz  
utc = pytz.utc  

# Converts char representation of int to numeric representation '121'->121, '-1729'->-1729 
def toInt(ch):  
    ret = 0  
    minus = False  
    if ch[0] == '-':  
        ch = ch[1:]  
        minus = True  
    for c in ch:  
        ret = ret*10 + ord(c) - 48  
    if minus:  
        ret *= -1  
    return ret  

# Converts given datetime in tzone to EST. dt = 'yyyymmdd' and tm = 'hh:mm:ss' 
def convert2EST(dt, tm, tzone): 
    y = toInt(dt[0:4]) 
    m = toInt(dt[4:6]) 
    d = toInt(dt[6:8]) 
    hh = toInt(tm[0:2]) 
    mm = toInt(tm[3:5]) 
    ss = toInt(tm[6:8])

    # EST timezone and given timezone 
    est_tz = timezone('US/Eastern') 
    given_tz = timezone(tzone)

    fmt = '%Y-%m-%d %H:%M:%S %Z%z'

    # Initialize given datetime and convert it to local/given timezone 
    local = datetime(y, m, d, hh, mm, ss) 
    local_dt = given_tz.localize(local)


    est_dt = est_tz.normalize(local_dt.astimezone(est_tz)) 
    dt = est_dt.strftime(fmt) 
    print dt 
    return dt  

Когда я вызываю этот метод с convert2EST('20110220', '11:00:00', 'Америка/Сан-Паулу')

вывод: «2011-02-20 08:00:00 EST-0500», но летнее время в Бразилии закончилось 20 февраля, и правильный ответ должен быть «2011-02-20 09:00:00 EST-0500».

Из некоторых экспериментов я понял, что, согласно pytz, переход на летнее время в Бразилии заканчивается 27 февраля, что неверно.

Содержит ли pytz неверные данные или я что-то упускаю. Любая помощь или комментарии будут высоко оценены.


person user629424    schedule 23.02.2011    source источник
comment
Вы должны просто использовать встроенную функцию int для преобразования ваших строк в целые числа.   -  person Sam Dolan    schedule 23.02.2011
comment
и strptime для преобразования в дату.   -  person Lennart Regebro    schedule 23.02.2011


Ответы (2)


Во-первых, чуть менее безумная реализация:

import datetime
import pytz

EST = pytz.timezone('US/Eastern')

def convert2EST(date, time, tzone):
    dt = datetime.datetime.strptime(date+time, '%Y%m%d%H:%M:%S')
    tz = pytz.timezone(tzone)
    dt = tz.localize(dt)
    return dt.astimezone(EST)

Теперь попробуем вызвать:

>>> print convert2EST('20110220', '11:00:00', 'America/Sao_Paulo')
2011-02-20 09:00:00-05:00

Как видим, мы получаем правильный ответ.

Обновление: я понял!

Бразилия изменила летнее время в 2008 году. Неясно, что было до этого, но, вероятно, ваши данные устарели.

Вероятно, это не ошибка pytz, поскольку pytz может использовать базу данных вашей операционной системы. Вероятно, вам нужно обновить операционную систему. Это (я думаю) причина, по которой я получил правильный ответ даже с pytz 2005 года, он использовал (обновленные) данные из моей ОС.

person Lennart Regebro    schedule 23.02.2011
comment
Согласно документам, pytz использует базу данных часовых поясов Олсона, а не часовые пояса ОС. Это может быть просто вопрос обновления до последней версии pytz. pytz.sourceforge.net/#latest-versions - person Mark Ransom; 23.02.2011
comment
@Mark Ransom: Большинство версий Unix, включая все версии Linux, а также, я думаю, OS X также используют базу данных Olson. Прошло некоторое время с тех пор, как я прочитал исходный код pytz, но у меня смутное воспоминание, в некоторых случаях он использует базу данных ОС вместо включенной. И это почти единственная возможность, если только он не использует версию pytz восьмилетней давности. - person Lennart Regebro; 23.02.2011
comment
Вы абсолютно правильно поняли! У меня была установлена ​​старая версия pytz, и ее обновление решило проблему. Спасибо, Леннарт. - person user629424; 24.02.2011
comment
Удивительно. Должно быть, это было действительно старо. - person Lennart Regebro; 24.02.2011
comment
Возможно, с 2005 года pytz изменился, чтобы во всех случаях использовать встроенный файл, а не ОС? Документация кажется довольно подробной, хотя это не гарантирует ее правильность. Если Бразилия изменилась в 2008 году, вам понадобится только копия трехлетней давности. - person Mark Ransom; 28.02.2011
comment
Да, мог быть. Поэтому, если у вас есть старая копия pytz и базы данных в ОС, вы получите неверные данные. Это кажется разумным. - person Lennart Regebro; 28.02.2011

Кажется, вы сами ответили на свой вопрос. Если pytz говорит, что переход на летнее время в Бразилии заканчивается 27 февраля, это неверно. Летнее время в Бразилии заканчивается третье воскресенье февраля, если это воскресенье не выпадает на период карнавала; это не в этом году, так что летнее время не задерживается.

Тем не менее, вы, кажется, без необходимости запускаете свой собственный конвертер. Вам следует обратить внимание на модуль time, который, среди прочего, упрощает преобразование времени по Гринвичу в местное время. вещи.

person senderle    schedule 23.02.2011