在Perl中快速到达YYYY-MM-DD HH:MM:SS

在编写Perl脚本时,我经常会发现需要获取以stringforms表示的当前时间,格式为YYYY-mm-dd HH:MM:SS (说2009-11-29 14:28:29 )。

在这样做的时候,我发现自己采取了这个相当麻烦的道路:

  • man perlfunc
  • /localtimesearch本地时间 – 重复五次( / + \n )到达联机帮助页的相关部分
  • 复制string($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年到$年来获得当年。
  • 尝试使用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);
  • 似乎没关系。 完成!

虽然上面概述的过程是有效的,但远非最佳。 我敢肯定有一个更聪明的方法,所以我的问题是:

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

“易”包含“易写”和“易记”。

在标准POSIX模块中使用strftime

 $ perl -MPOSIX -le 'print strftime "%F %T", localtime $^T' 

Perl绑定中strftime的参数被devise为与来自localtimegmtime的返回值一致。

什么不使用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'); 

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

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

版画

 Mon Apr 27 10:16:19 2015 

或任何configuration为您的区域设置。

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

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

我做了一个小testing(在vm下FreeBSD下的Perl v5.20.1),每次调用下面的块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); 

C

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

结果如下:

答:2秒

B:11秒

C:19秒

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

调用(例如在FreeBSD 10.1下)

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

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

最好的问候,Holger

短而甜,不需要额外的模块:

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

输出例如将是:04/25/2017 9:30:33 AM