Intereting Posts
C / C ++ post-increment / -decrement и вызов функции Соглашение об именах в Objective C / C начинается с «_»? читать из форматированного тестового файла с помощью fscanf () в c Должны ли определения структур идти в .h или .c файл? Как определить, когда звук закончил воспроизведение при использовании PlaySound в Win32 SDK? У меня возникают проблемы с получением средних значений при прохождении по адресу в C использовать функцию обратного вызова для отчета о возврате стека как получить разные цифры, начиная с самой значащей цифры в числе в c? Программирование на C: чтение (двойное) чисел из текстового файла, строка за строкой в ​​2D-массив Почему у Win32-API столько пользовательских типов? неосуществимая модификация и доступ к указателю Объем макросов в C? Каково значение этих #defines? Создание BMP-файла (растрового изображения) в C Определите, является ли функция безопасной с использованием асинхронного сигнала (может быть вызвана внутри обработчика сигнала)

Получить часовой пояс GMT в C

Я использую стандартную функцию mktime чтобы превратить struct tm в значение времени в эпоху. Поля tm заполняются локально, и мне нужно получить эпоху в качестве GMT. tm имеет поле gmtoff позволяющее вам установить локальное смещение GMT ​​в секундах только для этой цели.

Но я не могу понять, как получить эту информацию. Разумеется, где-то должна быть стандартная функция, которая вернет смещение? Как это делает localtime время?

Просто выполните следующие действия:

 #define _GNU_SOURCE /* for tm_gmtoff and tm_zone */ #include  #include  /* Checking errors returned by system calls was omitted for the sake of readability. */ int main(void) { time_t t = time(NULL); struct tm lt = {0}; localtime_r(&t, &lt); printf("Offset to GMT is %lds.\n", lt.tm_gmtoff); printf("The time zone is '%s'.\n", lt.tm_zone); return 0; } 

Примечание: секунды, прошедшие с момента возврата time() , измеряются как в Гринвиче.

Думаю, я должен был немного поработать, прежде чем спрашивать. Оказывается, есть небольшая известная функция timegm которая делает противоположное gmtime . Он поддерживается на GNU и BSD, который достаточно хорош для моих целей. Более портативное решение – временно установить значение переменной окружения TZ в «UTC», а затем использовать mktime , а затем установить TZ обратно.

Но timegm работает для меня.

Как это делает местное время?

Согласно localtime страницам

Функция localtime () действует так, как если бы она называлась tzset (3), и устанавливает внешние переменные tzname с информацией о текущем часовом поясе, часовой пояс с разницей между скоординированным универсальным временем (UTC) и локальным стандартным временем в секундах

Таким образом, вы можете вызвать localtime() и вы будете иметь разницу во timezone или вызовите tzset() :

 extern long timezone; .... tzset(); printf("%ld\n", timezone); 

Примечание: если вы решите пойти с localtime_r() обратите внимание, что вам не нужно устанавливать эти переменные, вам нужно будет сначала вызвать tzset() чтобы установить timezone :

Согласно POSIX.1-2004, localtime () требуется вести себя так, как если бы вызывался tzset (), тогда как localtime_r () не имеет этого требования. Для переносного кода tzset () следует вызывать перед localtime_r ()

Здесь приведена универсальная версия получения локальной функции смещения по времени.
Я заимствовал fragmentы кода из ответа в statckoverflow.

 int time_offset() { time_t gmt, rawtime = time(NULL); struct tm *ptm; #if !defined(WIN32) struct tm gbuf; ptm = gmtime_r(&rawtime, &gbuf); #else ptm = gmtime(&rawtime); #endif // Request that mktime() looksup dst in timezone database ptm->tm_isdst = -1; gmt = mktime(ptm); return (int)difftime(rawtime, gmt); } 

Я полагаю, что в linux по крайней мере верно: информация о часовом поясе поступает из / usr / share / zoneinfo /. localtime читает / etc / localtime, который должен быть копией соответствующего файла из зоныinfo. Вы можете видеть, что внутри, делая zdump -v в файле часового пояса (zdump может быть в sbin, но вам не нужны повышенные разрешения для чтения файлов часового пояса с ним). Вот один из них:

 / usr / share / zoneinfo / EST5EDT Вс Ноя 6 05:59:59 2033 UTC = Вс Ноя 6 01:59:59 2033 EDT isdst = 1 gmtoff = -14400
 / usr / share / zoneinfo / EST5EDT Вс Ноя 6 06:00:00 2033 UTC = Вс Ноя 6 01:00:00 2033 EST isdst = 0 gmtoff = -18000
 / usr / share / zoneinfo / EST5EDT Вс 12 мар 06:59:59 2034 UTC = Вс 12 мар 01:59:59 2034 EST isdst = 0 gmtoff = -18000
 / usr / share / zoneinfo / EST5EDT Вс Мар 12 07:00:00 2034 UTC = Вс 12 марта 03:00:00 2034 EDT isdst = 1 gmtoff = -14400
 / usr / share / zoneinfo / EST5EDT Вс Ноя 5 05:59:59 2034 UTC = Вс Ноя 5 01:59:59 2034 EDT 

Думаю, вы могли бы разобрать это сами, если хотите. Я не уверен, есть ли функция stdlib, которая возвращает gmtoff (может быть, но я не знаю …)

edit: man tzfile описывает формат файла zoneinfo. Вы должны иметь возможность просто mmap в структуру соответствующего типа. Кажется, это то, что делает zdump на основе его.