pytz - Преобразование UTC и часового пояса в местное время

У меня datetime в часовом поясе utc, например:

utc_time = datetime.datetime.utcnow()

И объект часового пояса pytz:

tz = timezone('America/St_Johns')

Как правильно преобразовать utc_time в указанный часовой пояс?


person Tzach    schedule 12.08.2014    source источник


Ответы (6)


Думаю, я понял:

pytz.utc.localize(utc_time, is_dst=None).astimezone(tz)

Эта строка сначала преобразует наивный (не знающий часовой пояс) объект utc_time datetime в объект datetime, содержащий часовой пояс (UTC). Затем он использует функцию astimezone для настройки времени в соответствии с в запрошенный часовой пояс.

person Tzach    schedule 12.08.2014
comment
Я удалил свой ответ, вы должны принять свой как самостоятельный ответ :) - person Ffisegydd; 12.08.2014
comment
utc_time.replace(tzinfo=pytz.utc).astimezone(tz). Примечание. pytz.utc - это особый случай (всегда нулевое смещение utc). В этом случае вам не нужен localize() звонок. Если вы все же сохраните его (для общности); затем добавьте вызов tz.normalize() вокруг выражения (это может потребоваться, если исходный часовой пояс не UTC). - person jfs; 31.08.2014
comment
@ J.F.Sebastian вызов localize необходим, потому что utc_time не содержит информации о часовом поясе. Без этого astimezone работать не будет. - person Tzach; 01.09.2014
comment
@Tzach, как вы думаете, что делает вызов replace() в моем предыдущем комментарии? - person jfs; 01.09.2014
comment
Он также работает для utc_timestamp как int с datetime.utcfromtimestamp (utc_timestamp), который возвращает объект datetime, не знающий о часовом поясе. Но utc_time.replace не выполняет сдвиг по времени, а только добавляет tzinfo. - person Yingding Wang; 08.05.2019
comment
@YingdingWang Вопрос, сделанный почти 5 лет назад, не использует utcfromtimestamp. Также datetime.datetime.utcnow() устанавливает для tzinfo значение None. - person CrackerJack9; 14.07.2019
comment
localize примерно на 7% медленнее, чем replace (это также пример, используемый в документации) - person CrackerJack9; 14.07.2019
comment
Используйте fromutc (см. ответ @ user8808265). - person Jérôme; 15.03.2021

Это точное назначение функции fromutc:

tz.fromutc(utc_time)

(astimezone функция вызывает fromutc под капотом, но сначала пытается преобразовать в UTC, что в вашем случае не требуется)

person user8808265    schedule 27.10.2017
comment
Это должен быть принятый ответ, примерно в два раза быстрее, чем localize или replace - person CrackerJack9; 14.07.2019
comment
Да, так работает лучше и менее многословно, чем replace - person Sean McCarthy; 26.03.2021

Я согласен с ответом Цаха. Просто хотел добавить, что параметр is_dst не требуется:

pytz.utc.localize(datetime.utcnow()).astimezone(tz)

Этот код преобразует текущее время в формате UTC в текущую дату и время с учетом часового пояса.

В то время как приведенный ниже код преобразует текущее время в формате UTC в дату и время с учетом часового пояса, которое не обязательно является текущим. Часовой пояс просто добавляется к значению времени UTC.

tz.localize(datetime.utcnow())
person paolov    schedule 07.11.2017
comment
Если у вас уже есть дата-время с учетом часового пояса, вам просто нужно использовать astimezone: dt.astimezone(tz). См. Также этот ответ и документы pytz. - person qris; 06.04.2018
comment
Ответ user8808265 намного проще. - person Rufflewind; 06.05.2019

Могу я порекомендовать использовать стрелку? Если я понял вопрос:

>>> import arrow
>>> utc = arrow.utcnow()
>>> utc
<Arrow [2014-08-12T13:01:28.071624+00:00]>    
>>> local = utc.to("America/St_Johns")
>>> local
<Arrow [2014-08-12T10:31:28.071624-02:30]>

Вы также можете использовать

tz.fromutc(utc_time)
person xbello    schedule 12.08.2014
comment
Спасибо. Эта библиотека действительно выглядит как хорошая альтернатива datetime, однако мой проект большой, и я не хочу создавать больше путаницы, используя другую библиотеку даты и времени. Я обязательно рассмотрю возможность использования его в других проектах. - person Tzach; 12.08.2014

Еще один очень простой способ:

Поскольку метод utcnow возвращает наивный объект, вам необходимо преобразовать наивный объект в осведомленный объект. Используя метод replace, вы можете преобразовать наивный объект в осведомленный объект. Затем вы можете использовать метод astimezone для создания нового объекта datetime в другом часовом поясе.

from datetime import datetime
import pytz    
utc_time = datetime.utcnow()
tz = pytz.timezone('America/St_Johns')

utc_time =utc_time.replace(tzinfo=pytz.UTC) #replace method      
st_john_time=utc_time.astimezone(tz)        #astimezone method
print(st_john_time)
person N Randhawa    schedule 11.10.2016
comment
заменить метод - плохая идея. Это случайное поведение - person paolov; 08.11.2017

Вы также можете использовать образец ниже, я использую его для аналогичной задачи

tz = pytz.timezone('America/St_Johns')
time_difference=tz.utcoffset(utc_time).total_seconds() #time difference between UTC and local timezones in 5:30:00 format
utc_time = date + timedelta(0,time_difference)

Работает быстро, и вам не нужно импортировать дополнительные библиотеки.

person awaik    schedule 23.11.2016
comment
Это неверно для часовых поясов с переходом на летнее время, потому что они не учитываются. См. этот ответ. - person qris; 06.04.2018