Python: Как вы конвертируете datetime/timestamp из одного часового пояса в другой часовой пояс?

В частности, учитывая часовой пояс моего сервера (системная временная перспектива) и ввод часового пояса, как мне рассчитать системное время, как если бы оно находилось в этом новом часовом поясе (независимо от летнего времени и т.д.)?

import datetime
current_time = datetime.datetime.now() #system time

server_timezone = "US/Eastern"
new_timezone = "US/Pacific"

current_time_in_new_timezone = ???

Ответ 1

Если вы знаете часовой пояс вашего происхождения и новый часовой пояс, в который хотите его преобразовать, сначала используйте pytz.localize для обработки любой локализации (например, для перехода на летнее время и т.д.), затем используйте pytz.timezone для создания объектов часового пояса и, наконец, используйте datetime.astimezone(timezone) для легкого вычисления. Например:

import datetime
import pytz # new import

my_timestamp = datetime.datetime.now() # some timestamp
old_timezone = pytz.timezone("US/Eastern")
new_timezone = pytz.timezone("US/Pacific")

# returns datetime in the new timezone
my_timestamp_in_new_timezone = old_timezone.localize(my_timestamp).astimezone(new_timezone) 

И, конечно, если все, что вы хотите, это текущее время в определенном часовом поясе, вы можете передать этот часовой пояс прямо в datetime.now(), чтобы получить метку времени. Вот так:

datetime.datetime.now(new_timezone)

Теперь, со всем сказанным, я настоятельно рекомендую хранить все ваши временные метки в UTC как системный стандарт и избегать всей проблемы DST. Для контекста по этому поводу см.: http://lucumr.pocoo.org/2011/7/15/eppur-si-muove/

И знать, как сложно справляться с расчетами времени в целом: http://yourcalendricalfallacyis.com

Ответ 2

Как конвертировать datetime/timestamp из одного часового пояса в другой часовой пояс?

Есть два шага:

  • Создайте известные объекты datetime из системного времени и часовой пояс, например, чтобы получить текущее системное время в данном часовом поясе:

    #!/usr/bin/env python
    from datetime import datetime
    import pytz
    
    server_timezone = pytz.timezone("US/Eastern")
    server_time = datetime.now(server_timezone) # you could pass *tz* directly
    

    Примечание: datetime.now(server_timezone) работает даже в неоднозначное время, например, во время переходов DST, в то время как server_timezone.localize(datetime.now()) может выйти из строя (вероятность 50%).

    Если вы уверены, что ваше время ввода существует в часовом поясе сервера, и оно уникально, вы можете передать is_dst=None, чтобы утверждать, что:

    server_time = server_timezone.localize(naive_time, is_dst=None)
    

    Это вызывает исключение для недопустимых времен. Если допустимо игнорировать до дневной ошибки (хотя обычно ошибка из-за DST составляет около часа), вы можете отказаться от параметра is_dst:

    server_time = server_timezone.normalize(server_timezone.localize(naive_time))
    

    .normalize() вызывается для корректировки несуществующих времен (локальное время в промежутке, во время "spring переходов вперед" ). Если правила часового пояса не изменились; ваш сервер не должен генерировать несуществующие времена. См. "Могу ли я просто установить is_dst = True?"

  • Преобразовать известный объект datetime в целевой часовой пояс tz:

    tz = pytz.timezone("US/Pacific")
    server_time_in_new_timezone = server_time.astimezone(tz)
    

Ответ 3

Я даю вам несколько указателей, чтобы выполнить то, о чем вы просите. Предупреждение: настройка среды TZ влияет на всю программу, вы можете сохранить текущий TZ и восстановить его, когда закончите.

import os
import datetime
os.environ['TZ'] = 'US/Pacific'
print datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

2015-08-12 18:28:34

os.environ['TZ'] = 'US/Eastern'
print datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

2015-08-12 21:28:42

del os.environ['TZ']