在编写 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 的绑定被设计为与返回值一致 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 方法对我来说有效地完成了这项工作。非常简单高效。


时间::件 (自 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]
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top