16 /* Проверка ошибок значений для краткости опущена. */
17 tm.tm_year -= 1900;
18 tm.tm_mon--;
19
20 tm.tm_isdst = -1; /* He знаю о летнем времени */
21
22 then = mktime(&tm);
23
24 printf("Got: %s", ctime(&then));
25 exit(0);
26 }
В строке 11 запрашиваются дата и время, а в строках 12–14 соответствующие значения считываются. (В коде изделия возвращаемые
scanf
значения должны
проверяться.) Строки 17 и 18 компенсируют различную базу для лет и месяцев соответственно. Строка 20 указывает, что мы не знаем, представляют ли данные дата и время летнее время. Строка 22 вызывает
mktime
, а строка 24 выводит результат преобразования. После компилирования и запуска мы видим, что это работает:
$ ch06-echodate
Enter a Date/time as YYYY/MM/DD HH:MM:SS : 2003/5/25 19:07:23
Got: Sun May 25 19:07:23 2003
6.1.5. Получение сведений о часовом поясе
На ранних системах Unix сведения о часовом поясе внедрялись в ядро при компиляции. Правила перехода на летнее время обычно были жестко вшиты в код, что создавало трудности для пользователей вне Соединенных Штатов или в местах внутри Соединенных Штатов, в которых не осуществлялся переход на летнее время.
В современных системах эти сведения выделены в двоичные файлы, которые читаются библиотекой С при извлечении функций, связанных со временем. Эта методика позволяет избежать необходимости в перекомпилировании библиотек и системных файлов при изменении правил и гораздо упрощает обновление правил.
Интерфейс языка С для сведений о часовых поясах развивался в разных версиях Unix, как на System V, так и Berkley, пока, наконец, не был стандартизован POSIX следующим образом.
#include <time.h> /* POSIX */
extern char *tzname[2];
extern long timezone;
extern int daylight;
void tzset(void);
Функция
tzset
проверяет переменную окружения
TZ
для получения сведений о часовом поясе и переходе на летнее время. [65] Если эта переменная не установлена,
tzset
использует «определенный в реализации часовой пояс по умолчанию», который скорее всего является часовым поясом машины, на которой вы работаете.
65
Хотя POSIX стандартизует формат TZ, он не представляет интереса, поэтому мы не стали возиться здесь с его документированием. В конце концов, именно
tzset
должна понимать формат, а не код пользователя. Реализации могут использовать и используют форматы, которые расширяют POSIX — Примеч. автора.
После вызова
tzset
сведения о локальном часовом поясе доступны в нескольких переменных:
extern char *tzname[2]
Стандартное имя и имя летнего времени для часового пояса. Например, для областей США в восточном часовом поясе именами часового пояса являются 'EST' (Eastern Standard Time) и 'EDT' (Eastern Daylight Time).
extern long timezone
Разница в секундах между текущим часовым поясом и UTC. Стандарт не определяет, как эта разница работает. На практике отрицательные значения представляют часовые пояса восточнее (перед, или те, которые позже) UTC; положительные значения представляют часовые пояса западнее (за, или те, которые раньше) UTC. Если вы посмотрите на это значение как «насколько изменить местное время, чтобы оно стало равно UTC», тогда знак этого значения имеет смысл.
extern int daylight
Эта переменная равна нулю, если правила перехода на летнее время никогда не должны использоваться для данного часового пояса, и не равны нулю в противном случае.
ЗАМЕЧАНИЕ. Переменная
daylight
не означает, действует ли в настоящий момент летнее время! Вместо этого она просто констатирует, может ли текущий часовой пояс вообще иметь летнее время.
Стандарт POSIX указывает, что
ctime
,
localtime
,
mktime
и
strftime
действуют, «как если бы» они вызывали
tzset
.
Это означает, что им в действительности не нужно вызывать
tzset
, но они должны вести себя, как если бы эта функция была вызвана. (Формулировка призвана дать определенную гибкость при реализации, в то же время гарантируя правильное поведение кода уровня пользователя.)
На практике это означает, что вы сами почти никогда не будете вызывать
tzset
. Но если понадобится, эта функция есть.
6.1.5.1. Системы BSD:
timezone
, не
timezone
Некоторые производные от BSD 4.4 системы вместо переменной POSIX
timezone
предоставляют функцию
timezone
:
#include <time.h> /* BSD */
char *timezone(int zone, int dst);
Аргумент
zone
является числом минут западнее GMT, a
dst
истинно, если действует летнее время. Возвращаемое значение является строкой, дающей имя указанного часового пояса, или значение, выраженное относительно GMT. Эта функция обеспечивает совместимость с функцией V7 с тем же именем и поведением.
Локальное время: откуда оно известно?
Системы GNU/Linux хранят информацию о часовых поясах в файлах и каталогах в
/usr/share/zoneinfo
:
$ cd /usr/share/zoneinfo
$ ls -FC
Africa/ Canada/ Factory Iceland MST7MDT Portugal W-SU
America/ Chile/ GB Indian/ Mexico/ ROC WET
Antarctica/ Cuba GB-Eire Iran Mideast/ ROK Zulu
Arctic/ EET GMT Israel NZ Singapore iso3166.tab
Asia/ EST GMT+0 Jamaica NZ-CHAT SystemV/ posix/
Atlantic/ EST5EDT GMT-0 Japan Navajo Turkey posixrules
Australia/ Egypt GMT0 Kwajalein PRC UCT right/
Brazil/ Eire Greenwich Libya PST8PDT US/ zone.tab
CET Etc/ HST MET Pacific/ UTC
CST6CDT Europe/ Hongkong MST Poland Universal
Когда возможно, этот каталог использует прямые ссылки для предоставления одних и тех же данных с разными именами. Например, файлы
EST5EDT
и
US/Eastern
на самом деле одни и те же:
$ ls -il EST5EDT US/Eastern
724350 -rw-r--r-- 5 root root 1267 Sep б 2002 EST5EDT
Частью установки системы является выбор часового пояса. Надлежащий файл данных часового пояса помещается затем в
/etc/localtime
:
$ file /etc/localtime
/etc/localtime: timezone data
На нашей системе это автономная копия файла для нашего часового пояса. На других системах это может быть символическая ссылка на файл в
/usr/share/zoneinfo
. Преимуществом использования отдельной копии является то, что все по-прежнему работает, если
/usr
не смонтирован.
Переменная окружения
TZ
, если она установлена, перекрывает значение по умолчанию для часового пояса:
$ date /* Дата и время в часовом поясе по умолчанию
*/
Wed Nov 19 06:44:50 EST 2003
$ export TZ=PST8PDT /* Смена часового пояса на Западное
побережье США */
$ date /* Вывести дату и время */
Wed Nov 19 03:45:09 PST 2003
Широкое распространение этой функции делает переносимое использование переменной POSIX
timezone
трудной. К счастью, мы не видим большой потребности в ней
strftime
должно быть достаточно едва ли не для большинства необычных потребностей
6.2. Функции сортировки и поиска
Сортировка и поиск являются двумя фундаментальными операциями, потребность в которых постоянно возникает во многих приложениях Библиотека С предоставляет ряд стандартных интерфейсов для осуществления этих задач.