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

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

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

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

current_time_in_new_timezone = ???

4 ответа

Решение

Если вы знаете свой часовой пояс происхождения и новый часовой пояс, в который хотите преобразовать его, сначала используйте 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 как системный стандарт и избегать всей проблемы летнего времени. Для контекста по этому вопросу см.: http://lucumr.pocoo.org/2011/7/15/eppur-si-muove/

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

В Python 3.9 в стандартной библиотеке есть все, что вам нужно: zoneinfo. pytz больше не нужен (устарело; -> устаревшая прокладка pytz ).

Бывший:

      from datetime import datetime
from zoneinfo import ZoneInfo

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

current_time = datetime.now(ZoneInfo(server_timezone)) 

# current_time_in_new_timezone = ???
current_time_in_new_timezone = current_time.astimezone(ZoneInfo(new_timezone))

print(current_time_in_new_timezone)
print(repr(current_time_in_new_timezone))

# 2021-05-02 02:02:38.976798-07:00
# datetime.datetime(2021, 5, 2, 2, 2, 38, 976798, tzinfo=zoneinfo.ZoneInfo(key='US/Pacific'))

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

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

  1. Создайте осведомленные объекты 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)
    

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

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

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

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

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

Если вы хотите преобразовать метку времени из одного часового пояса в другой, вы можете использовать этот код:

      from datetime import datetime
from zoneinfo import ZoneInfo


from_timezone = ZoneInfo('Europe/Moscow')  # UTC-3
to_timezone = ZoneInfo('Asia/Tbilisi')  # UTC-4

dt = datetime.fromtimestamp(timestamp, to_timezone)
result_timestamp = int(dt.replace(tzinfo=from_timezone).timestamp())

Например, если вы возьмете timestamp = 529635600 (1986-14-10 04:00:00 в Москве) и запустите этот код, вы получите result_timestamp = 529639200 (1986-14-10 05:00:00 в Тбилиси).

Другие вопросы по тегам