如何在Perl中追溯月份,同时考虑到月份中的不同日期?

如何在Perl中追溯月份,同时考虑到月份中的不同日期?,perl,function,date,time,localtime,Perl,Function,Date,Time,Localtime,我想知道是否有一个内置的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+$yea

我想知道是否有一个内置的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);

我可以处理二月的例子,因为它只适用于年,但如果这是在2012年12月31日,那么去掉一个月就意味着2012年11月31日,当然这是不存在的。我想在把事情复杂化之前我会问一下是否有一个功能。。。谢谢:)

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

如果您有机会安装模块。当你处理约会时,它会给你很多额外的好处

use strict;
use DateTime;

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

printf "%s", $dt->datetime();

其他人建议使用
DateTime
,但它相当大,不是核心,而且速度可能很慢

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

use POSIX qw( mktime );

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

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

您可以搜索此模块吗?(上面有日期的数学)下面的两个答案都很好!日期-时间看起来是一个非常有用的选项,但由于我想在代码的一小部分中使用它,我想我可能会投入其中,为它编写一系列子句。长篇大论,但它会帮助我学习。。。这是我第一天使用Perl:P,谢谢你的帮助!老实说,如果我能给出两个最好的答案,我会的,但你有更多的信息:)谢谢!我从未见过say功能-知道它很有用!此功能取决于Perl的版本。它应该是>=5.10这看起来很好,但我无法让它打印出$2个月前的数字,因为它说它是未初始化的(然后我初始化了它,没有任何更改)。对于其他代码,它确实可以!我不得不说,这是我一直在寻找的一个更好的版本:)Kudos使用
POSIX::mktime()
Time::Local::timelocal()
有什么优势吗?在我看来,他们都做了同样的事。没什么。POSIX one是一个真正的POSIX函数,Time::Local函数只是为了在Time::Local包中实现完整性。它们应该给出相同的结果。我通常更喜欢POSIX,因为在任何非普通大小的程序中,很可能POSIX.{pm,so}已经加载,所以使用它的更多函数是免费的。我认为这不是OP要求的方式。如果你从2012-12-31减去一个月,你将得到2012-12-01,而不是2012-11-30。2012-01-31再加上一个月,你就得到了2012-03-02,而不是2012-02-29。如果结果月份的天数少于给定日期的月份天数,则结果将按超出天数向前或向后计算到下一个月或上一个月。