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


70

在编写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);
  • 记住第一点:必须将$ year加1900才能获得当前年份。
  • 试试看 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中获取当前日期/时间的最简单方法是什么?

“简单”既包括“易于编写”又包括“易于记忆”。


当然,您应该已经编写了一个子程序来搜索perlfunc,并为您记住了陷阱!
2009年

编写一个包含所有步骤的stackoverflow问题,假装寻求解决方案:-)
Astrinus,

Answers:


78

使用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,返回值是格林尼治标准时间的当前时间。使用检索您当地时区的时间localtime


在Time :: Piece中也有strftime(自5.10开始,它是核心),它使您可以使用面向对象的形式(请参阅下面的答案)。另外,$ ^ T(程序启动后的时间)也不是您想要的。
MkV 2012年

34

为什么不使用该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;

32

尝试这个:

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

strftime方法对我有效。非常简单高效。



13

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

1
提及核心模块及其用法+1 -因为大量可用模块是我们大多数人首先使用Perl的主要原因之一
osirisgothra,2015年

8

我做了一点测试(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秒

当然,这不是彻底的测试或基准测试,但至少对我而言是可重现的,因此,即使它比较复杂,但如果经常需要生成日期时间戳,我还是希望使用第一种方法。

调用(例如在FreeBSD 10.1下)

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

可能不是一个好主意,因为它与操作系统无关,并且需要花费很多时间。

最好的问候,Holger


5

如果您只需要人类可读的时间字符串而不是确切的格式:

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

版画

Mon Apr 27 10:16:19 2015

或为您的语言环境配置的任何内容。


4

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

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

再次提及Time :: Piece应该让我现在记住它-如果不是每天都不使用,那不是最容易记住的最简单的模块了:)
osirisgothra

2

简短有趣,无需其他模块:

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

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


date +%Y-%m-%d" "%H:%M:%S获取OP所需的确切格式
lfurini,

从Windows命令行调用时不起作用,对吗?Windows版本的“日期”具有不同的行为。
罗马

我的答案基于在Unix系统上运行的Perl,因此它可能不适用于Windows版本的Perl。因此,您没有在Windows上运行Perl时得到此结果吗?
关金

2

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

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

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

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

替代的高分辨率启动时间:

0+ [ Time::HiRes::stat("/proc/$$") ]->[10]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.