Проблема с gmtime, localtime и их вариантами заключается в зависимости от переменной окружения TZ. Функции времени сначала вызывают tzset (void), который читает TZ, чтобы определить смещения DST и т. Д. Если TZ не установлен в среде пользователя, (g) libc использует системный часовой пояс. Поэтому, если у вас есть локальная структура, скажем, «Европа / Париж», а ваша машина или окружение настроены на «Америка / Денвер», при преобразовании в GMT будет применено неправильное смещение. Все функции времени вызывают tzset (void), который читает TZ, чтобы установить char * tzname [2], длинный часовой пояс (разность в секундах, от GMT) и int daylight (логическое значение для DST). Установка их напрямую не влияет, потому что tzset () перезапишет их при следующем вызове по местному времени и т. Д.
Я столкнулся с той же проблемой, что и 'igor' в первоначальном вопросе, в то время как работа setenv кажется проблематичной (re-entran?). Я решил посмотреть дальше, чтобы посмотреть, смогу ли я изменить tzset (void) на tzset (char *), чтобы явно установить вышеупомянутые переменные. Ну, конечно, это просто плохая идея ... но при исследовании источника glibc и источника данных базы данных IANA TZ я пришел к выводу, что подход setenv не так уж и плох.
Во-первых, setenv изменяет только глобальную переменную процесса «char ** environment» (не вызывающую оболочку, поэтому «настоящая» TZ не затрагивается). И, во-вторых, glibc фактически блокирует setenv. Недостаток заключается в том, что вызовы setenv / tzset не являются атомарными, поэтому другой поток мог записать в TZ перед вызовом исходного потока tzset. Но хорошо реализованное приложение, использующее потоки, должно следить за этим в любом случае.
Было бы здорово, если бы POSIX определил tzset, чтобы взять символ * для поиска в обширной базе данных IANA TZ (и принять NULL в значении 'использовать пользовательский или системный TZ /), но если это не удастся, setenv кажется Хорошо.