Как задокументировано, mktime()
принимает компоненты разбитого времени в местное время .
Сначала сохраните текущий часовой пояс пользователя:
char *old_timezone, *temp;
temp = getenv("TZ");
if (temp) {
const size_t len = temp;
old_timezone = malloc(len + 1);
if (!old_timezone) {
fprintf(stderr, "Out of memory!\n");
exit(EXIT_FAILURE);
}
if (len > 0)
memcpy(old_timezone, temp, len);
old_timezone[len] = '\0';
} else
old_timezone = NULL;
Если пользователь использует системное значение по умолчанию, old_timezone
будет НЕДЕЙСТВИТЕЛЕН.
Далее установите текущий часовой пояс (для этого процесса) в UTC:
setenv("TZ", "UTC", 1);
tzset();
Обратите внимание, что при желании вы можете использовать любой спецификатор часового пояса вместо "UTC"
выше; см. tzset()
для деталей. Вызов tzset()
обычно выполняется изнутри вашей C-библиотекой, но выполнение этого в явном виде помогает нам понять, что только что произошло что-то специфическое для часового пояса.
В этот момент mktime()
будет работать в UTC, а localtime()
и gmtime()
будут возвращать те же результаты.
Затем восстановите часовой пояс на
if (old_timezone) {
setenv("TZ", old_timezone, 1);
free(old_timezone);
old_timezone = NULL;
} else
unsetenv("TZ");
tzset();
Обратите внимание, что это не влияет ни на что, кроме текущего процесса (и любых дочерних процессов, которые вы можете создать с помощью popen()
или system()
или fork()
и exec()
). Часовой пояс, как и локаль, является свойством процесса.
Запуск
unsetenv("TZ");
tzset();
изменит текущий часовой пояс для этого процесса на системный часовой пояс по умолчанию.
Если ваша программа работает явно в формате UTC, вы можете сделать просто
/* This program works explicitly in the UTC timezone.
User/system timezone configuration is completely ignored. */
setenv("TZ", "UTC", 1");
tzset();
в начале вашего main()
.