Быстро добраться до ГГГГ-мм-дд ЧЧ: ММ: СС в Perl - PullRequest
60 голосов
/ 29 ноября 2009

При написании сценариев Perl я часто нахожу необходимость получить текущее время, представленное в виде строки, отформатированной как YYYY-mm-dd HH:MM:SS (скажем, 2009-11-29 14:28:29).

Поступая так, я иду по этому довольно громоздкому пути:

  • man perlfunc
  • /localtime для поиска местного времени - повторите пять раз (/ + \n), чтобы перейти к соответствующему разделу справочной страницы
  • Скопируйте строку ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); из man-страницы в мой скрипт.
  • Попробуйте с my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year, $mon, $mday, $hour, $min, $sec);
  • Помните, что у вас # 1: для получения текущего года нужно добавить 1900 к $ year.
  • Попробуйте с my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon, $mday, $hour, $min, $sec);
  • Помните, что у вас # 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?

Там, где «легкий» включает в себя «легкий для написания» и «легкий для запоминания».

Ответы [ 9 ]

70 голосов
/ 29 ноября 2009

Используйте strftime в стандартном модуле POSIX. Аргументы strftime в привязке Perl предназначены для выравнивания с возвращаемыми значениями 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.

32 голосов
/ 29 ноября 2009

Что не использовать модуль 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;
30 голосов
/ 16 октября 2012

Попробуйте это:

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

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


13 голосов
/ 16 октября 2012

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 голосов
/ 22 сентября 2015

Я провел небольшой тест (Perl v5.20.1 под FreeBSD в VM), вызывая следующие блоки 1.000.000 раз каждый:

A

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

B

my $now = strftime('%Y%m%d%H%M%S',localtime);

C

my $now = Time::Piece::localtime->strftime('%Y%m%d%H%M%S');

со следующими результатами:

A: 2 секунды

B: 11 секунд

C: 19 секунд

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

Calling (например, под FreeBSD 10.1)

my $now = `date "+%Y%m%d%H%M%S" | tr -d "\n"`;

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

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

3 голосов
/ 27 апреля 2015

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

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

отпечатки

Mon Apr 27 10:16:19 2015

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

3 голосов
/ 05 февраля 2014

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

use Time::Piece;
print localtime->datetime(T => q{ });
1 голос
/ 25 апреля 2017

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

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

Например, вывод будет: 25.04.2017 9:30:33 AM

0 голосов
/ 08 июня 2019

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

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

Для этого варианта «текущего времени» можно использовать константу, а также для документирования того, что она была заморожена во время компиляции:

use constant YMD_HMS_AT_START => POSIX::strftime( "%F %T", localtime $^T );

Альтернативное время запуска с более высоким разрешением:

0+ [ Time::HiRes::stat("/proc/$$") ]->[10]
...