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'))
Как вы конвертируете дату / время из одного часового пояса в другой?
Есть два шага:
Создайте осведомленные объекты 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)
работает даже в неоднозначные времена, например, во время переходов DSTserver_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?"Преобразовать осведомленный объект даты и времени в целевой часовой пояс
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 в Тбилиси).