Категории
Самые читаемые
PochitayKnigi » Компьютеры и Интернет » Программное обеспечение » Linux программирование в примерах - Арнольд Роббинс

Linux программирование в примерах - Арнольд Роббинс

Читать онлайн Linux программирование в примерах - Арнольд Роббинс

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 41 42 43 44 45 46 47 48 49 ... 165
Перейти на страницу:

Локаль (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.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 : ");

12  scanf("%d/%d/%d %d:%d:%d",

13   &tm.tm_year, &tm.tm_mon, &tm.tm_mday,

14   &tm.tm_hour, &tm.tm_min, &tm.tm_sec);

15

16  /* Проверка ошибок значений для краткости опущена. */

17  tm.tm_year -= 1900;

18  tm.tm_mon--;

19

20  tm.tm_isdst = -1; /* He знаю о летнем времени */

21

22  then = mktime(&tm);

23

24  printf("Got: %s", ctime(&then));

25  exit(0);

26 }

В строке 11 запрашиваются дата и время, а в строках 12–14 соответствующие значения считываются. (В коде изделия возвращаемые scanf() значения должны проверяться.) Строки 17 и 18 компенсируют различную базу для лет и месяцев соответственно. Строка 20 указывает, что мы не знаем, представляют ли данные дата и время летнее время. Строка 22 вызывает mktime(), а строка 24 выводит результат преобразования. После компилирования и запуска мы видим, что это работает:

$ ch06-echodate

Enter a Date/time as YYYY/MM/DD HH:MM:SS : 2003/5/25 19:07:23

Got: Sun May 25 19:07:23 2003

6.1.5. Получение сведений о часовом поясе

На ранних системах Unix сведения о часовом поясе внедрялись в ядро при компиляции. Правила перехода на летнее время обычно были жестко вшиты в код, что создавало трудности для пользователей вне Соединенных Штатов или в местах внутри Соединенных Штатов, в которых не осуществлялся переход на летнее время.

В современных системах эти сведения выделены в двоичные файлы, которые читаются библиотекой С при извлечении функций, связанных со временем. Эта методика позволяет избежать необходимости в перекомпилировании библиотек и системных файлов при изменении правил и гораздо упрощает обновление правил.

1 ... 41 42 43 44 45 46 47 48 49 ... 165
Перейти на страницу:
Тут вы можете бесплатно читать книгу Linux программирование в примерах - Арнольд Роббинс.
Комментарии