К сожалению, я считаю, что это правда, что вы, как правило, не можете получить эту информацию из развернутых файлов TZif
, поскольку, как вы заметили, в зонах IANA содержится больше информации, чем может быть надлежащим образом зафиксировано строкой POSIX
и любым другим такое правило, используемое для генерации файла, теряется в процессе компиляции.
Два «вторых лучших» решения, которые вы можете попробовать:
Как описано в RF C 8536 , любой файл V2 + TZif
(то есть любой файл, сгенерированный zic
с ~ 2004 года) будет иметь строку POSIX TZ
в конце данных для данной зоны, это смещения, которые применяются в данной зоне после переходов, указанных в конце файла. Как правило, это соответствует лучшему предположению базы данных о том, какие правила будут в будущем (т.е. после 2038-01-18), но я не удивлюсь, обнаружив, что это лучшее предположение почти во всех случаях «переходы часовых поясов будут продолжать следовать текущим правилам».
Формат TZif
легко пропустить, поэтому вам просто нужно проанализировать заголовок ( здесь Apache -лицензированный класс , который можно скопировать-вставить и преобразовать в Python 2, если вы должны ), а затем перейти к концу данных перехода для восстановления. строка POSIX.
TZ str является последним в файле, и он разделен символами новой строки, поэтому в твите Артура Дэвида Олсона вы можете извлечь его с помощью следующего команда:
tail -1 path/to/zone
Последние версии базы данных часовых поясов создадут
tzdata.zi
файл «компактных текстовых данных», который будет иметь необработанные входные данные для синтаксического анализатора
zic
. Вот
пример формата :
R u 1918 1919 - Mar lastSu 2 1 D
R u 1918 1919 - O lastSu 2 0 S
R u 1942 o - F 9 2 1 W
R u 1945 o - Au 14 23u 1 P
R u 1945 o - S 30 2 0 S
R u 1967 2006 - O lastSu 2 0 S
R u 1967 1973 - Ap lastSu 2 1 D
R u 1974 o - Ja 6 2 1 D
R u 1975 o - F lastSu 2 1 D
R u 1976 1986 - Ap lastSu 2 1 D
R u 1987 2006 - Ap Su>=1 2 1 D
R u 2007 ma - Mar Su>=8 2 1 D
R u 2007 ma - N Su>=1 2 0 S
...
R NY 1920 o - Mar lastSu 2 1 D
R NY 1920 o - O lastSu 2 0 S
R NY 1921 1966 - Ap lastSu 2 1 D
R NY 1921 1954 - S lastSu 2 0 S
R NY 1955 1966 - O lastSu 2 0 S
Z America/New_York -4:56:2 - LMT 1883 N 18 12:3:58
-5 u E%sT 1920
-5 NY E%sT 1942
-5 u E%sT 1946
-5 NY E%sT 1967
-5 u E%sT
Как видите, для многих зон есть нужная вам информация - вам нужно знать, что правило u
применяется к America/New_York
, начиная с 1967 года, используя сокращения E% sT и начиная с 2007 года, правило:
R u 2007 ma - Mar Su>=8 2 1 D
R u 2007 ma - N Su>=1 2 0 S
Этой информации достаточно, чтобы получить применимую в настоящее время зону POSIX, хотя она может быть больше работы, чем вы готовы.
Примечание по проверке
Если вы go с подходом # 1, есть, по крайней мере, полезный способ проверить, что строка POSIX соответствует к текущему правилу, чтобы вы хотя бы получили предупреждение о том, что у вас неверные данные, вы можете использовать dateutil.tz.tzstr
для создания часового пояса из извлеченной строки POSIX и dateutil.tz.gettz
, чтобы прочитать полные данные, а затем сравнить, что они делают то же самое в течение следующих нескольких лет. Вы можете уточнить выборку, проверив точки перехода, потому что tz.tzstr
имеет ошибочно недокументированную функцию transitions
- она документирована на tzwin
, но в текущей версии, я думаю, функции autodo c не делали неправильно работает с tzstr
. Тогда вы можете сделать что-то вроде этого:
iana_zone = tz.gettz(IANA_KEY)
posix_zone = tz.tzstr(POSIX_STR)
current_year = datetime.now().year
for year in range(current_year, current_year + 5):
transitions = posix_zone.transitions(year)
if not transitions:
continue
dst_start, dst_end = transitions
# Add your tests here
...