2015-11-04 3 views
1

У меня есть более 1 миллиона объектов datetime из базы данных, и я хочу преобразовать каждый из них в объекты datetime, относящиеся к часовому поясу. Вот мой помощник несильно conv_tz:pytz timezone conversion performance

# dt is python datetime object, src_tz and dest_tz and pytz.timezone objects 
def conv_tz(dt, src_tz, dest_tz): 
    if not dt: return None 
    sdt = src_tz.localize(dt) 
    return sdt.astimezone(dest_tz) 

Вот результат от профилировщика:

ncalls tottime percall cumtime percall filename:lineno(function) 
1101475 1.166 0.000 44.440 0.000 ../release/python/lib/dtutil.py:128(conv_tz) 
1101475 9.092 0.000 35.656 0.000 /app/python/lib/python3.4/site-packages/pytz/tzinfo.py:244(localize) 

Вопрос 1: Есть ли в любом случае, чтобы сделать его работать быстрее? Предполагается, что каждый объект datetime из базы данных находится в pytz.timezone ('America/New_York'), а часовой пояс назначения изменяется по каждому объекту datetime (или каждой строке в базе данных)

Фактически, после получения часовой пояс, известно, объект даты и время, что я действительно хочу добиться того, чтобы преобразовать это DATETIME объектого времени MatLab Так вот функция to_mat я использую (который не часовой пояс известен.):

def to_mat(dt): 
    if not dt: return None 
    val = dt.toordinal() + 366 
    t = dt.time() 
    return val + (((t.hour * 60) + t.minute) * 60 + t.second)/float(_seconds_day) + t.microsecond/1.0e6/_seconds_day 

Я называю эти- функционирует совместно для более чем 1 млн. единиц времени.

matdt = dtutil.to_mat(dtutil.conv_tz(dt, pytz.timezone('America/New_York'), dst_tz)) 

Вопрос2: Может быть, есть лучший способ сделать эти преобразования вместе? Вот профилировщика to_mat, который, кажется, меньше времени, чем conv_tz:

3304425 5.067 0.000 5.662 0.000 ../release/python/lib/dtutil.py:8(to_mat) 

Окружающая среда: CentOS6 x64 + x64 Python3.4.3

+0

Похоже, что в большинстве случаев функция 'localize()' является сложной в общем случае. Вы можете значительно упростить его для зоны America/New_York для известного диапазона дат. – jfs

+0

диапазон datetime от 2009-01-01 до текущего времени. Есть элементы в базе данных, которые происходят в дни смены DST, например, в прошедшее воскресенье, это создаст проблему, если я зафиксирую смещение в определенные дни. Вот почему я решил позволить базовому pytz выполнять все задания при расчете правильного смещения, особенно в дни переключения DST. – fivelements

+0

Я сказал, что вы должны игнорировать DST? Нет. Посмотрите на [источник 'localize()') (http://bazaar.launchpad.net/~stub/pytz/devel/view/head:/src/pytz/tzinfo.py): вы не знаете, t нужна вся сложность (в худшем случае достаточно простого двоичного поиска над '_utc_transition_times'), чтобы вычислить два смещения UTC для вашего ввода. – jfs

ответ

2

Спасибо за J.F. Себастьян комментарий! Вот что я решил использовать, если предположить, часовой пояс по умолчанию для этих объектов datatime соответствуют часовому поясу OS:

def conv_tz2(dt, dest_tz): 
    if not dt: return None 
    return datetime.fromtimestamp(dt.timestamp(), dest_tz) 

И это работает небольшая часть исходного conv_tz. Вот тест, основанный на полумиллионном преобразовании:

ncalls tottime percall cumtime percall filename:lineno(function) 
567669 0.664 0.000 23.354 0.000 ../test/test_tz.py:17(conv_tz) 
567669 4.831 0.000 18.732 0.000 /app/python/lib/python3.4/site-packages/pytz/tzinfo.py:244(localize) 
567669 0.472 0.000 5.786 0.000 ../test/test_tz.py:22(conv_tz2)