Я только что заметил это и совершенно озадачен тем, почему это происходит и как я могу это предотвратить.
На компьютере, на котором я работаю, установлена Windows 10, и он установлен в городе Копенгаген. Моя платформа такова:
$ for ix in "uname -s" "python3 --version"; do echo "$ix: " $($ix); done
uname -s: MINGW64_NT-10.0-19045
python3 --version: Python 3.11.9
Поскольку я использую терминал bash под MINGW64, у меня также есть псевдоним для python3 в .bashrc:
alias python3 = "winpty python3"
ХОРОШО; поэтому теперь я хочу напечатать tzlocal.get_localzone(), вызвав команду python3 в терминале bash:
$ python3 -c 'import tzlocal; print(tzlocal.get_localzone())'
Europe/Copenhagen
Отлично, я получил именно тот часовой пояс, как и ожидал. Однако напомним, что python3 здесь на самом деле winpty python3; чтобы проверить просто python3, давайте добавим к команде обратную косую черту, чтобы избежать псевдонима bash:
$ \python3 -c 'import tzlocal; print(tzlocal.get_localzone())'
Europe/Paris
Удивительно – я никогда бы этого не ожидал; с какой стати у меня здесь Париж, а не Копенгаген (на это настроена сама Windows 10 на этой машине)?
Я имею в виду, что это не так уж и далеко, что касается часовых поясов - но зачем соглашаться на меньшее, когда очевидно, что есть условия, которые заставляют его выводить правильный часовой пояс?
Итак, почему это происходит и как мне \python3 запустить tzlocal.get_localzone() и вернуть Европу/Копенгаген?
Обновлено: напечатав os.environ в обоих случаях, можно увидеть, что среда winpty python определяет переменную среды «TZ»: «Europe/Copenhagen» - тогда как в прямой среде Python такой переменной нет.






Немного предыстории: Windows и IANA не используют одни и те же идентификаторы часовых поясов в своих базах данных часовых поясов. tzlocal дает вам идентификаторы IANA. Итак, когда вы работаете в Windows, вам нужно сопоставление между этими двумя системами БД часовых поясов. Это чревато ошибками, поскольку между IANA и MS нет соглашения о том, что это должно быть однозначно (см. также тег тег часового пояса , раздел «Базы данных часовых поясов»). tzlocal полагается в этом на усилия сообщества.
В Windows, если я устанавливаю tz на Копенгаген, Windows использует внутреннее «Романтское стандартное время» (на данный момент; 18 апреля 2024 г.). Вы можете проверить это, запустив tzutil /g в терминале. Если вы проверите XML-файл, ссылку на который я дал выше, первое сопоставление будет... «Европа/Париж». «Европа/Копенгаген» также указано внизу. Эти два часовых пояса следуют одним и тем же правилам AFAIK, поэтому отображение «ОК» (правильно с точки зрения смещения UTC), но не идеально.
Что касается того, почему вы получаете разные результаты; Я думаю, вы предоставили объяснение в разделе «печать os.environ в обоих случаях. Вы можете видеть, что среда winpty python определяет переменную среды «TZ»: «Европа/Копенгаген»». tzlocalищет переменную среды TZ. Если для него установлен идентификатор базы данных IANA, он вернет его, поскольку на самом деле это более надежно, чем описанное выше сопоставление Windows tz.
Отлично, огромное спасибо за этот ответ, действительно здорово знать предысторию таких проблем, с которыми я не сталкиваюсь ежедневно, но в любом случае меня удивляют...
Кстати, о: «нет соглашения между IANA и MS» — я нашел stackoverflow.com/q/74970414 «Не существует стандартного способа сделать это до C++20, и даже тогда реализована только последняя версия MSVC на сегодняшний день (gcc приближается). В C++20 есть тип std::chrono::time_zone, который имеет функцию-член name(), которая возвращает строку, например "America/Los_Angeles"." - Я попробовал скомпилировать программу с помощью MSVC и получил «Европу/Копенгаген», так что, возможно, есть надежда на взаимодействие IANA и MS.
@sdbbs Мой опыт работы с C++ очень ограничен, но на первый взгляд кажется, что хроно поставляется с базой данных IANA. Это обычное дело для библиотек часовых поясов: быть независимыми от платформы и контролировать версию базы данных. Крейт Chronic-tz в Rust делает то же самое, а также пакет времени в Go. Проблемы всегда начинаются тогда, когда вы хотите получить текущее состояние системы, т. е. когда вам нужно вызвать какой-то API ОС.
См. также: github.com/orgs/pyinstaller/discussions/8414