Reputation: 1691
I was wondering if there is an in-built Perl function that adjusts the date if you take a month from it. E.g. if date is the 31st, it will adjust to be the end of the previous month if it doesn't have 31 days.
I would just change it to 30th easily if it weren't for the months with 31 days next to each other (Dec/Jan, Jul/Aug) and February. I just want to store the date a certain amount of time away from the current date, e.g.
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);
I can deal with the February instance as it only applies to years, but if this was taken on the 31st December 2012 then taking away a month would mean 31st Nov 2012, which of course didn't exist. I thought I would ask if there was a function before complicating things for myself... thanks :)
Upvotes: 5
Views: 6877
Reputation: 8532
Others have suggested DateTime
, but it's quite large, non-core, and can be slow.
A much simpler solution is to use the builtin localtime
and POSIX::mktime
functions:
use POSIX qw( mktime );
my @t = localtime $epoch;
$t[4] -= 2; # $t[4] is tm_mon
my $two_months_ago = mktime @t;
The mktime()
function specifically handles denormalised values; it will cope with the fact that Janurary minus 2 months is November of the previous year, etc.. It will keep the same second/minute/hour of the day, and the same day of the month.
Upvotes: 9
Reputation: 3465
If you have a chance to install module DateTime. It gives your a lot of perks, when you have deal with dates.
use strict;
use DateTime;
my $epoch = ...;
my $dt = DateTime->from_epoch( epoch => $epoch );
$dt->subract(months => 1);
printf "%s", $dt->datetime();
Upvotes: 7
Reputation: 5279
DateTime is not a built-in module, but once you've installed it, it makes this math trivial:
#!/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;
}
When I run this today (Aug 29, 2012) I get the following output:
[~] $ 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
Upvotes: 9