Подтвердить что ты не робот

Быстро добраться до ГГГГ-мм-дд ЧЧ: ММ: СС в Перл

При написании скриптов 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);
  • Помните, что gotcha # 1: нужно добавить от 1900 до $года, чтобы получить текущий год.
  • Попробуйте my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon, $mday, $hour, $min, $sec);
  • Помните, что gotcha # 2: нужно добавить от 1 до $mon, чтобы получить текущий месяц.
  • Попробуйте my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec);
  • Кажется, все в порядке. Готово!

В то время как описанный выше процесс работает, он далеко не оптимален. Я уверен, что есть более умный способ, поэтому мой вопрос просто:

Каков самый простой способ получить YYYY-mm-dd HH:MM:SS текущей даты/времени в Perl?

Где "легко" охватывает как "легко записываемые", так и "легко запоминаемые".

4b9b3361

Ответ 1

Используйте 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.

Ответ 2

Что не использует модуль 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;

Ответ 3

Попробуйте следующее:

use POSIX qw/strftime/;
print strftime('%Y-%m-%d',localtime);

Метод strftime делает работу эффективно для меня. Очень простой и эффективный.


Ответ 4

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');

Ответ 5

Я сделал небольшой тест (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"`;

может не быть такой хорошей идеей, потому что она не зависит от ОС и занимает довольно много времени.

С уважением, Хольгер

Ответ 6

Time::Piece::datetime() может устранить T.

use Time::Piece;
print localtime->datetime(T => q{ });

Ответ 7

если вы просто хотите, чтобы человекочитаемая строка времени, а не точный формат:

$t = localtime;
print "$t\n";

печатает

Mon Apr 27 10:16:19 2015

или все, что настроено для вашей локали.

Ответ 8

Короткий и сладкий, никаких дополнительных модулей не требуется:

my $toDate = `date +%m/%d/%Y" "%l:%M:%S" "%p`;

Результат, например, будет: 25.04.2012 9:30:33 AM

Ответ 9

Во многих случаях необходимое "текущее время" - это скорее $ ^ T, то есть время, в которое скрипт начал работать, в целых секундах (при условии, что только 60 секунд), начиная с эпохи UNIX.

Это предотвращает использование в ранней части сценария другой даты (или статуса перехода на летнее время), чем в более поздней части сценария, например, в условиях запроса и других производных значениях.

Для этого варианта "текущего времени" можно использовать константу, а также документировать, что она была заморожена во время компиляции: use constant YMD_HMS_AT_START => POSIX::strftime( "%F %T", localtime $^T );

Альтернативное время запуска с более высоким разрешением: 0+ [ Time::HiRes::stat("/proc/$$") ]->[10]