Функция mktime вернет -1, если структура не может быть представлена как значение типа time_t.
Для вывода программой date "дружественных" (в противоположность машинному) времени и даты можно воспользоваться функциями asctime и ctime:
#include <time.h>
char *asctime(const struct tm *timeptr);
char *ctime(const time_t *timeval);
Функция asctime возвращает строку, представляющую время и дату, заданные tm-структурой timeptr. У возвращаемой строки формат, подобный приведенному далее:
Sun Jun 9 12:34:56 2007\n\0
У нее всегда фиксированный формат длиной 26 символов. Функция ctime эквивалентна следующему вызову:
asctime(localtime(timeval))
Она принимает необработанное машинное значение времени и преобразует его в местное время.
А теперь выполните упражнение 4.8.
Упражнение 4.8. Функция ctime
В этом примере благодаря приведенному далее программному коду вы увидите функцию ctime в действии.
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
time_t timeval;
(void)time(&timeval);
printf ("The date is: %s", ctime(&timeval));
exit(0);
}
Откомпилируйте и затем запустите на выполнение ctime.c, и вы увидите нечто похожее на приведенные далее строки:
$ ./ctime
The date is: Sat Jun 9 08:02:08 2007.
Как это работает
Программа ctime.c вызывает функцию time для получения машинного значения времени и дает возможность функции ctime выполнить всю тяжелую работу по преобразованию этого значения в удобочитаемую строку, которую потом и выводит на экран.
Для лучшего управления точным форматированием времени и даты ОС Linux и современные UNIX-подобные системы предоставляют функцию strftime. Она довольно похожа на функцию sprintf для дат и времени и действует аналогичным образом:
#include <time.h>
size_t strftime(char *s, size_t maxsize, const char *format, struct tm *timeptr);
Функция strftime форматирует время и дату, представленные в структуре tm, на которую указывает параметр, timeptr, и помещает результат в строку s. Эта строка задается длиной maxsize (как минимум) символов. Строка format применяется для управления символами, записываемыми в строку. Как и в функции printf, она содержит обычные символы, которые будут переданы в строку, и спецификаторы преобразований для форматирования элементов времени и даты. В табл. 4.3 перечислены используемые спецификаторы преобразований.
Таблица 4.3
| Спецификатор преобразования | Описание |
|---|---|
| %a | Сокращенное название дня недели |
| %А | Полное название дня недели |
| %b | Сокращенное название месяца |
| %B | Полное название месяца |
| %c | Дата и время |
| %d | День месяца, 01–31 |
| %H | Час, 00–23 |
| %I | Час по 12-часовой шкале, 01–12 |
| %j | День в году, 001–366 |
| %m | Номер месяца в году, 01–12 |
| %M | Минуты, 00–59 |
| %p | a.m. (до полудня) или p.m. (после полудня) |
| %S | Секунды, 00–59 |
| %u | Номер дня недели, 1–7 (1 соответствует понедельнику) |
| %U | Номер недели в году, 01–53 (воскресенье - первый день недели) |
| %V | Номер недели в году, 01–53 (понедельник - первый день недели) |
| %w | Номер дня недели, 0–6 (0 соответствует воскресенью) |
| %x | Дата в региональном формате |
| %X | Время в региональном формате |
| %y | Номер года, меньший 1900 |
| %Y | Год |
| %Z | Название часового пояса |
| %% | Символ % |
Таким образом, обычная дата, такая же, как полученная из программы date, соответствует следующей строке формата функции strftime:
"%a %b %d %Н: %М: %S %Y"
Для облегчения чтения дат можно использовать функцию strptime, принимающую строку с датой и временем и формирующую структуру tm с теми же датой и временем:
#include <time.h>
char *strptime(const char *buf, const char *format, struct tm *timeptr);
Строка format конструируется точно так же, как одноименная строка функции strftime. Функций strptime действует аналогично функции sscanf: она сканирует строку в поиске опознаваемых полей и записывает их в переменные. В данном случае это элементы структуры tm, которая заполняется в соответствии со строкой format. Однако спецификаторы преобразований для strptime немного мягче спецификаторов функции strftime. Так, в функции strptime разрешены как сокращенные, так и полные названия дней и месяцев. Любое из этих представлений будет соответствовать спецификатору %a функции strptime. Кроме того, в то время как функция strftime для представления чисел, меньших 10, всегда применяет ведущие нули, strptime считает их необязательными.
Функция strptime возвращает указатель на символ, следующий за последним, обработанным в процессе преобразования. Если она встречает символы, которые не могут быть преобразованы, в этой точке преобразование просто прекращается. Для того чтобы убедиться в том, что в структуру tm записаны значимые данные, вызывающей программе следует проверять, достаточно ли символов строки принято и обработано.
Рассмотрим работу функций на примере (упражнение 4.9).