kanewilliam7777 has asked for the wisdom of the Perl Monks concerning the following question:

Hello,

How to get last month date using Date::Calc?

For example, today is 8/2003 - I would like the function to return 7/2003 (for the previous month).

If the date today is 1/2004 - it should return 12/2003

  • Comment on How to get last month date using Date::Calc

Replies are listed 'Best First'.
Re: How to get last month date using Date::Calc
by haukex (Archbishop) on Oct 12, 2018 at 10:55 UTC
    use warnings; use strict; use Date::Calc qw/Add_Delta_YM/; sub prevmonth { my ($year, $month) = @_; my ($newyear, $newmonth, undef) = Add_Delta_YM( $year, $month, 1, 0, -1 ); return [$newyear, $newmonth]; } use Test::More; is_deeply prevmonth(2003,8), [2003,7]; is_deeply prevmonth(2004,1), [2003,12]; done_testing;

    Update: This is also possible with the core module Time::Piece. If you have a modern browser like the latest Firefox or Chrome, here is a live demo of the following code.

    use warnings; use strict; use Time::Piece; while (<>) { chomp; my $t = Time::Piece->strptime($_, '%m/%Y'); my $prev = $t->add_months(-1); print $prev->strftime('%m/%Y'), "\n"; }
Re: How to get last month date using Date::Calc
by Discipulus (Canon) on Oct 12, 2018 at 10:52 UTC
    Hello kanewilliam7777

    I think you can use Add_Delta_DHMS adding -1 month (well I intended Add_Delta_YMD )

    update

    perl -e "use Date::Calc qw(Add_Delta_YMD); ($year, $month, $day) = Add +_Delta_YMD(2003, 8,1,0,-1,0); print qq($month/$year)" 7/2003

    L*

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: How to get last month date using Date::Calc (caution advised)
by 1nickt (Canon) on Oct 12, 2018 at 12:13 UTC

    Hi, date math is tricky, not so much because there are no tools, but because one must be very precise in thinking about the calculation actually needed.

    If you are asking on, say, March 30, what month is a month ago?

    Perl tools differ in their answer:

    $ perl -MDate::Calc=Add_Delta_YM -E 'say "$_ : " . join "-", Add_Delta +_YM( split("-", $_), 0,-1) for qw/2018-03-28 2018-03-29 2018-03-30 20 +18-03-31/' 2018-03-28 : 2018-2-28 2018-03-29 : 2018-2-28 2018-03-30 : 2018-2-28 2018-03-31 : 2018-2-28 $ perl -MTime::Piece -E 'do { $t = Time::Piece->strptime($_, "%Y-%m-%d +"); say "$_ : " . $t->add_months(-1)->strftime("%Y-%m-%d") } for qw/2 +018-03-28 2018-03-29 2018-03-30 2018-03-31/' 2018-03-28 : 2018-02-28 2018-03-29 : 2018-03-01 2018-03-30 : 2018-03-02 2018-03-31 : 2018-03-03
    ... and that's not even taking into account Daylight Savings Time and other things. So be careful!

    (For those wondering, DateTime returns the same as Date::Calc.)

    Hope this helps!


    The way forward always starts with a minimal test.

      The docs for Time::Piece explain it thus (emphasis mine):

      The months and years can be negative for subtractions. Note that there is some "strange" behaviour when adding and subtracting months at the ends of months. Generally when the resulting month is shorter than the starting month then the number of overlap days is added. For example subtracting a month from 2008-03-31 will not result in 2008-02-31 as this is an impossible date. Instead you will get 2008-03-02. This appears to be consistent with other date manipulation tools.
        An odd thing to say, since it isn't consistent with DateTime, Time::Moment, or (apparently) Date::Calc.
Re: How to get last month date using Date::Calc
by Tux (Canon) on Oct 12, 2018 at 12:30 UTC

    When the day (and time) is not involved, your question does not need Date::Calc or anything fancy.

    $ perl -wE'my($m,$y)=(localtime)[4,5];--$m<0 and($m,$y)=($m+12,$y--);s +ay $m+1,"-",$y+1900;' 9-2018

    or as sub

    sub previous_month { my ($month, $year) = @_; # month = 1..12 if (--$month < 1) { $month = 12; $year--; } ($month, $year); } # previous_month say for previous_month (10, 2018);

    Enjoy, Have FUN! H.Merijn
Re: How to get last month date using Date::Calc
by Anonymous Monk on Oct 12, 2018 at 21:01 UTC