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

58

При написании скриптов 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?

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

  • 0
    Вы должны были написать подпрограмму для поиска в perlfunc и, конечно же, запомнить для вас ошибки!
Теги:
datetime
timestamp
formatting

8 ответов

70
Лучший ответ

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

  • 0
    Существует также strftime в Time :: Piece (ядро с 5.10), который позволяет вам использовать более объектно-ориентированную форму (см. Мой ответ ниже). Кроме того, $ ^ T (время с момента запуска программы) не то, что вы хотите.
34

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

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

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

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


13

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');
  • 1
    +1 за упоминание основного модуля и его использование - поскольку огромное количество доступных модулей является одной из основных причин, почему большинство из нас в первую очередь используют Perl
4

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

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

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

3

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

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

печатает

Mon Apr 27 10:16:19 2015

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

2

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

use Time::Piece;
print localtime->datetime(T => q{ });
  • 0
    еще одно упоминание о Time :: Piece должно заставить меня вспомнить это сейчас - не совсем простой модуль, который нужно запомнить, если не использовать его каждый день :)
0

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

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню