5

我想知道是否有一个内置的 Perl 函数可以调整日期,如果你需要一个月的时间。例如,如果日期是 31 日,如果没有 31 天,它将调整为上个月的月底。

如果不是相邻的 31 天(12 月/1 月、7 月/8 月)和 2 月,我会轻松地将其更改为第 30 天。我只想将日期存储在距当前日期一定时间的位置,例如

my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);

$current_date = join("-", (1900+$year), ($mon+1), $mday);
$one_month_ago = join("-", (1900+$year), ($mon), $mday);
$one_year_ago = join("-", (1899+$year), ($mon+1), $mday);

我可以处理 2 月的实例,因为它只适用于年份,但如果这是在 2012 年 12 月 31 日拍摄的,那么带走一个月将意味着 2012 年 11 月 31 日,这当然不存在。我想我会在为自己复杂化之前询问是否有一个功能......谢谢:)

4

3 回答 3

10

DateTime 不是一个内置模块,但是一旦你安装了它,它就会使这个数学变得微不足道:

#!/usr/bin/perl
use strict;
use warnings;

use feature qw( say );
use DateTime;

my $dt = DateTime->now;
say $dt->ymd;

$dt->truncate( to => month );

say $dt->ymd;

$dt->add( days => -1 );
say $dt->ymd;

foreach ( 1 .. 12 ) { 
    $dt->add( months => -1 );
    say $dt->ymd;
} 

当我今天(2012 年 8 月 29 日)运行它时,我得到以下输出:

[~] $ perl dt.pl 
2012-08-29
2012-08-01
2012-07-31
2012-06-30
2012-05-31
2012-04-30
2012-03-31
2012-02-29
2012-01-31
2011-12-31
2011-11-30
2011-10-31
2011-09-30
2011-08-31
2011-07-31
于 2012-08-29T11:20:05.547 回答
9

其他人提出了建议DateTime,但它非常大,非核心,并且可能很慢。

一个更简单的解决方案是使用内置localtimePOSIX::mktime函数:

use POSIX qw( mktime );

my @t = localtime $epoch;
$t[4] -= 2;  # $t[4] is tm_mon
my $two_months_ago = mktime @t;

mktime()函数专门处理非规范化值;它将处理一月减去 2 个月是上一年的十一月等事实。它将保持一天中相同的秒/分钟/小时,以及该月的同一天。

于 2012-08-29T11:59:03.740 回答
8

如果您有机会安装模块DateTime。当您处理日期时,它会给您带来很多好处。

use strict;
use DateTime;

my $epoch = ...;
my $dt    = DateTime->from_epoch( epoch => $epoch );
$dt->subract(months => 1);

printf "%s", $dt->datetime();
于 2012-08-29T11:20:52.753 回答