Подтвердить что ты не робот

Python: отображение локального часового пояса

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

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

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

Любые идеи?

4b9b3361

Ответ 1

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

Ответ 2

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

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

Это сложное использование datetime code.

Ответ 3

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

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

tzlocal module возвращает часовой пояс 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() создает наивный объект datetime в UTC.

Ответ 4

Я спрашивал об этом сам, и я нашел ответ в 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, только для справки.

Ответ 5

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

pip install pytz tzlocal

затем

from tzlocal import get_localzone
local = get_localzone()

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

from datetime import datetime
print(datetime.now(local))

Ответ 6

Здесь можно получить локальный часовой пояс, используя только стандартную библиотеку (работает только в среде * 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>)

Ответ 7

Основываясь на J. F. Ответ Себастьяна, вы можете сделать это со стандартной библиотекой:

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

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

Ответ 8

Вот несколько более краткая версия решения @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()

Ответ 9

Избегание нестандартного модуля (кажется, отсутствует метод модуля 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)

Ответ 10

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

from datetime import datetime
round((round((datetime.now()-datetime.utcnow()).total_seconds())/1800)/2)

Ответ 11

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

import datetime
import time

class LocalTZ(datetime.tzinfo):
    _unixEpochOrdinal = datetime.datetime.utcfromtimestamp(0).toordinal()

    def dst(self, dt):
        return datetime.timedelta(0)

    def utcoffset(self, dt):
        t = (dt.toordinal() - self._unixEpochOrdinal)*86400 + dt.hour*3600 + dt.minute*60 + dt.second + time.timezone
        utc = datetime.datetime(*time.gmtime(t)[:6])
        local = datetime.datetime(*time.localtime(t)[:6])
        return local - utc


print datetime.datetime.now(LocalTZ())
print datetime.datetime(2010, 4, 27, 12, 0, 0, tzinfo=LocalTZ())

# If you're in the EU, the following datetimes are right on the DST change.
print datetime.datetime(2013, 3, 31, 0, 59, 59, tzinfo=LocalTZ())
print datetime.datetime(2013, 3, 31, 1, 0, 0, tzinfo=LocalTZ())
print datetime.datetime(2013, 3, 31, 1, 59, 59, tzinfo=LocalTZ())

# The following datetime is invalid, as the clock moves directly from
# 01:59:59 standard time to 03:00:00 daylight savings time.
print datetime.datetime(2013, 3, 31, 2, 0, 0, tzinfo=LocalTZ())

print datetime.datetime(2013, 10, 27, 0, 59, 59, tzinfo=LocalTZ())
print datetime.datetime(2013, 10, 27, 1, 0, 0, tzinfo=LocalTZ())
print datetime.datetime(2013, 10, 27, 1, 59, 59, tzinfo=LocalTZ())

# The following datetime is ambigous, as 02:00 can be either DST or standard
# time. (It is interpreted as standard time.)
print datetime.datetime(2013, 10, 27, 2, 0, 0, tzinfo=LocalTZ())

Ответ 12

now_dt = datetime.datetime.now()
utc_now = datetime.datetime.utcnow()
now_ts, utc_ts = map(time.mktime, map(datetime.datetime.timetuple, (now_dt, utc_now)))
offset = int((now_ts - utc_ts) / 3600)

надеюсь, это поможет вам.

Ответ 13

Вы можете быть счастливы с маятником

>>> pendulum.datetime(2015, 2, 5, tz='local').timezone.name
'Israel'

Маятник имеет хорошо разработанный API для манипулирования датами. Все в курсе ТЗ.

Ответ 14

Во-первых, обратите внимание, что вопрос представляет неправильную инициализацию объекта осведомленного объекта datetime:

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

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

>>> print(local_time.utcoffset())
2:21:00

(Обратите внимание на результат, который является нечетной долей часа.)

Для правильной инициализации достоверного datetime с помощью pytz следует использовать метод localize() следующим образом:

>>> local_time=pytz.timezone('Israel').localize(datetime.datetime(2010, 4, 27, 12))
>>> print(local_time.utcoffset())
3:00:00

Теперь, если вам нужен локальный часовой пояс pytz как новый tzinfo, вы должны использовать пакет tzlocal, как объяснили другие, но если все, что вам нужно, это экземпляр с правильным локальным часовым поясом и аббревиатурой, а затем перетасовка с помощью Python 3.3, вы можете вызвать метод astimezone() без аргументов для преобразования знающего datetime экземпляра в локальный часовой пояс:

>>> local_time.astimezone().strftime('%Y-%m-%d %H:%M %Z %z')
'2010-04-27 05:00 EDT -0400'

Ответ 15

Я также искал простой способ прочитать конфигурацию локального хоста и узнать о часовом поясе local_time на его основе. Начиная с Python 3. 6+ самый простой подход - использовать dateutil.tz, который будет читать /etc/localtime и помогать в получении объекта datetime с информацией о часовом поясе.

Вот больше информации об этом: https://dateutil.readthedocs.io/en/stable/tz.html

Реализация для достижения того, что вы ищете, выглядит следующим образом:

from datetime import datetime
from dateutil import tz
local_time = datetime.now(tz.gettz())

Это предоставит вам следующее local_time:

2019-10-18 13:41:06.624536-05:00

Дополнительные ресурсы, которые я использовал при исследовании этой темы: Пол Гансле Презентация о часовых поясах: https://www.youtube.com/watch?v=l4UCKCo9FWY

pytz: самый быстрый пулемет на западеhttps://blog.ganssle.io/articles/2018/03/pytz-fastest-footgun.html

Ответ 16

tzlocal из dateutil.

Ниже приведен пример кода. Последняя строка подходит для использования в именах файлов.

>>> from datetime import datetime
>>> from dateutil.tz import tzlocal
>>> str(datetime.now(tzlocal()))
'2015-04-01 11:19:47.980883-07:00'
>>> str(datetime.now(tzlocal())).replace(' ','-').replace(':','').replace('.','-')
'2015-04-01-111947-981879-0700'
>>>