Книга: Linux программирование в примерах
6.1.3.2. Сложное форматирование времени: strftime()
6.1.3.2. Сложное форматирование времени: strftime()
Хотя часто достаточно использования asctime()
и ctime()
, у них есть также и ограничения:
• Формат вывода фиксирован. Нет способа изменить порядок элементов.
• В вывод не включаются сведения о часовом поясе.
• В выводе используются сокращенные названия месяца и дня.
• В выводе используются английские названия месяцев и дней.
По этим причинам C89 ввело стандартную библиотечную процедуру strftime()
:
#include <time.h> /* ISO С */
сходна с
size_t strftime(char *s, size_t max, const char *format,
const struct tm *tm);
strftime()sprintf()
. Ее аргументы следующие:
char *s
Буфер для форматированной строки.
size_t max
Размер буфера.
const char *format
Форматирующая строка.
const struct tm *tm
Указатель на struct tm
, представляющий разложенное время, которое надо отформатировать.
Форматирующая строка содержит символы букв, смешанные о описателями преобразования, указывающими, что должно быть помещено в строку, такими, как полное имя дня недели, час в соответствии с 24-часовым или 12-часовым циклом, наличие указателей am или p.m[64], и т.д. (Вскоре будут приведены примеры.)
Если всю строку можно отформатировать с использованием не более max
символов, возвращаемое значение представляет собой число символов, помещенных в s, не включая завершающий нулевой байт. В противном случае, возвращаемое значение ноль. В последнем случае содержание s «неопределенно». Следующий простой пример дает представление об использовании strftime()
:
#include <stdio.h>
#include <time.h>
int main(void) {
char buf[100];
time_t now;
struct tm *curtime;
time(&now);
curtime = localtime(&now);
(void)strftime(buf, sizeof buf,
"It is now %A, %B %d, %Y, %I:%M %p", curtime);
printf("%sn", buf);
exit(0);
}
После запуска эта программа выводит что-то типа:
It is now Thursday, May 22, 2003, 04:15 PM
В табл. 6.2 предоставлен полный список описателей преобразования, их возможные альтернативные представления и их значения. Вдобавок стандарт C99 добавил к списку дополнительные описатели; новые для C99 описатели помечены символом ?.
Таблица 6.2. Описатели преобразования формата strftime()
Описатель | C99 | Значение |
---|---|---|
%a |
Локальное сокращенное название дня недели. | |
%A |
Локальное полное название дня недели. | |
%b |
Локальное сокращенное название месяца. | |
%B |
Локальное полное название месяца. | |
%c, %Ec |
Локальное «подходящее» представление даты и времени | |
%C, %EC |
? | Век (00–99) |
%d, %Od |
День месяца (01–31) | |
%D |
? | То же, что %m/%d/%y |
%e, %Oe |
? | День месяца. Одна цифра дополняется пробелом (1–31). |
%F |
? | То же, что и %Y-%m-%d (формат даты ISO 8601) |
%g |
? | Две последние цифры, основанной на неделе года (00–99). |
%G |
? | Основанный на неделе год ISO 8601 |
%h |
? | То же, что и %b |
%H, %OH |
Час в 24-часовом цикле (00–23) | |
%I, %OI |
Час в 12-часовом цикле (01–12) | |
%j |
День года (001–366) | |
%m, %Om |
Месяц в виде числа (01–12). | |
%M, %OM |
Минута в виде числа (00–59) | |
%n |
? | Символ конца строки ('n') |
%p |
Локальное обозначение a.m./p.m. | |
%r |
? | Локальное время в 12-часовом цикле |
%R |
? | Тоже, что и %H:%M |
%S, %OS |
Секунда в виде числа (00–60) | |
%t |
? | Символ табуляции ('t ') |
%T |
? | То же, что и %H:%M:%S (формат ISO 8601). |
%u, %Ou |
? | Число дня недели ISO 8601, понедельник = 1 (1–7). |
%U, %OU |
Номер недели, первое воскресенье является первым днем недели 1 (00–53) | |
%V, %OV |
? | Номер недели ISO 8601 (01–53) |
%w, %Ow |
День недели как число, воскресенье = 0 (0–6). | |
%W, %OW |
Номер недели, первый понедельник является первым днем недели 1 (00–53) | |
%x, %Ex |
Локальное «подходящее» представление даты | |
%X, %EX |
Локальное «подходящее» представление времени. | |
%y, %Ey, %Oy |
Две последние цифры года (00–99) | |
%Y, %EY |
Год как число. | |
%Z |
Локальный часовой пояс или отсутствие символов, если сведения о часовом поясе недоступны | |
%% |
Простой % |
Локаль (locale) является способом описания местной специфики, принимая во внимание такие вещи, как язык, кодировка символов и значения по умолчанию для форматирования дат, времени, денежных сумм и т.д. Мы будем иметь с ними дело в главе 13 «Интернационализация и локализация». Пока достаточно понять, что результаты strftime()
для одной и той же форматирующей строки могут быть разными в зависимости от настроек текущей локали.
Версии, начинающиеся с %E
и %O
, предназначены для «альтернативного представления». В некоторых локалях есть несколько способов представления одних и тех же сведений; эти описатели предоставляют доступ к дополнительным представлениям. Если определенная локаль не поддерживает альтернативного представления, strftime()
использует обычную версию.
Многие Unix-версии date
дают возможность предоставить в командной строке форматирующую строку, начинающуюся с символа '+
'. Затем date
форматирует текущие дату и время и выводит в соответствии с форматирующей строкой:
$ date + 'It is now %A, %B %d, %Y, %I:%M %p'
It is now Sunday, May 25, 2003, 06:44 PM
Большинство новых описателей 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> */
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.3. Форматирование даты и времени
- Уменьшение времени, необходимого для резервного копирования и восстановления
- Ограничение времени ожидания для транзакций (Lock timeout)
- 7.12. Объективизация времени
- Квант времени
- Формула времени. Тайм-менеджмент на Outlook 2013
- Как в документ Microsoft Word вставить текст, в котором отсутствует форматирование?
- Трюки с форматированием
- 12.6. Сигналы реального времени
- Время от времени оптическая мышь начинает мигать. Она сломалась?
- 2.9. Форматирование строк
- Чем отличается быстрое форматирование от обычного?