Python: выяснить местный часовой пояс - PullRequest
49 голосов
/ 27 апреля 2010

Я хочу сравнить метки времени UTC из файла журнала с местными метками времени. При создании локального datetime объекта я использую что-то вроде:

>>> local_time=datetime.datetime(2010, 4, 27, 12, 0, 0, 0, 
                                 tzinfo=pytz.timezone('Israel'))

Я хочу найти автоматический инструмент, который заменит tzinfo=pytz.timezone('Israel') на текущий часовой пояс.

Есть идеи?

Ответы [ 15 ]

58 голосов
/ 22 августа 2016

В Python 3.x местный часовой пояс может быть определен так:

import datetime
LOCAL_TIMEZONE = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo

Это хитрое использование datetime ' кода .

30 голосов
/ 27 апреля 2010

Попробуйте dateutil с типом tzlocal , который делает то, что вам нужно.

27 голосов
/ 28 июня 2013

для сравнения меток времени UTC из файла журнала с локальными метками времени.

трудно найти название Olson TZ для местного часового пояса портативным способом. К счастью, он не нужен для сравнения.

tzlocal модуль возвращает pytz часовой пояс, соответствующий местному часовому поясу:

from datetime import datetime

import pytz # $ pip install pytz
from tzlocal import get_localzone # $ pip install tzlocal

tz = get_localzone()
local_dt = tz.localize(datetime(2010, 4, 27, 12, 0, 0, 0), is_dst=None)
utc_dt = local_dt.astimezone(pytz.utc) #NOTE: utc.normalize() is unnecessary here

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

  • местное время может быть неоднозначным , т. Е. Точное сравнение может быть невозможно для некоторых локальных времен
  • Смещение utc может отличаться для одного и того же имени местного часового пояса для дат в прошлом. Некоторые библиотеки, которые поддерживают объекты datetime с учетом часового пояса (например, dateutil), не учитывают это

Примечание: чтобы получить объект datetime с учетом часового пояса из наивного объекта datetime, вы должны использовать *:

local_dt = tz.localize(datetime(2010, 4, 27, 12, 0, 0, 0), is_dst=None)

вместо:

#XXX fails for some timezones
local_dt = datetime(2010, 4, 27, 12, 0, 0, 0, tzinfo=tz)

*is_dst=None вызывает исключение, если заданное местное время неоднозначно или отсутствует.

Если вы уверены, что все локальные временные метки используют одинаковое (текущее) смещение utc для локального часового пояса, тогда вы можете выполнить сравнение, используя только stdlib:

# convert a naive datetime object that represents time in local timezone to epoch time
timestamp1 = (datetime(2010, 4, 27, 12, 0, 0, 0) - datetime.fromtimestamp(0)).total_seconds()

# convert a naive datetime object that represents time in UTC to epoch time
timestamp2 = (datetime(2010, 4, 27, 9, 0) - datetime.utcfromtimestamp(0)).total_seconds()

timestamp1 и timestamp2 можно сравнивать напрямую.

Примечание:

  • timestamp1 формула работает, только если смещение UTC в эпоху (datetime.fromtimestamp(0)) такое же, как сейчас
  • fromtimestamp() создает наивный объект datetime в текущем местном часовом поясе
  • utcfromtimestamp() создает наивный объект даты-времени в UTC.
12 голосов
/ 09 декабря 2013

Я спрашивал про себя то же самое и нашел ответ в 1:

Взгляните на раздел 8.1.7: формат "% z" (строчные буквы, прописные буквы Z возвращают также часовой пояс, но не в 4-значном формате, а в виде сокращений часовых поясов, как в [ 3]) из strftime возвращает форму "+/- 4DIGIT", стандартную для заголовков электронной почты (см. Раздел 3.3 RFC 2822, см. [2], в котором устарели другие способы указания часового пояса для заголовков электронной почты).

Итак, если вы хотите использовать часовой пояс в этом формате, используйте:

time.strftime("%z")

[1] http://docs.python.org/2/library/datetime.html

[2] http://tools.ietf.org/html/rfc2822#section-3.3

[3] Сокращения часовых поясов: http://en.wikipedia.org/wiki/List_of_time_zone_abbreviations, только для справки.

6 голосов
/ 10 октября 2014

Сначала получите модули pytz и tzlocal

pip install pytz tzlocal

тогда

from tzlocal import get_localzone
local = get_localzone()

тогда вы можете делать такие вещи, как

from datetime import datetime
print(datetime.now(local))
4 голосов
/ 03 сентября 2014

Вот способ получить местный часовой пояс, используя только стандартную библиотеку (работает только в среде * nix):

>>> '/'.join(os.path.realpath('/etc/localtime').split('/')[-2:])
'Australia/Sydney'

Вы можете использовать это для создания pytz часового пояса:

>>> import pytz
>>> my_tz_name = '/'.join(os.path.realpath('/etc/localtime').split('/')[-2:])
>>> my_tz = pytz.timezone(my_tz_name)
>>> my_tz
<DstTzInfo 'Australia/Sydney' LMT+10:05:00 STD>

... который вы затем можете применить к datetime:

>>> import datetime
>>> now = datetime.datetime.now()
>>> now
datetime.datetime(2014, 9, 3, 9, 23, 24, 139059)

>>> now.replace(tzinfo=my_tz)
>>> now
datetime.datetime(2014, 9, 3, 9, 23, 24, 139059, tzinfo=<DstTzInfo 'Australia/Sydney' LMT+10:05:00 STD>)
3 голосов
/ 15 апреля 2018

Вот несколько более краткая версия решения @ vbem:

from datetime import datetime as dt

dt.utcnow().astimezone().tzinfo

Единственное существенное отличие состоит в том, что я заменил datetime.datetime.now(datetime.timezone.utc) на datetime.datetime.utcnow(). Для краткости я также назвал datetime.datetime как dt.

Для моих целей я хочу смещение UTC в секундах. Вот как это выглядит:

dt.utcnow().astimezone().utcoffset().total_seconds()
3 голосов
/ 17 марта 2017

Исходя из ответа Дж. Ф. Себастьяна , вы можете сделать это с помощью стандартной библиотеки:

import time, datetime
local_timezone = datetime.timezone(datetime.timedelta(seconds=-time.timezone))

Протестировано в 3.4, должно работать на 3.4 +

2 голосов
/ 28 июня 2013

Основываясь на ответе Току выше, вот ответ, который разрешает часовой пояс с точностью до получаса (что актуально для некоторых часовых поясов, например, для Южной Австралии):

from datetime import datetime
round((round((datetime.now()-datetime.utcnow()).total_seconds())/1800)/2)
2 голосов
/ 17 апреля 2013

Как избежать нестандартного модуля (кажется, отсутствует метод модуля datetime):

from datetime import datetime
utcOffset_min = int(round((datetime.now() - datetime.utcnow()).total_seconds())) / 60   # round for taking time twice
utcOffset_h = utcOffset_min / 60
assert(utcOffset_min == utcOffset_h * 60)   # we do not handle 1/2 h timezone offsets

print 'Local time offset is %i h to UTC.' % (utcOffset_h)
...