ЭЛЕКТРОННАЯ БИБЛИОТЕКА КОАПП |
Сборники Художественной, Технической, Справочной, Английской, Нормативной, Исторической, и др. литературы. |
3.6. Определение номера недели или дня недели/месяца/годаПроблемаИмеется дата в секундах с начала эпохи или в виде отдельных компонентов - года, месяца и т. д. Требуется узнать, на какой номер недели или день недели/месяца/года она приходится.РешениеЕсли дата выражена в секундах с начала эпохи, день года, день месяца или недели возвращается функцией localtime. Номер недели легко рассчитывается по дню года.($MONTHDAY, $WEEKDAY, $YEARDAY) = (localtime $DATE) [3,6,7]; $WEEKNUM = int($YEARDAY / 7) + 1; Отдельные компоненты полного времени можно преобразовать в число секунд с начала эпохи (см. рецепт 3.3) и воспользоваться приведенным выше решением. Возможен и другой вариант - применение функций Day_of_Week, Week_Number и Day_of_Year модуля Date::Calc с CPAN: use Date::Calc qw(Day_of_Week Week_Number Day_of_Year); # Исходные величины - $year, $month и $day # По определению $day является днем месяца $wday = Day_of_Week($year, $month, $day);
КомментарийФункции Day_of_Week, Week ^..n'bo:'" и Day_of_Year получают год без вычитания 1900 и месяц в нумерации, начпиаюпк-йся с 1 (январь), а не с 0. Возвращаемое значение функции Day_of_Week находится в интервале 1-7 (с понедельника до воскресенья) или равняется 0 в случае ошибки (например, при неверно заданной дате).use Date::Calc qw(Day_of_Week Week_Number);
6/16/1981 was a Tuesday in the 25 week В некоторых странах существуют специальные стандарты, касающиеся первой недели года. Например, в Норвегии первая неделя должна содержать не менее 4 дней (и начинаться с понедельника). Если 1 января выпадает на неделю из 3 и менее дней, она считается 52 или 53 неделей предыдущего года. В Америке первая рабочая неделя обычно начинается с первого понедельника года. Возможно, при таких правилах вам придется написать собственный алгоритм или по крайней мере изучить форматы %G, %L, %W и %U функции UnixDate модуля Date::Manip. > Смотри также -------------------------------- Описание функции localtime в perlfunc(1); документация но стандартному модулю Date::Calc от CPAN. 3.7. Анализ даты и времени в строкахПроблемаСпецификация даты или времени читается в произвольном формате, однако ее требуется преобразовать в отдельные компоненты (год, месяц и т. д.).РешениеЕсли дата уже представлена в виде числа или имеет жесткий, легко анализируемый формат, воспользуйтесь регулярным выражением (и, возможно, хэшем, связывающим названия месяцев с номерами) для извлечения отдельных значений дня, месяца и года. Затем преобразуйте их в секунды с начала эпохи с помощью функций timelocal и timegm стандартного модуля Time::Local.use Time::Local:
Более гибкое решение - применение функции ParseDate из модуля Date::Manip
с CPAN и последующее извлечение отдельных компонентов с помощью UnixDate.
КомментарийУниверсальная функция ParseDate поддерживает различные форматы дат. Она даже преобразует такие строки, как "today" ("сегодня"), "2 weeks ago Friday" ("в пятницу две недели назад") и "2nd Sunday in 1996" ("2-е воскресенье 1996 года"), а также понимает форматы даты/времени в заголовках почты и новостей. Расшифрованная дата возвращается в собственном формате - строке вида "ГПТММДДЧЧ:ММ:СС". Сравнение двух строк позволяет узнать, совпадают ли представленные ими даты, однако арифметические операции выполняются иначе. Поэтому мы воспользовались функцией UnixDate для извлечения года, месяца и дня в нужном формате. Функция UnixDate получает дату в виде строки, возвращаемой ParseDate, и список форматов. Она последовательно применяет каждый формат к строке и возвращает результат. Формат представляет собой строку с описанием одного или нескольких элементов даты/времени и способов оформления этих элементов. Например, формат %Y соответствует году, состоящему из четырех цифр. Приведем пример:use Date::Manip qw(ParseDate UnixDate);
> Смотри также ------------------------------- Документация для модуля Date::Manip с CPAN; пример использования приведен в рецепте 3.11. 3.8. Вывод датыПроблемаТребуется преобразовать дату и время, выраженные в секундах с начала эпохи, в более понятную для человека форму.РешениеВызовите localtime или gmtime в скалярном контексте - в этом случае функция получает количество секунд с начала эпохи п возвращает строку вида Tue May 26 05:15:20 1998:$STRING = localtime($EPOCH_SECONDS);
use POSIX qw(strftime);
В модуле Date::Manip с CPAN есть функция UnixDate - нечто вроде специализированного варианта spnntf, предназначенного для работы с датами. Ей передается дата в формате Date::Manip. Применение Date::Manip вместо POSIX::strftim( имеет дополнительное преимущество, так как для этого от системы не требуется совместимость с POSIX. use Date::Manip qw(UnixDate);
КомментарийПростеишее решение - функция localtime - относится к встроенным средствам Perl. В скалярном контексте эта функция возвращает строку, отформатированную особым образом: Sun Sep 21 15:33:36 1999 Программа получается простои, хотя формат строки сильно ограничен:use Time::Local;
Разумеется, дата н время для localtime должны исчисляться в секундах с начала эпохи. Функция POSIX: :strftime получает набор компонентов полного времени н форматную строку, аналогичную orintf, н возвращает также строку. Поля в выходной строке задаются директивами %. Полный список директив приведен в документации но strftime для Bauicii системы. Функция strftime ожидает, что отдельные компоненты даты/времени принадлежат тем же интервалам, что н значения, возвращаемые localtime: use POSIX qw(strftime);
Разумеется, дата и время для localtime должны исчисляться в секундах с нача-;i;i :)IIOXH. Функция POSIX: : strftime получает набор компонентов полного времени и форматную строку, аналогичную pr -intf, н возвращает также строку. Поля в выходнон строке задаются директивами %. Полный список директив приведен в документации по strftime для вашей системы. Функция strftime ожидает, что отдельные компоненты даты/времени принадлежат тем же интервалам, что и значения, возвращаемые localtime: use POSIX qw(strftime);
При использовании POSIX: : strftime все значения выводятся в соответствии с национальными стандартами. Так, во Франции ваша программа вместо "Sunday" выведет "Dimanche". Однако учтите: интерфейс Perl к функции strftime модуля POSIX всегда преобразует дату в предположении, что она относится к текущему часовому поясу. Если функция strftime модуля POSIX недоступна, у вас всегда остается верный модуль Date::Manip, описанный в рецепте 3.6. use Date::Manip qw(ParseDate UnixDate);
[> Смотри также ------------------------------- Описание функции gmtime и localtime в perlfunc(1); perllocate(1); man-странице strfrime(3) вашей системы; документация по модулям POSIX и Date::Manip cCPAN. 3.9. Таймеры высокого разрешенияПроблемаФункция time возвращает время с точностью до секунды. Требуется измерить время с более высокой точностью.РешениеИногда эта проблема неразрешима. Если на вашем компьютере Perl поддерживает функцию syscall, а в системе имеется функция тина gettimeofday(2), вероятно, ими можно воспользоваться для измерения времени. Особенности вызов;! syscall зависят от конкретного компьютера. В комментарии приведен примерный вид фрагмента, однако его переносимость не гарантирована. На некоторых компьютерах эти функциональные возможности инкапсулируются в модуле Time::HiRes (распространяется с CPAN):use Time::HiRes qw(gettimeofday);
КомментарийВ следующем фрагменте модуль Time::HiRes используется для измерения промежутка между выдачей сообщения и нажатием клавиши RETURN:use Time::HiRes qw(gettimeofday);
Сравните с эквивалентным фрагментом, использующим syscall:
Press return when ready;
> Смотри также -------------------------------- Документация по модулям Time::HiRes и BenchMark с CPAN; описание функции syscall в perlfunc(1); man-страница syscall{2). 3.10. Короткие задержкиПроблемаТребуется сделать в программе паузу продолжительностью менее секунды.РешениеВоспользуйтесь функцией select, если она поддерживается вашей системой: select(undef, undet, undef, $time_to_sleep); где $time_to_sleep - длительность паузы. Некоторые системы не поддерживают select с четырьмя аргументами. В модуле Time::HiRes присутствует функция sleep, которая допускает длину паузы с плавающей точкой:use Time::HiRes qw(sleep);
КомментарийСледующий фрагмент демонстрирует применение функции select. Он представляет собой упрощенную версию программы из рецепта 1.5. Можете рассматривать его как эмулятор 300-бодного терминала:while (<>) {
С помощью Time::HiRes это делается так: use Time::HiRes qw(sleep);
> Смотри также Документация по модулям Time::HiRes и BenchMark с CPAN; описание функций sleep и select Qperlfunc(1). Функция select использована для организации короткой задержки в программе slowcat из рецепта 1.5. 3.11. Программа: hopdeltaВы никогда не задавались вопросом, почему какое-нибудь важное письмо так долго добиралось до вас? Обычная почта не позволит узнать, как долго ваше письмо пылилось на полках всех промежуточных почтовых отделений. Однако в электронной почте такая возможность имеется. В заголовке сообщения присутствует строка Received: с информацией о том, когда сообщение было получено каждым промежуточным транспортным агентом. Время в заголовках воспринимается плохо. Его приходится читать в обратном направлении, снизу вверх. Оно записывается в разных форматах но прихоти каждого транспортного агента. Но хуже всего то, что каждое время регистрируется в своем часовом поясе. Взглянув на строки "Tue, 26 May 1998 23:57:38 -0400" и "Wed, 27 May 1998 05:04:03 +0100", вы вряд ли сразу поймете, что эти два момента разделяют всего 6 минут 25 секунд. На помощь приходят функции ParseDate и DateCalc модуля Date::Manip от CPAN:use Date::Manip qw(ParseDate DateCalc);
+0:0:0:0:0:6:25
Пример 1.3. hopdelta #!/usr/bin/perl
|