在 Perl 中快速访问 YYYY-MM-dd HH: MM: SS

在编写 Perl 脚本时,我经常发现需要获取当前时间,这些时间表示为 YYYY-mm-dd HH:MM:SS格式的字符串(比如 2009-11-29 14:28:29)。

在这样做的过程中,我发现自己走上了一条相当麻烦的道路:

  • man perlfunc
  • /localtime搜索 localtime-重复5次(/ + \n)到达页面的相关部分
  • 将字符串 ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);从 manpage 复制到我的脚本。
  • 试试 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: 必须向 $mon 添加1才能得到当前月份。
  • 试试 my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec);
  • 看起来不错,搞定了!

虽然上面概述的过程是有效的,但它远远不是最佳的。我相信还有更聪明的办法,所以我的问题很简单:

在 Perl 中获得当前日期/时间的 YYYY-mm-dd HH:MM:SS最简单的方法是什么?

“容易”包括“容易写”和“容易记”。

162503 次浏览

在标准的 POSIX模块中使用 strftime。Perl 绑定中 strftime的参数被设计为与来自 localtimegmtime的返回值保持一致。比较一下

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以来在 core 中)也有一个 strftime 函数,默认情况下重载 localtime 和 gmtime 以返回 Time: : Piece 对象:

use Time::Piece;
print localtime->strftime('%Y-%m-%d');

或者没有被覆盖的本地时间:

use Time::Piece ();
print Time::Piece::localtime->strftime('%F %T');

Time::Piece::datetime()可以消除 T

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

如果你只是想要一个人类可读的时间字符串,而不是确切的格式:

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

指纹

Mon Apr 27 10:16:19 2015

或者为您的区域设置的任何东西。

我做了一个小测试(在 VM 中的 FreeBSD 下的 Perl v5.20.1) ,每个块调用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');

结果如下:

答: 2秒

11秒

C: 19秒

这当然不是一个彻底的测试或基准,但至少对我来说它是可重现的,所以即使它更复杂,如果经常需要生成一个日期时间戳,我更喜欢第一种方法。

调用(例如在 FreeBSD 10.1下)

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

可能不是一个好主意,因为它不是独立于操作系统的,而且需要相当长的时间。

最好的问候, 霍格

简洁明了,不需要额外的模块:

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

例如,输出为: 04/25/20179:30:33 AM

在许多情况下,所需的“当前时间”相当于 $^ T,即自 UNIX 时代以来脚本开始运行的整个秒(假设只有60秒)。

这是为了防止脚本的早期部分使用与脚本的后期部分不同的日期(或夏时制状态) ,例如在查询条件和其他派生值中。

对于“当前时间”的变体,可以使用一个常量,也可以记录它在编译时被冻结:

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

另一种更高分辨率的启动时间:

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