if (setlocale(LC_ALL, "") == NULL)
errExit("setlocale"); /* Использование настроек локали при преобразовании */
memset(&tm, 0, sizeof(struct tm)); /* Инициализация 'tm' */
if (strptime(argv[1], argv[2], &tm) == NULL)
fatal("strptime");
tm.tm_isdst = -1; /* Не устанавливается функцией strptime(); заставляет функцию
mktime() определить действие режима летнего времени */
printf("calendar time (seconds since Epoch): %ld\n", (long) mktime(&tm));
ofmt = (argc > 3)? argv[3]: "%H:%M:%S %A, %d %B %Y %Z";
if (strftime(sbuf, SBUF_SIZE, ofmt, &tm) == 0)
fatal("strftime returned 0");
printf("strftime() yields: %s\n", sbuf);
exit(EXIT_SUCCESS);
}
time/strtime.c
Разные страны (а иногда даже и разные регионы одной страны) находятся в разных часовых поясах и режимах действия летнего времени. Программы, где используется ввод и вывод времени, должны учитывать часовой пояс и режим действия летнего времени той системы, в которой они запускаются. К счастью, все эти особенности обрабатываются средствами библиотеки языка C.
Информация о часовом поясе характеризуется, как правило, обширностью и нестабильностью. Поэтому, вместо того, чтобы вносить ее в код программ или библиотек напрямую, система хранит эту информацию в файлах в стандартных форматах.
Эти файлы находятся в каталоге /usr/share/zoneinfo. Каждый файл в нем содержит информацию о часовом поясе конкретной страны или региона. Файлы названы в соответствии с тем часовым поясом, описание которого в них дается, поэтому там можно найти файлы с такими именами, как EST (US Eastern Standard Time — североамериканское восточное время), CET (Central European Time — центральноевропейское время), UTC, Turkey и Iran. Кроме того, для создания иерархии групп, связанных с часовыми поясами, могут использоваться подкаталоги. Например, в каталоге Pacific можно найти файлы Auckland, Port_Moresby и Galapagos. Когда мы указываем программе, какой именно часовой пояс использовать, на самом деле указывается относительное путевое имя для одного из файлов часового пояса в этом каталоге.
Местное время для системы определяется файлом часового пояса /etc/localtime, который часто ссылается на один из файлов в каталоге /usr/share/zoneinfo.
Формат файлов часовых поясов задокументирован на странице руководства tzfile(5). Файлы часовых поясов создаются с помощью zic(8), компилятора информации о часовых поясах. С помощью команды zdump можно вывести текущее время для указанных файлов часовых поясов.
Чтобы указать часовой пояс при выполнении программы, переменной среды TZ присваивается значение в виде строки, содержащей символ двоеточия (:), за которым следует одно из названий часовых поясов, определенное в /usr/share/zoneinfo. Установка часового пояса автоматически влияет на функции ctime(), localtime(), mktime() и strftime().
Для получения текущей установки часового пояса в каждой из этих функций применяется функция tzset(3), которая инициализирует три глобальные переменные:
char *tzname[2]; /* Название часового пояса и альтернативного часового пояса
с учетом действия режима летнего времени */
int daylight; /* Ненулевое значение при наличии альтернативного
часового пояса с учетом действия режима летнего времени */
long timezone; /* Разница в секундах между UTC и местным [поясным] временем */
Функция tzset() сначала проверяет значение переменной среды TZ. Если значение для нее не установлено, часовой пояс инициализируется значением по умолчанию, определенным в файле часового пояса /etc/localtime. Если переменная TZ определена и имеет значение, которое не может соответствовать файлу часового пояса, или если оно представляет собой пустую строку, тогда используется UTC. Для переменной среды TZDIR (нестандартное GNU-расширение) может быть установлено имя каталога, в котором требуется вести поиск информации о часовом поясе вместо исходного каталога /usr/share/zoneinfo.
Эффект использования переменной TZ можно увидеть, запустив на выполнение программу, показанную в листинге 10.4. При первом запуске будет виден вывод, соответствующий исходному часовому поясу системы (центральноевропейского времени, CET). При втором запуске будет указан часовой пояс для Новой Зеландии, где в заданное время года действует режим летнего времени и местное время опережает CET на 12 часов.
$ ./show_time
ctime() of time() value is: Tue Feb 1 10:25:56 2011
asctime() of local time is: Tue Feb 1 10:25:56 2011
strftime() of local time is: Tuesday, 01 Feb 2011, 10:25:56 CET
$ TZ=":Pacific/Auckland"./show_time
ctime() of time() value is: Tue Feb 1 22:26:19 2011
asctime() of local time is: Tue Feb 1 22:26:19 2011
strftime() of local time is: Tuesday, 01 February 2011, 22:26:19 NZDT
Листинг 10.4. Демонстрация эффекта часовых поясов и локалей
time/show_time.c
#include
#include
#include "tlpi_hdr.h"