Как я могу преобразовать часовой пояс IANA / Olson в POSIX.1? - PullRequest
2 голосов
/ 30 апреля 2020

Я пишу некоторый временной код для ESP32 в C. Я хочу отображать время в часовом поясе, определенном во время сборки. Документы ESP32 показывают, как применить часовой пояс , но формат часового пояса должен быть в в формате POSIX.1 , например. для Сиднея, Австралия это:

AEST-10AEDT,M10.1.0/2,M4.1.0/2

Я бы хотел указать часовой пояс во время сборки в качестве имени базы данных IANA / Olson , например. Australia/Sydney и преобразовать его в формат POSIX.1 для использования в коде. Система сборки ESP32 использует CMake и файл sdkconfig, так что это означает либо макрос, определенный с помощью CMake, либо строку, вставленную в sdkconfig например.

CONFIG_TIMEZONE=AEST-10AEDT,M10.1.0/2,M4.1.0/2

Есть ли таблица или база данных, которые я мог бы просмотреть это в кроссплатформенной утилите, которая может сделать преобразование? Набор инструментов ESP IDF сильно зависит от Python (2.7), поэтому даже что-то в Python может работать. Чем меньше сложностей в интеграции этого в сборку, тем лучше. Я просто не могу найти ничего в виде автономных утилит или кроссплатформенных библиотек, которые легко обернуть и вызвать из CMake.

(я знаю, что формат POSIX.1 содержит меньше информации, чем данные IANA, и Я был бы счастлив просто с выражением POSIX.1, которое дает текущее поведение re. UT C смещение и летнее время.)

1 Ответ

3 голосов
/ 30 апреля 2020

К сожалению, я считаю, что это правда, что вы, как правило, не можете получить эту информацию из развернутых файлов TZif, поскольку, как вы заметили, в зонах IANA содержится больше информации, чем может быть надлежащим образом зафиксировано строкой POSIX и любым другим такое правило, используемое для генерации файла, теряется в процессе компиляции.

Два «вторых лучших» решения, которые вы можете попробовать:

  1. Как описано в 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
    ...
...