Как получить системный часовой пояс и передать его в pytz.timezone?
Мы можем использовать time.tzname
получить имя местного часового пояса, но это имя не совместимо с pytz.timezone
,
На самом деле имя возвращается time.tzname
неоднозначно. Этот метод возвращает ('CST', 'CST')
в моей системе, но "CST" может указывать четыре часовых пояса:
- Центральный часовой пояс (Северная Америка) - наблюдается в центральном часовом поясе Северной Америки
- Стандартное время Китая
- Стандартное время Chungyuan - термин "Стандартное время Chungyuan" в настоящее время редко используется на Тайване
- Центральное австралийское время (ACST)
6 ответов
Очень простой способ решить этот вопрос:
import time
def localTzname():
offsetHour = time.timezone / 3600
return 'Etc/GMT%+d' % offsetHour
Обновление: @MartijnPieters сказал: "Это не будет работать с DST / летнее время". Так как насчет этой версии?
import time
def localTzname():
if time.daylight:
offsetHour = time.altzone / 3600
else:
offsetHour = time.timezone / 3600
return 'Etc/GMT%+d' % offsetHour
tzlocal
модуль возвращает объект pytz tzinfo, соответствующий местному часовому поясу:
import time
from datetime import datetime
import pytz # $ pip install pytz
from tzlocal import get_localzone # $ pip install tzlocal
# get local timezone
local_tz = get_localzone()
# test it
# utc_now, now = datetime.utcnow(), datetime.now()
ts = time.time()
utc_now, now = datetime.utcfromtimestamp(ts), datetime.fromtimestamp(ts)
local_now = utc_now.replace(tzinfo=pytz.utc).astimezone(local_tz) # utc -> local
assert local_now.replace(tzinfo=None) == now
Он работает даже при переходах на летнее время, когда местное время может быть неоднозначным.
local_tz
также работает для прошлых дат, даже если смещение utc для местного часового пояса было другим в то время. dateutil.tz.tzlocal()
В этом случае решение на основе не срабатывает, например, в часовом поясе Европа / Москва (пример с 2013 года):
>>> import os, time
>>> os.environ['TZ'] = 'Europe/Moscow'
>>> time.tzset()
>>> from datetime import datetime
>>> from dateutil.tz import tzlocal
>>> from tzlocal import get_localzone
>>> dateutil_tz = tzlocal()
>>> tzlocal_tz = get_localzone()
>>> datetime.fromtimestamp(0, dateutil_tz)
datetime.datetime(1970, 1, 1, 4, 0, tzinfo=tzlocal())
>>> datetime.fromtimestamp(0, tzlocal_tz)
datetime.datetime(1970, 1, 1, 3, 0, tzinfo=<DstTzInfo 'Europe/Moscow' MSK+3:00:00 STD>)
dateutil возвращает неправильное смещение UTC+4 вместо правильного UTC+3 1970-01-01.
Для тех, кто столкнулся с этим в 2017 году dateutil.tz.tzlocal()
все еще сломан. Вышеприведенный пример работает сейчас, потому что текущее смещение utf в Москве UTC+3 (что случайно равно смещению utc от 1970 года). Чтобы продемонстрировать ошибку, мы можем выбрать дату, когда смещение utc равно UTC+4:
>>> import os, time
>>> os.environ['TZ'] = 'Europe/Moscow'
>>> time.tzset()
>>> from datetime import datetime
>>> from dateutil.tz import tzlocal
>>> from tzlocal import get_localzone
>>> dateutil_tz = tzlocal()
>>> tzlocal_tz = get_localzone()
>>> ts = datetime(2014, 6,1).timestamp() # get date in 2014 when gmtoff=14400 in Moscow
>>> datetime.fromtimestamp(ts, dateutil_tz)
datetime.datetime(2014, 5, 31, 23, 0, tzinfo=tzlocal())
>>> datetime.fromtimestamp(ts, tzlocal_tz)
datetime.datetime(2014, 6, 1, 0, 0, tzinfo=<DstTzInfo 'Europe/Moscow' MSK+4:00:00 STD>)
dateutil возвращает неправильное смещение UTC+3 вместо правильного UTC+4 2014-06-01.
Начиная с Python 3.6, вы можете просто запустить naive_datetime.astimezone()
и часовой пояс системы будет добавлен в naive_datetime
объект.
Если вызывается без аргументов (или с tz=None), системный часовой пояс местного времени принимается за целевой часовой пояс. Атрибут.tzinfo преобразованного экземпляра datetime будет установлен на экземпляр часового пояса с именем зоны и смещением, полученными из ОС.
https://docs.python.org/3/library/datetime.html
Пример:
>>> import datetime
>>> datetime.datetime.now().astimezone().isoformat(timespec='minutes')
'2018-10-02T13:09+03:00'
Использовать tzlocal
функция от python-dateutil
пакет:
from dateutil.tz import tzlocal
localtimezone = tzlocal()
Внутренне, это класс, который использует time.timezone
а также time.altzone
(переключение на основе time.daylight
), но из этого создает подходящий объект часового пояса.
Вы используете это вместо pytz
часовой пояс.
Альтернативой является чтение текущего настроенного часового пояса из операционной системы, но это сильно отличается от ОС к ОС. В Mac OS X вам нужно прочитать вывод systemsetup -gettimezone
:
$ systemsetup -gettimezone
Time Zone: Europe/Copenhagen
В системах Debian и Ubuntu вы можете прочитать /etc/timezone
:
$ cat /etc/timezone
Europe/Oslo
На RedHat и направленных системах вам нужно прочитать его с /etc/sysconfig/clock
:
$ grep ZONE /etc/sysconfig/clock
ZONE="Europe/Oslo"
Я не знаю, полезно ли это для вас или нет, но я думаю, что это решает вашу более общую проблему:
если у вас есть дата, которая находится в неоднозначном часовом поясе, как CST
Простая дата (только python 3.2+, извините) может автоматизировать поиск и позволяет делать такие вещи, как предпочитать определенные страны.
например:
>>> SimpleDate('2013-07-04 18:53 CST')
Traceback [...
simpledate.AmbiguousTimezone: 3 distinct timezones found: <DstTzInfo 'Australia/Broken_Hill' CST+9:30:00 STD>; <DstTzInfo 'America/Regina' LMT-1 day, 17:01:00 STD>; <DstTzInfo 'Asia/Harbin' LMT+8:27:00 STD> (timezones=('CST',), datetime=datetime.datetime(2013, 7, 4, 18, 53), is_dst=False, country=None, unsafe=False)
>>> SimpleDate('2013-07-04 18:53 CST', country='CN')
SimpleDate('2013-07-04 18:53 CST')
>>> SimpleDate('2013-07-04 18:53 CST', country='CN').utc
SimpleDate('2013-07-04 10:53 UTC', tz='UTC')
обратите внимание, что, указав страну, вы достаточно уменьшаете диапазон возможных значений, чтобы разрешить преобразование в UTC.
это реализовано путем поиска по часовым поясам в PyTZ:
>>> SimpleDate('2013-07-04 18:53 CST', country='CN', debug=True)
...
PyTzFactory: Have country code CN
PyTzFactory: Country code CN has 5 timezones
PyTzFactory: Expanded country codes to 5 timezones
PyTzFactory: Expanding ('CST',)
PyTzFactory: Name lookup failed for CST
PyTzFactory: Found CST using Asia/Shanghai
PyTzFactory: Found CST using Asia/Harbin
PyTzFactory: Found CST using Asia/Chongqing
PyTzFactory: Found CST using Asia/Urumqi
PyTzFactory: Found CST using Asia/Kashgar
PyTzFactory: Expanded timezone to 5 timezones
PyTzFactory: New offset 8:00:00 for Asia/Shanghai
PyTzFactory: Known offset 8:00:00 for Asia/Harbin
PyTzFactory: Known offset 8:00:00 for Asia/Chongqing
PyTzFactory: Known offset 8:00:00 for Asia/Urumqi
PyTzFactory: Known offset 8:00:00 for Asia/Kashgar
PyTzFactory: Have 1 distinct timezone(s)
PyTzFactory: Found Asia/Shanghai
...
SimpleDate('2013-07-04 18:53 CST')
наконец, чтобы ответить на заданный вопрос, он также включает tzlocal, как уже упоминалось в другом ответе, поэтому автоматически выполнит то, что вы ожидаете, если вы не указали часовой пояс. например, я живу в Чили, так
>>> SimpleDate()
SimpleDate('2013-07-04 19:21:25.757222 CLT', tz='America/Santiago')
>>> SimpleDate().tzinfo
<DstTzInfo 'America/Santiago' CLT-1 day, 20:00:00 STD>
дает часовой пояс моей локали (двусмысленный или нет).
import pytz
скажем, у вас есть список значений utc DateTime в объекте списка OBJ.
tz=pytz.timezone('Asia/Singapore')
найдите ниже url, чтобы получить соответствующий параметр позиционной строки часового пояса. Есть ли список часовых поясов Pytz?
Теперь наш ТЗ является объектом сингапурского времени.
result=[]
for i in OBJ:
i=i+tz.utcoffset(i)
result.append(i)
объект списка результатов имеет значение DateTime вашего соответствующего часового пояса