Большинство новых описателей C99 происходит от таких существующих реализаций
date
Unix. Описатели
%n
и
%t
не являются в С абсолютно необходимыми, поскольку символы табуляции и конца строки могут быть помещены в строку непосредственно. Однако в контексте форматирующей строки
date
для командной строки они имеют больше смысла. Поэтому они также включены в спецификацию
strftime
.
Стандарт ISO 8601 определяет (среди других вещей), как нумеруются недели
в пределах года. В соответствии с этим стандартом недели отсчитываются с понедельника по воскресенье, а понедельник является днем недели 1, а не 0. Если неделя, в которой оказывается 1 января, содержит по крайней мере четыре дня нового года, она считается неделей 1. В противном случае, это последняя неделя предыдущего года с номером 52 или 53. Эти правила используются для вычислений описателей форматов
%g
,
%G
и
%V
. (Хотя ограниченным американцам, таким, как автор, эти правила могут показаться странными, они обычно повсюду используются в Европе.)
Многие из описателей стандартов дают результаты, специфичные для текущей локали. Вдобавок некоторые указывают, что они выдают «подходящее» представление для локали (например,
%x
). Стандарт C99 определяет значения для локали «С». Эти значения перечислены в табл. 6.3
Таблица 6.3. Значения локали «С» для определенных форматов
strftime
Описатель
Значение
%а
Первые три символа
%А
.
%А
Один из дней Sunday, Monday, …, Saturday
%b
Первые три символа
%В
%В
Один из месяцев January, February, …, December
%с
То же, что и
%а %b %е %T %Y
%p
AM или PM
%r
То же, что и
%I:%M:%S %p
%x
То же, что и
%m/%d/%y
%X
То же, что и
%T
.
%Z
Определяется реализацией
Должно быть очевидно, что
strftime
предоставляет значительную гибкость и контроль над связанным с датой и временем выводом, во многом таким же образом, как
printf
и
sprintf
. Более того,
strftime
не может переполнить буфер, поскольку она проверяет входной параметр размера, что делает ее более безопасной процедурой, чем
sprintf
.
В качестве простого примера рассмотрим создание файлов журнала программы, когда каждый час создается новый файл. Имя файла должно включать дату и время создания:
/* Проверка ошибок для краткости опущена */
char fname[PATH_МАХ]; /* PATH_МАХ находится в <limits.h> */
год-месяц-день-час-минута вызывает сортировку файлов в том порядке, в каком они были созданы.
ЗАМЕЧАНИЕ. Некоторые форматы данных более полезны, чем другие. Например, 12-часовое время двусмысленно, также, как чисто числовые форматы дат. (Что означает '
9/11
'? Это зависит от того, где вы живете) Сходным образом, годы из двух цифр также являются плохой мыслью. Используйте
strftime
благоразумно
6.1.4. Преобразование разложенного времени в
time_t
Получение от системы значений «секунд с начала Эпохи» просто; именно так даты и времена хранятся в индексах и возвращаются с помощью
time
и
stat
. Эти значения также легко оценивать на равенство или посредством < и > для простых тестов раньше/позже.
Однако, с датами, введенными людьми, не так легко работать. Например, многие версии команды
touch
позволяют предусмотреть дату и время, в которое
touch
должна установить время модификации или доступа к файлу (с помощью
utime
, как было описано в разделе 5.5.3 «Изменение отметок времени:
utime
»).
Преобразование даты, введенной человеком, в значение
time_t
трудно: надо принять во внимание високосные годы, учесть часовые пояса и т.д. Поэтому стандарт C89 ввел функцию
mktime
:
#include <time.h> /* ISO С */
time_t mktime(struct tm *tm);
Для использования
mktime
укажите в
struct tm
соответствующие значения — год, месяц, день и т.д. Если вы знаете, действовало ли для данной даты летнее время, установите соответствующим образом поле
tm_isdst
: 0 для «нет» и положительное значение для «да». В противном случае, используйте отрицательное значение для «не знаю». Поля
tm_wday
и
tm_yday
игнорируются.
mktime
предполагает, что
struct tm
представляет локальное время, не UTC. Она возвращает значение
time_t
, представляющее переданные дату и время, или
(time_t)(-1)
, если данные дата/время не могут быть правильно представлены. После успешного возвращения все значения
struct tm
выверены на попадание в правильные диапазоны, a
tm_wday
и
tm_yday
также корректно установлены. Вот простой пример:
1 /* ch06-echodate.c --- демонстрирует mktime. */
2
3 #include <stdio.h>
4 #include <time.h>
5
6 int main(void)
7 {
8 struct tm tm;
9 time_t then;
10
11 printf("Enter a Date/time as YYYY/MM/DD HH:MM:SS : ");