Опрос и установка показаний часов реального времени
Простейшим средством опроса и/или изменения текущих даты и времени является служебная программа date:
date [-u] [+формат] date [-u] ммддччмм[[вв]гг]
В первой форме утилита date выдает на стандартный вывод дату и время (по умолчанию - текущие), в соответствии с заданным форматом. Во второй форме date позволяет установить системные дату и время.
При наличии опции -u работа ведется без учета часового пояса, во всемирном времени (как если бы значением переменной окружения TZ была цепочка "UTC0"). Без этой опции учитывается значение TZ или, если таковое не установлено или пусто, принимается во внимание системное подразумеваемое значение.
Если в командной строке date задан аргумент, начинающийся со знака +, форматом вывода даты и времени управляет пользователь. Формат включает спецификаторы преобразований и прочие символы (последние выводятся без изменений). Спецификаторы преобразований начинаются со знака % и замещаются при выводе соответствующим значением.
%a | Сокращенное название дня недели. |
%A | Полное название дня недели. |
%b |
Сокращенное название месяца. |
%B | Полное название месяца. |
%c | Принятое в данной языково-культурной среде представление даты и времени. |
%C | Две первые цифры четырехзначного номера года [00, 99]. |
%d | Номер дня в месяце [01, 31]. |
%D | Дата в формате мм/дд/гг. |
%e | Номер дня в месяце [1, 31] в двухсимвольном поле с дополнением, при необходимости, пробела. |
%h | То же, что %b. |
%H | Номер часа [00, 23]. |
%I | Номер часа [01, 12]. |
%j | Номер дня в году [001, 366]. |
%m | Номер месяца [01, 12]. |
%M |
Минуты [00, 59]. |
%n | Перевод строки |
%S |
Секунды [00, 60]. |
%t | Табуляция |
%T | Время в формате чч:мм:сс. |
%u | Номер дня недели [1, 7] (единица соответствует понедельнику). |
%U | Номер недели в году [00, 53]. Первым днем недели считается воскресенье. Все дни нового года, предшествующие первому воскресенью, относятся к нулевой неделе. |
%V | Номер недели в году [01, 53]. Первым днем недели считается понедельник. Если первое января приходится на пятницу, субботу или воскресенье, конец недели формально относят к прошлому году, а первой считают следующую неделю. |
%w | Номер дня недели [0, 6] (ноль соответствует воскресенью). |
%W | Номер недели в году [00, 53]. Первым днем недели считается понедельник. Все дни нового года, предшествующие первому понедельнику, относятся к нулевой неделе. |
%x | Принятое в данной языково-культурной среде представление даты. |
%X | Принятое в данной языково-культурной среде представление времени. |
%y | Две младшие цифры номера года [00, 99]. |
%Y | Четырехзначный номер года. |
%Z | Имя часового пояса. |
%% | Знак процента. |
Чтобы установить текущие дату и время, необходимо, чтобы система допускала данное действие, а у процесса были соответствующие привилегии.
Во второй форме вызова утилиты date первая пара букв м обозначает номер месяца, дд - номер дня в месяце, чч - часы, мм - минуты, ввгг - год. Если две первые цифры года опущены, то диапазон [69, 99] трактуется как [1969, 1999], а [00, 68] - как [2000, 2068]. Если год не указан, имеется в виду текущий.
Приведем несколько примеров употребления служебной программы date.
Вывод в подразумеваемом формате, используемом командой date без аргументов, может выглядеть так:
Fri Dec 26 17:48:02 MSK 2003
Опция -u повлияет на вывод следующим образом:
Fri Dec 26 14:48:05 UTC 2003
Команда
date '+Дата: %d.%m.%Y%nВремя: %H:%M:%S'
выдаст примерно следующее:
Дата: 26.12.2003 Время: 17:49:15
Для сдвига показаний системных часов на один час вперед можно воспользоваться shell-процедурой, показанной в листинге 12.1 (предполагается, что ее выполняют днем при наличии соответствующих привилегий).
moda=`date +%m%d` ho=$((`date +%H` + 1)) mi=`date +%M` date ${moda}${ho}${mi}
Листинг 12.1. Пример использования служебной программы date. (html, txt)
С функцией time() ассоциирована функция difftime(), вычисляющая ( в виде значения типа double) разность в секундах между двумя моментами времени (time1 - time0, см. листинг 12.3).
#include <time.h> double difftime (time_t time1, time_t time0);
Листинг 12.3. Описание функции difftime().
Узнать текущее время с большей точностью позволяет функция gettimeofday() (см. листинг 12.4).
#include <sys/time.h> int gettimeofday (struct timeval *restrict tp, void *restrict tzp);
Листинг 12.4. Описание функции gettimeofday().
Согласно стандарту POSIX-2001, описанная в заголовочном файле <sys/time.h> структура timeval содержит по крайней мере следующие поля.
time_t tv_sec; /* Секунды */ suseconds_t tv_usec; /* Микросекунды */
Функция gettimeofday() записывает текущее время, выраженное в секундах и микросекундах от начала отсчета, в структуру типа timeval, на которую указывает аргумент tp. Указатель tzp должен быть пустым.
Впрочем, микросекунды - это еще на предел точности, а опрос системных часов - не предел общности. В необязательную часть стандарта POSIX-2001, регламентирующую работу с таймерами, входят функции, позволяющие опросить и установить показания заданных часов, а также узнать их разрешающую способность (см. листинг 12.5).
#include <time.h> int clock_getres (clockid_t clock_id, struct timespec *res); int clock_gettime (clockid_t clock_id, struct timespec *tp); int clock_settime (clockid_t clock_id, const struct timespec *tp);
Листинг 12.5. Описание функций опроса характеристик и установки часов.
Структура timespec отличается от timeval тем, что вместо микросекунд хранит наносекунды:
time_t tv_sec; /* Секунды */ long tv_nsec; /* Наносекунды */
Функция clock_getres() позволяет опросить разрешающую способность часов с заданным идентификатором и поместить результат в структуру, на которую указывает аргумент res.
Функция clock_gettime() записывает в аналогичную структуру текущие показания заданных часов.
Наконец, функция clock_settime() устанавливает заданные часы на основании значений полей структуры типа timespec, на которую указывает аргумент tp.