Стандарт 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_МАХ находится в
time_t now;
struct tm *tm;
int fd;
time(&now);
tm = localtime(&now);
strftime(fname, sizeof fname, "/var/log/myapp.%Y-%m-%d-%H:%M", tm);
fd = creat(name, 0600);
...
Формат год-месяц-день-час-минута вызывает сортировку файлов в том порядке, в каком они были созданы.
ЗАМЕЧАНИЕ. Некоторые форматы данных более полезны, чем другие. Например, 12-часовое время двусмысленно, также, как чисто числовые форматы дат. (Что означает '9/11
'? Это зависит от того, где вы живете) Сходным образом, годы из двух цифр также являются плохой мыслью. Используйте strftime()
благоразумно
6.1.4. Преобразование разложенного времени в time_t
Получение от системы значений «секунд с начала Эпохи» просто; именно так даты и времена хранятся в индексах и возвращаются с помощью time()
и stat()
. Эти значения также легко оценивать на равенство или посредством < и > для простых тестов раньше/позже.
Однако, с датами, введенными людьми, не так легко работать. Например, многие версии команды touch
позволяют предусмотреть дату и время, в которое touch
должна установить время модификации или доступа к файлу (с помощью utime()
, как было описано в разделе 5.5.3 «Изменение отметок времени: utime()
»).
Преобразование даты, введенной человеком, в значение time_t
трудно: надо принять во внимание високосные годы, учесть часовые пояса и т.д. Поэтому стандарт C89 ввел функцию mktime()
:
#include
time_t mktime(struct tm *tm);
Для использования mktime()
укажите в struct tm
соответствующие значения — год, месяц, день и т.д. Если вы знаете, действовало ли для данной даты летнее время, установите соответствующим образом поле tm_isdst
: 0 для «нет» и положительное значение для «да». В противном случае, используйте отрицательное значение для «не знаю». Поля tm_wday
и tm_yday
игнорируются.