为什么perl的本地时间似乎输出错误的月份?

时间:2015-11-12 16:42:22

标签: perl date

我已经看到了其他答案,但由于某些原因他们并没有为我工作。

我试图使用以下代码在Perl脚本中获取昨天的日期。

供将来参考,今天的日期是2015年11月12日

my (undef, undef, undef, $mday,$mon,$year) = localtime();
my $prev_day = timelocal(0, 0, 0, $mday-1, $mon, $year);
(undef, undef, undef, $mday,$mon,$year) = localtime($prev_day);
$year += 1900;

print "Yesterday's Day: $mday, Month: $mon, Year: $year\n";

除了我的输出看起来像这样

Yesterday's Day: 11, Month: 10, Year: 2015.

我应该在昨天阅读Day: 11, Month: 11, Year: 2015的日期。为什么减去月份?

编辑:这与建议的答案不同,因为我想知道为什么当地时间似乎写错了月份。

2 个答案:

答案 0 :(得分:7)

documentation for localtime说明了这个

  

$ mday是月份中的一天,月份中的$ mon是0..11,0表示1月,11表示12月。

因此,要获得一月份为1的月份数字,您需要$mon+1,或者您可以在向$mday $year添加一个>

喜欢这个

use strict;
use warnings 'all';

use Time::Local;

my ($y, $m, $d) = (localtime)[5,4,3];

my $yesterday = timelocal(0, 0, 0, $d-1, $m, $y);
($y, $m, $d) = (localtime($yesterday))[5,4,3];
$y += 1900;
++$m;

print "Yesterday's Day: $d, Month: $m, Year: $y\n";

输出

Yesterday's Day: 11, Month: 11, Year: 2015

更好的方法是使用像这样的核心库Time::Piece

use strict;
use warnings 'all';

use Time::Piece;
use Time::Seconds 'ONE_DAY';

my $yesterday = localtime() - ONE_DAY;

printf "Yesterday's Day: %d, Month: %d, Year: %d\n",
    $yesterday->mday,
    $yesterday->mon,
    $yesterday->year;

输出

Yesterday's Day: 11, Month: 11, Year: 2015

答案 1 :(得分:4)

localtime和朋友们在6(或9-)元素列表上工作,该列表只展开POSIX struct tm结构的各个字段。在该结构中,tm_mon字段是第5个元素,表示0到11范围内的月份。我相信这里的意图可能是允许您将其用作包含字符串的字符串数组中的索引。您所在地区的月份名称。

获取时间元素列表并将其格式化以供人类消费的唯一合理方法是通过strftime函数,该函数采用您希望呈现的某种格式。例如:

use POSIX qw( strftime );

print strftime( "Yesterday's Day: %d Month: %m, Year: %Y\n", localtime $epoch );

如果您还没有Unix纪元价值,可以从mktime()timelocal()

获取一个
use POSIX qw( strftime mktime );

my ( $mday, $mon, $year ) = ... # as before

print strftime( "Yesterday's Day: %d Month: %m, Year: %Y\n",
   localtime mktime 0, 0, 0, $mday, $mon, $year );

通过此mktime - localtime往返发送值非常重要,因为这是他们规范化的方式 - 例如因为从该月的第一天减去1; mktime()这里的工作是将其重新规范到上个月的最后一天(并且如果是1月份则必须回滚年份等等)