> **Источник:** https://python-all.ru/3.9/library/zoneinfo.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

# [`zoneinfo`](https://python-all.ru/3.9/library/zoneinfo.html#module-zoneinfo) – поддержка часовых поясов IANA

Новое в версии 3.9.

---

Модуль [`zoneinfo`](https://python-all.ru/3.9/library/zoneinfo.html#module-zoneinfo) предоставляет конкретную реализацию часового пояса для поддержки базы данных часовых поясов IANA, изначально описанной в [**PEP 615**](https://python-all.ru/3.9/library/zoneinfo.html). По умолчанию [`zoneinfo`](https://python-all.ru/3.9/library/zoneinfo.html#module-zoneinfo) использует системные данные о часовых поясах, если они доступны; если системные данные недоступны, библиотека использует собственный пакет [tzdata](https://python-all.ru/3.9/library/zoneinfo.html), доступный на PyPI.

> **См. также**
>
> **Модуль: [`datetime`](https://python-all.ru/3.9/library/datetime.html#module-datetime)**
>
> Предоставляет типы [`time`](https://python-all.ru/3.9/library/datetime.html#datetime.time) и [`datetime`](https://python-all.ru/3.9/library/datetime.html#datetime.datetime), для использования с которыми предназначен класс [`ZoneInfo`](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo.ZoneInfo).
>
> **Пакет [tzdata](https://python-all.ru/3.9/library/zoneinfo.html)**
>
> Пакет, поддерживаемый основными разработчиками CPython, для поставки данных о часовых поясах через PyPI.

## Использование `ZoneInfo`

[`ZoneInfo`](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo.ZoneInfo) – это конкретная реализация абстрактного базового класса [`datetime.tzinfo`](https://python-all.ru/3.9/library/datetime.html#datetime.tzinfo), предназначенная для прикрепления к `tzinfo` через конструктор, метод [`datetime.replace`](https://python-all.ru/3.9/library/datetime.html#datetime.datetime.replace) или [`datetime.astimezone`](https://python-all.ru/3.9/library/datetime.html#datetime.datetime.astimezone):

```python
>>> from zoneinfo import ZoneInfo
>>> from datetime import datetime, timedelta

>>> dt = datetime(2020, 10, 31, 12, tzinfo=ZoneInfo("America/Los_Angeles"))
>>> print(dt)
2020-10-31 12:00:00-07:00

>>> dt.tzname()
'PDT'
```

Объекты datetime, созданные таким образом, совместимы с арифметикой datetime и обрабатывают переходы на летнее время без дополнительных действий:

```python
>>> dt_add = dt + timedelta(days=1)

>>> print(dt_add)
2020-11-01 12:00:00-08:00

>>> dt_add.tzname()
'PST'
```

Эти часовые пояса также поддерживают атрибут [`fold`](https://python-all.ru/3.9/library/datetime.html#datetime.datetime.fold), введённый в [**PEP 495**](https://python-all.ru/3.9/library/zoneinfo.html). При переходах смещения, вызывающих неоднозначное время (например, переход с летнего на стандартное время), смещение *до* перехода используется, когда `fold=0`, а смещение *после* перехода используется, когда `fold=1`, например:

```python
>>> dt = datetime(2020, 11, 1, 1, tzinfo=ZoneInfo("America/Los_Angeles"))
>>> print(dt)
2020-11-01 01:00:00-07:00

>>> print(dt.replace(fold=1))
2020-11-01 01:00:00-08:00
```

При преобразовании из другого часового пояса атрибут fold будет установлен в правильное значение:

```python
>>> from datetime import timezone
>>> LOS_ANGELES = ZoneInfo("America/Los_Angeles")
>>> dt_utc = datetime(2020, 11, 1, 8, tzinfo=timezone.utc)

>>> # Перед переходом с PDT на PST
>>> print(dt_utc.astimezone(LOS_ANGELES))
2020-11-01 01:00:00-07:00

>>> # После перехода с PDT на PST
>>> print((dt_utc + timedelta(hours=1)).astimezone(LOS_ANGELES))
2020-11-01 01:00:00-08:00
```

## Источники данных

Модуль `zoneinfo` не предоставляет данные о часовых поясах напрямую, а получает информацию о часовых поясах из системной базы данных часовых поясов или из основного пакета PyPI [tzdata](https://python-all.ru/3.9/library/zoneinfo.html), если он доступен. Некоторые системы, в частности Windows, не имеют базы данных IANA, поэтому для проектов, нацеленных на кроссплатформенную совместимость и требующих данные о часовых поясах, рекомендуется объявить зависимость от tzdata. Если ни системные данные, ни tzdata недоступны, все вызовы [`ZoneInfo`](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo.ZoneInfo) будут вызывать [`ZoneInfoNotFoundError`](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo.ZoneInfoNotFoundError).

### Настройка источников данных

При вызове `ZoneInfo(key)` конструктор сначала ищет в каталогах, указанных в [`TZPATH`](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo.TZPATH), файл, соответствующий `key`, а в случае неудачи ищет совпадение в пакете tzdata. Это поведение можно настроить тремя способами:

1. Значение [`TZPATH`](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo.TZPATH) по умолчанию, если не указано иное, можно настроить [на этапе компиляции](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo-data-compile-time-config).
2. [`TZPATH`](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo.TZPATH) можно настроить с помощью [переменной окружения](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo-data-environment-var).
3. [Во время выполнения](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo-data-runtime-config) путь поиска можно изменить с помощью функции [`reset_tzpath()`](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo.reset_tzpath).

#### Настройка на этапе компиляции

По умолчанию [`TZPATH`](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo.TZPATH) включает несколько распространённых мест развёртывания базы данных часовых поясов (за исключением Windows, где нет «общеизвестных» мест для данных часовых поясов). На системах POSIX распространители и те, кто собирает Python из исходного кода и знает, где развёрнуты их системные данные часовых поясов, могут изменить путь по умолчанию, указав опцию времени компиляции `TZPATH` (или, что более вероятно, флаг `configure` `--with-tzpath`), которая должна быть строкой, разделённой [`os.pathsep`](https://python-all.ru/3.9/library/os.html#os.pathsep).

На всех платформах настроенное значение доступно как ключ `TZPATH` в [`sysconfig.get_config_var()`](https://python-all.ru/3.9/library/sysconfig.html#sysconfig.get_config_var).

#### Настройка через переменные окружения

При инициализации [`TZPATH`](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo.TZPATH) (либо во время импорта, либо при вызове [`reset_tzpath()`](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo.reset_tzpath) без аргументов) модуль `zoneinfo` будет использовать переменную окружения `PYTHONTZPATH`, если она существует, для установки пути поиска.

**`PYTHONTZPATH`**

Это строка, разделённая [`os.pathsep`](https://python-all.ru/3.9/library/os.html#os.pathsep), содержащая путь поиска часовых поясов. Она должна состоять только из абсолютных, а не относительных путей. Относительные компоненты, указанные в `PYTHONTZPATH`, использоваться не будут, но в остальном поведение при указании относительного пути определяется реализацией; CPython вызовет [`InvalidTZPathWarning`](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo.InvalidTZPathWarning), но другие реализации могут молча игнорировать ошибочный компонент или вызывать исключение.

Чтобы настроить систему на игнорирование системных данных и использование пакета tzdata, установите `PYTHONTZPATH=""`.

#### Настройка во время выполнения

Путь поиска TZ также можно настроить во время выполнения с помощью функции [`reset_tzpath()`](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo.reset_tzpath). Обычно это не рекомендуется, но вполне разумно использовать в тестовых функциях, требующих определённого пути к часовым поясам (или отключения доступа к системным часовым поясам).

## Класс `ZoneInfo`

#### `class zoneinfo.ZoneInfo(key)`

Конкретный подкласс [`datetime.tzinfo`](https://python-all.ru/3.9/library/datetime.html#datetime.tzinfo), представляющий часовой пояс IANA, заданный строкой `key`. Вызовы основного конструктора всегда будут возвращать объекты, которые сравниваются идентично; иными словами, если не происходит инвалидации кэша через [`ZoneInfo.clear_cache()`](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo.ZoneInfo.clear_cache), для всех значений `key` следующее утверждение всегда будет истинным:

```python
a = ZoneInfo(key)
b = ZoneInfo(key)
assert a is b
```

`key` должен быть в виде относительного нормализованного пути POSIX, без ссылок на родительские каталоги. Конструктор вызовет [`ValueError`](https://python-all.ru/3.9/library/exceptions.html#ValueError), если будет передан несоответствующий ключ.

Если файл, соответствующий `key`, не найден, конструктор вызовет [`ZoneInfoNotFoundError`](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo.ZoneInfoNotFoundError).

Класс `ZoneInfo` имеет два альтернативных конструктора:

#### `classmethod ZoneInfo.from_file(fobj, /, key=None)`

Создаёт объект `ZoneInfo` из файлоподобного объекта, возвращающего байты (например, файл, открытый в бинарном режиме, или объект [`io.BytesIO`](https://python-all.ru/3.9/library/io.html#io.BytesIO)). В отличие от основного конструктора, этот всегда создаёт новый объект.

Параметр `key` задаёт имя зоны для целей [`__str__()`](https://python-all.ru/3.9/reference/datamodel.html#object.__str__) и [`__repr__()`](https://python-all.ru/3.9/reference/datamodel.html#object.__repr__).

Объекты, созданные через этот конструктор, не могут быть pickled (см. [pickling](https://python-all.ru/3.9/library/zoneinfo.html#pickling)).

#### `classmethod ZoneInfo.no_cache(key)`

Альтернативный конструктор, который обходит кеш конструктора. Он идентичен основному конструктору, но возвращает новый объект при каждом вызове. Это скорее всего будет полезно для целей тестирования или демонстрации, но также может использоваться для создания системы с другой стратегией инвалидации кеша.

Объекты, созданные через этот конструктор, также будут обходить кеш процесса десериализации при десериализации (unpickled).

> **Внимание**
>
> Использование этого конструктора может неожиданным образом изменить семантику объектов datetime, используйте его только в том случае, если уверены, что это необходимо.

Также доступны следующие методы класса:

#### `classmethod ZoneInfo.clear_cache(*, only_keys=None)`

Метод для инвалидации кеша класса `ZoneInfo`. Если аргументы не переданы, все кеши инвалидируются, и следующий вызов основного конструктора для каждого ключа вернёт новый экземпляр.

Если в параметр `only_keys` передан итерируемый объект с именами ключей, из кеша будут удалены только указанные ключи. Ключи, переданные в `only_keys`, но не найденные в кеше, игнорируются.

> **Предупреждение**
>
> Вызов этой функции может неожиданным образом изменить семантику объектов datetime при использовании `ZoneInfo`; она изменяет глобальное состояние процесса и поэтому может иметь широкие последствия. Применяйте её, только если это действительно необходимо.

Класс имеет один атрибут:

#### `ZoneInfo.key`

Это [атрибут](https://python-all.ru/3.9/glossary.html#term-attribute) только для чтения, который возвращает значение `key`, переданное конструктору; это должен быть ключ поиска в базе данных часовых поясов IANA (например, `America/New_York`, `Europe/Paris` или `Asia/Tokyo`).

Для зон, созданных из файла без указания параметра `key`, этому атрибуту будет присвоено значение `None`.

> **Примечание**
>
> Хотя существует довольно распространённая практика показывать эти значения конечным пользователям, они предназначены для использования в качестве первичных ключей для представления соответствующих зон и не обязательно являются элементами пользовательского интерфейса. Такие проекты, как CLDR (Unicode Common Locale Data Repository), можно использовать для получения более удобных для пользователя строк из этих ключей.

### Строковые представления

Строковое представление, возвращаемое при вызове [`str`](https://python-all.ru/3.9/library/stdtypes.html#str) для объекта [`ZoneInfo`](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo.ZoneInfo), по умолчанию использует атрибут [`ZoneInfo.key`](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo.ZoneInfo.key) (см. примечание об использовании в документации атрибута):

```python
>>> zone = ZoneInfo("Pacific/Kwajalein")
>>> str(zone)
'Pacific/Kwajalein'

>>> dt = datetime(2020, 4, 1, 3, 15, tzinfo=zone)
>>> f"{dt.isoformat()} [{dt.tzinfo}]"
'2020-04-01T03:15:00+12:00 [Pacific/Kwajalein]'
```

Для объектов, созданных из файла без указания параметра `key`, `str` прибегает к вызову [`repr()`](https://python-all.ru/3.9/library/functions.html#repr). `repr` объекта `ZoneInfo` определяется реализацией и не обязательно стабилен между версиями, но гарантируется, что он не является допустимым ключом `ZoneInfo`.

### Сериализация pickle

Вместо сериализации всех данных переходов объекты `ZoneInfo` сериализуются по ключу, а объекты `ZoneInfo`, созданные из файлов (даже те, для которых указано значение `key`), не могут быть pickled.

Поведение файла `ZoneInfo` зависит от того, как он был создан:

1. `ZoneInfo(key)`: При создании с помощью основного конструктора объект `ZoneInfo` сериализуется по ключу, а при десериализации процесс использует основной конструктор, поэтому ожидается, что это будет тот же объект, что и другие ссылки на тот же часовой пояс. Например, если `europe_berlin_pkl` – это строка, содержащая pickle, созданный из `ZoneInfo("Europe/Berlin")`, ожидается следующее поведение:

   ```pycon
   >>> a = ZoneInfo("Europe/Berlin")
   >>> b = pickle.loads(europe_berlin_pkl)
   >>> a is b
   True
   ```
2. `ZoneInfo.no_cache(key)`: При создании через конструктор, обходящий кеш, объект `ZoneInfo` также сериализуется по ключу, но при десериализации процесс десериализации использует конструктор, обходящий кеш. Если `europe_berlin_pkl_nc` – это строка, содержащая pickle, созданный из `ZoneInfo.no_cache("Europe/Berlin")`, можно ожидать следующего поведения:

   ```pycon
   >>> a = ZoneInfo("Europe/Berlin")
   >>> b = pickle.loads(europe_berlin_pkl_nc)
   >>> a is b
   False
   ```
3. `ZoneInfo.from_file(fobj, /, key=None)`: При создании из файла объект `ZoneInfo` возбуждает исключение при попытке pickling. Если конечный пользователь хочет pickle объект `ZoneInfo`, созданный из файла, рекомендуется использовать тип-обёртку или пользовательскую функцию сериализации: либо сериализовать по ключу, либо сохранить содержимое файлового объекта и сериализовать его.

Этот метод сериализации требует, чтобы данные часового пояса для требуемого ключа были доступны и на сериализующей, и на десериализующей стороне – аналогично тому, как ссылки на классы и функции должны существовать в обеих средах: сериализующей и десериализующей. Это также означает, что не даётся никаких гарантий согласованности результатов при десериализации (unpickling) объекта `ZoneInfo`, который был pickled в среде с другой версией данных часового пояса.

## Функции

#### `zoneinfo.available_timezones()`

Возвращает набор, содержащий все допустимые ключи для часовых поясов IANA, доступные где-либо в пути часовых поясов. Это значение пересчитывается при каждом вызове функции.

Эта функция включает только канонические имена зон и не включает «особые» зоны, такие как те, что находятся в каталогах `posix/` и `right/`, или зону `posixrules`.

> **Внимание**
>
> Эта функция может открывать большое количество файлов, так как лучший способ определить, является ли файл в пути временной зоны допустимой временной зоной, – прочитать «магическую строку» в начале.

> **Примечание**
>
> Эти значения не предназначены для отображения конечным пользователям; для элементов пользовательского интерфейса приложениям следует использовать что-то вроде CLDR (Общего репозитория локалей Unicode), чтобы получить более удобочитаемые строки. См. также предостережение по [`ZoneInfo.key`](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo.ZoneInfo.key).

#### `zoneinfo.reset_tzpath(to=None)`

Устанавливает или сбрасывает путь поиска временной зоны ([`TZPATH`](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo.TZPATH)) для модуля. При вызове без аргументов [`TZPATH`](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo.TZPATH) устанавливается в значение по умолчанию.

Вызов `reset_tzpath` не сбросит кеш [`ZoneInfo`](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo.ZoneInfo), поэтому вызовы конструктора `ZoneInfo` будут использовать новый `TZPATH` только в случае промаха кеша.

Параметр `to` должен быть [последовательностью](https://python-all.ru/3.9/glossary.html#term-sequence) строк или [`os.PathLike`](https://python-all.ru/3.9/library/os.html#os.PathLike), а не строкой, причём все элементы должны быть абсолютными путями. Будет вызвано исключение [`ValueError`](https://python-all.ru/3.9/library/exceptions.html#ValueError), если передан не абсолютный путь.

## Глобальные переменные

#### `zoneinfo.TZPATH`

Последовательность только для чтения, представляющая путь поиска временной зоны: при создании `ZoneInfo` по ключу ключ объединяется с каждым элементом в `TZPATH`, и используется первый найденный файл.

`TZPATH` может содержать только абсолютные пути, никогда – относительные, независимо от способа настройки.

Объект, на который указывает `zoneinfo.TZPATH`, может измениться при вызове [`reset_tzpath()`](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo.reset_tzpath), поэтому рекомендуется использовать `zoneinfo.TZPATH`, а не импортировать `TZPATH` из `zoneinfo` или присваивать `zoneinfo.TZPATH` долгоживущей переменной.

Для получения дополнительной информации о настройке пути поиска временной зоны см. [Настройка источников данных](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo-data-configuration).

## Исключения и предупреждения

#### `exception zoneinfo.ZoneInfoNotFoundError`

Возникает, когда создание объекта [`ZoneInfo`](https://python-all.ru/3.9/library/zoneinfo.html#zoneinfo.ZoneInfo) завершается неудачей, так как указанный ключ не найден в системе. Это подкласс [`KeyError`](https://python-all.ru/3.9/library/exceptions.html#KeyError).

#### `exception zoneinfo.InvalidTZPathWarning`

Возникает, когда [`PYTHONTZPATH`](https://python-all.ru/3.9/library/zoneinfo.html#envvar-PYTHONTZPATH) содержит недопустимый компонент, который будет отфильтрован, например, относительный путь.
