我以格式%dd。%mm。%YYYY获取日期,并且我尝试使用Perl减去一个月。
示例:12.07.2013 - > 12.06.2013,30.09.2013 - > 2013年8月31日
我应该使用Date :: Calc吗?有什么想法吗?
由于
答案 0 :(得分:6)
您可以使用Time::Piece
,这是自Perl v5.9.5以来的核心模块。
use strict;
use warnings;
use Time::Piece;
use Time::Seconds;
my $t = Time::Piece->strptime(shift, "%d.%m.%Y");
$t -= ONE_MONTH;
print $t->strftime("%d.%m.%Y");
鉴于参数12.07.2013
和30.09.2013
,此代码分别打印11.06.2013
和30.08.2013
。
strptime
函数根据模板将字符串解析为Time::Piece
对象。然后我们可以简单地添加/减去对象来操纵日期。这里我使用Time::Seconds
模块中的常量,相当于一个月。
这全部来自Time::Piece
的文档。
答案 1 :(得分:4)
DateTime支持您正在寻找的按月到月末行为。 end_of_month
选项记录在Adding a Duration to a Datetime部分中。我还提供了显示逻辑的Date::Calc解决方案。两种解决方案的输出相同。
<强> DateTime 强>
use DateTime;
my @dates = qw(
01.01.2013
28.02.2013
12.07.2013
30.09.2013
);
foreach my $string (@dates) {
my %p; @p{qw(day month year)} = split /\./, $string;
my $dt = DateTime->new(%p);
for my $n (-1, 1) {
my $res = $dt->clone->add(months => $n, end_of_month => 'preserve');
printf "%s %+d month => %s\n", $string, $n, $res->strftime('%d.%m.%Y');
}
}
<强> Date::Calc 强>
use Date::Calc qw[Days_in_Month Decode_Date_EU];
my @dates = qw(
01.01.2013
28.02.2013
12.07.2013
30.09.2013
);
sub Add_Months {
@_ == 4 || die q/Usage: Add_Months($year, $month, $day, $delta)/;
my ($y, $m, $d, $delta) = @_;
my $ultimo = ($d == Days_in_Month($y, $m));
use integer;
$m += $delta;
$y += $m / 12;
$m %= 12;
if ($m < 1) {
$y--, $m += 12;
}
my $dim = Days_in_Month($y, $m);
if ($d > $dim || $ultimo) {
$d = $dim;
}
return ($y, $m, $d);
}
foreach my $string (@dates) {
for my $n (-1, 1) {
printf "%s %+d month => %.2d.%.2d.%.4d\n",
$string, $n, reverse(Add_Months(Decode_Date_EU($string), $n));
}
}
输出:
01.01.2013 -1 month => 01.12.2012
01.01.2013 +1 month => 01.02.2013
28.02.2013 -1 month => 31.01.2013
28.02.2013 +1 month => 31.03.2013
12.07.2013 -1 month => 12.06.2013
12.07.2013 +1 month => 12.08.2013
30.09.2013 -1 month => 31.08.2013
30.09.2013 +1 month => 31.10.2013