在 Perl 中快速获取 YYYY-mm-dd HH:MM:SS
-
06-07-2019 - |
题
在编写 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);
从联机帮助页到我的脚本。 - 尝试用
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);
- 看起来还可以。完毕!
虽然上述过程有效,但远非最佳。我确信有一种更聪明的方法,所以我的问题很简单:
获得证书的最简单方法是什么 YYYY-mm-dd HH:MM:SS
Perl 中的当前日期/时间?
其中“容易”包含“易于编写”和“易于记住”。
解决方案
使用 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
.
其他提示
什么不可以用 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
方法对我来说有效地完成了这项工作。非常简单高效。
时间::件 (自 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');
我做了一个小测试(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);
乙
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秒
乙:11秒
C:19秒
这当然不是一个彻底的测试或基准,但至少它对我来说是可重现的,所以即使它更复杂,如果经常需要生成日期时间戳,我更喜欢第一种方法。
打电话(例如在 FreeBSD 10.1 下)
my $now = `date "+%Y%m%d%H%M%S" | tr -d "\n"`;
可能不是一个好主意,因为它不独立于操作系统并且需要相当长的时间。
最好的问候,霍尔格
Time::Piece::datetime()
可以消除 T
.
use Time::Piece;
print localtime->datetime(T => q{ });
如果您只想要一个人类可读的时间字符串而不是确切的格式:
$t = localtime;
print "$t\n";
印刷
Mon Apr 27 10:16:19 2015
或为您的语言环境配置的任何内容。
简短而甜蜜,不需要额外的模块:
my $toDate = `date +%m/%d/%Y" "%l:%M:%S" "%p`;
例如输出将是:2017 年 4 月 25 日 9:30:33 上午
在许多情况下,所需的“当前时间”实际上是 $^T,这是脚本开始运行的时间,自 UNIX 纪元以来以整秒为单位(假设只有 60 秒分钟)。
这是为了防止脚本的早期部分使用与脚本的后期部分不同的日期(或夏令时状态),例如在查询条件和其他派生值中。
对于“当前时间”的变体,可以使用一个常量,也可以记录它在编译时被冻结:
use constant YMD_HMS_AT_START => POSIX::strftime( "%F %T", localtime $^T );
替代更高分辨率的启动时间:
0+ [ Time::HiRes::stat("/proc/$$") ]->[10]