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']