При написании скриптов Perl я часто нахожу необходимость получить текущее время, представленное в виде строки, отформатированной как YYYY-mm-dd HH:MM:SS
(скажем 2009-11-29 14:28:29
).
При этом я нахожу себя в этом довольно громоздком пути:
man perlfunc
/localtime
для поиска по местному времени - повторите пять раз (/
+ \n
), чтобы перейти к соответствующему разделу manpage($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
с man-страницы на мой script.my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year, $mon, $mday, $hour, $min, $sec);
my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon, $mday, $hour, $min, $sec);
my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec);
В то время как описанный выше процесс работает, он далеко не оптимален. Я уверен, что есть более умный способ, поэтому мой вопрос просто:
Каков самый простой способ получить YYYY-mm-dd HH:MM:SS
текущей даты/времени в Perl?
Где "легко" охватывает как "легко записываемые", так и "легко запоминаемые".
Используйте strftime
в стандартном модуле POSIX
. Аргументы strftime
в привязке Perls были разработаны для выравнивания с возвращаемыми значениями из localtime
и gmtime
. сравнить
strftime(fmt, sec, min, hour, mday, mon, year, wday = -1, yday = -1, isdst = -1)
с
my ($sec,$min,$hour,$mday,$mon,$year,$wday, $yday, $isdst) = gmtime(time);
Пример использования командной строки
$ perl -MPOSIX -le 'print strftime "%F %T", localtime $^T'
или из исходного файла, как в
use POSIX;
print strftime "%F %T", localtime time;
Некоторые системы не поддерживают сокращения %F
и %T
, поэтому вам придется явно указать
print strftime "%Y-%m-%d %H:%M:%S", localtime time;
или же
print strftime "%Y-%m-%d %H:%M:%S", gmtime time;
Обратите внимание, что time
возвращает текущее время при вызове, тогда как $^T
фиксируется во время запуска вашей программы. С gmtime
возвращаемое значение является текущим временем в GMT. Получить время в вашей временной зоне с localtime
.
Что не использует модуль DateTime
для выполнения грязной работы? Легко писать и запоминать!
use strict;
use warnings;
use DateTime;
my $dt = DateTime->now; # Stores current date and time as datetime object
my $date = $dt->ymd; # Retrieves date as a string in 'yyyy-mm-dd' format
my $time = $dt->hms; # Retrieves time as a string in 'hh:mm:ss' format
my $wanted = "$date $time"; # creates 'yyyy-mm-dd hh:mm:ss' string
print $wanted;
Как только вы знаете, что происходит, вы можете избавиться от темпов и сохранить несколько строк кода:
use strict;
use warnings;
use DateTime;
my $dt = DateTime->now;
print join ' ', $dt->ymd, $dt->hms;
Попробуйте следующее:
use POSIX qw/strftime/;
print strftime('%Y-%m-%d',localtime);
Метод strftime
делает работу эффективно для меня. Очень простой и эффективный.
Time:: Piece (в ядре, так как Perl 5.10) также имеет функцию strftime и по умолчанию перегружает localtime и gmtime для возврата объектов Time:: Piece:
use Time::Piece;
print localtime->strftime('%Y-%m-%d');
или без переопределенного локального времени:
use Time::Piece ();
print Time::Piece::localtime->strftime('%F %T');
Я сделал небольшой тест (Perl v5.20.1 под FreeBSD в VM), вызывающий следующие блоки: 1.000.000 раз каждый:
А
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec);
В
my $now = strftime('%Y%m%d%H%M%S',localtime);
С
my $now = Time::Piece::localtime->strftime('%Y%m%d%H%M%S');
со следующими результатами:
A: 2 секунды
B: 11 секунд
C: 19 секунд
Это, конечно, не тщательный тест или бенчмарк, но, по крайней мере, он воспроизводится для меня, поэтому, хотя это сложнее, я бы предпочел первый метод, если генерация datetimestamp требуется очень часто.
Вызов (например, под FreeBSD 10.1)
my $now = `date "+%Y%m%d%H%M%S" | tr -d "\n"`;
может не быть такой хорошей идеей, потому что она не зависит от ОС и занимает довольно много времени.
С уважением, Хольгер
если вы просто хотите, чтобы человекочитаемая строка времени, а не точный формат:
$t = localtime;
print "$t\n";
печатает
Mon Apr 27 10:16:19 2015
или все, что настроено для вашей локали.
Time::Piece::datetime()
может устранить T
.
use Time::Piece;
print localtime->datetime(T => q{ });
Короткий и сладкий, никаких дополнительных модулей не требуется:
my $toDate = `date +%m/%d/%Y" "%l:%M:%S" "%p`;
Результат, например, будет: 25.04.2012 9:30:33 AM