Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Month Dates

by Anonymous Monk
on Mar 01, 2007 at 20:50 UTC ( [id://602779]=perlquestion: print w/replies, xml ) Need Help??

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

Would anybody know of a module to help identify last month, last two months, etc taking into consideration leap dates? Essentially, I need to be able to say based on this month, give me:
This month => 03 or March last month => 02 or February Month before last => 01 or January Month before => 12 or December (of last year) This code is not working: my $tm = localtime; my $this_month = sprintf("%04d%02d?", $tm->year+1900, ($tm->mon)+1); my $last_month = sprintf("%04d%02d?", $tm->year+1900, ($tm->mon)); my $last_month_1 = sprintf("%04d%02d?", $tm->year+1900, ($tm->mon)-1); my $last_month_2 = sprintf("%04d%02d?", $tm->year+1900, ($tm->mon)-2);
Any ideas? Thanks.

Replies are listed 'Best First'.
Re: Month Dates
by Herkum (Parson) on Mar 01, 2007 at 21:25 UTC

    DateTime would be a better module to use than localtime,

    use DateTime; my $dt = DateTime->now(); print "Current Month " . $dt->month_name . "\n"; $dt->subtract( months => 1 ); print "Last Month " . $dt->month_name . "\n"; $dt->subtract( months => 1 ); print "2 Months ago " . $dt->month_name . "\n"; $dt->subtract( months => 1 ); print "3 Months ago " . $dt->month_name . "\n";
Re: Month Dates
by ww (Archbishop) on Mar 01, 2007 at 20:59 UTC
    The usual recommendations include Date::Calc and company.

    Depending on what your system is, ppm (for ActiveState) or CPAN for others will let you get and use the module.

    You'll also want to note that localtime does not count months as "1"-based, as you appear to be doing (pardon asked if I'm wrong):

    From perdoc -f localtime
    ...$mon is the month itself, in the range 0..11 with 0 indicating January and 11 indicating December. ....
    Just as an aside, you'll find that search and/or SuperSearch right here at the Monastery will be very helpful.
Re: Month Dates
by fenLisesi (Priest) on Mar 01, 2007 at 21:20 UTC
Re: Month Dates
by Sidhekin (Priest) on Mar 01, 2007 at 21:33 UTC

    I'm probably missing something, as this looks just too easy ... but have you considered modulus?

    Your code with minimal changes:

    my $tm = localtime; my $this_month = sprintf("%04d%02d?", $tm->year+1900, $tm->mon()+1, ); my $last_month = sprintf("%04d%02d?", $tm->year+1900-($tm->mon()<1 ? 1 : 0), ($tm->mon()-1)%12+1, ); my $last_month_1 = sprintf("%04d%02d?", $tm->year+1900-($tm->mon()<2 ? 1 : 0), ($tm->mon()-2)%12+1, ); my $last_month_2 = sprintf("%04d%02d?", $tm->year+1900-($tm->mon()<3 ? 1 : 0), ($tm->mon()-3)%12+1, );

    Edit: Bah, yeah, that was too easy. Forgot the year. Fixed now.

    print "Just another Perl ${\(trickster and hacker)},"
    The Sidhekin proves Sidhe did it!

Re: Month Dates
by ikegami (Patriarch) on Mar 01, 2007 at 22:07 UTC

    Using core functionality:

    use Time::Local qw( timelocal_nocheck ); use POSIX qw( strftime ); my ($sec,$min,$hour,$day,$mon,$year) = localtime; for (0..3) { my $time = timelocal_nocheck($sec,$min,$hour,$day,$mon-$_,$year); print(strftime("%Y-%m", localtime($time)), "\n"); }

    Update: Nevermind. Buggy because of the following change to Time::Local:

    Removed the code from the docs that implied that the *_nocheck variants were created for doing date math. They're just for speeding things up when you have known valid data. If you pass them invalid data, you'll probably get an incorrect answer. See #31421 on rt.perl.org for discussion.

    I do get invalid data.

Re: Month Dates
by jettero (Monsignor) on Mar 01, 2007 at 21:41 UTC

    I'm rather fond of the englishy things you can do with Date::Manip:

    my $this_month = &UnixDate(&ParseDate("today"), "%m"); my $two_ago = &UnixDate(&ParseDate("2 months ago"), "%B");

    -Paul

Re: Month Dates
by hangon (Deacon) on Mar 01, 2007 at 22:17 UTC

    This is fairly straightforward as long as you're not concerned with days of the month. Just roll your own code.

    # set numeric values my $month = my $year = my $monthsback = # subtract from current month $month -= $monthsback; # convert to proper range of values if($month <= 0){$year--} $year += int($month/12); $month = $month%12; if ($month == 0){$month = 12}

    Well, maybe a little more straightforward if you were looking for future months. If you need to take days of the month into account, you would have to figure out how you want to deal with such thinge as Feb 31st.

      It's odd that $month starts 0-based and ends 1-based. You also assume $monthsback is a small number. Fix:

      use POSIX qw( floor strftime ); my $monthsback = 3; # 0=this month -1=last, -2, ... my ($day,$mon,$year) = (localtime())[3,4,5]; $mon -= $monthsback; $year += floor($mon / 12); $mon = $mon % 12; print(strftime("%Y-%m", 0,0,0, $day,$mon,$year), "\n");

      A more general solution:

      use POSIX qw( floor strftime ); my $mon_delta = -3; # ..., -2, -1=last, 0=this month +1=next, +2, ... my ($day,$mon,$year) = (localtime())[3,4,5]; $mon += $mon_delta; $year += floor($mon / 12); $mon = $mon % 12; print(strftime("%Y-%m", 0,0,0, $day,$mon,$year), "\n");

        You're rigorous as usual ikegami, your realname wouldn't be Spock? ;)

        My point is that a simple algorithm could be used instead of importing a module, but I should have specified it's parameters more thoroughly:

        # positive integer, current year my $year = # integer 1 to 12, current month my $month = # positive integer, number of months to go back my $monthsback =
Re: Month Dates
by Thelonius (Priest) on Mar 02, 2007 at 13:26 UTC
    use Time::localtime; my $tm = localtime; my $this_month = sprintf("%04d%02d?", $tm->year+1900, ($tm->mon)+1); my $last_month = ($tm->mon == 0) ? sprintf("%04d12?", $tm->year+1899) : sprintf("%04d%02d?", $tm->year+1900, $tm->mon);
Re: Month Dates
by siva kumar (Pilgrim) on Mar 02, 2007 at 06:47 UTC
    You can use "inc_month" function in "DateTime::Precise" module.
    use DateTime::Precise; use strict; my $t1 = DateTime::Precise->new; my %months = ( 1 => q{January}, 2 => q{February}, 3 => q{March}, 4 => q{April}, 5 => q{May}, 6 => q{June}, 7 => q{July}, 8 => q{Auguest}, 9 => q{Septemper}, 10 => q{October}, 11 => q{November}, 12 => q{December}, ); my $thisMonth = $months{$t1->month}; my $prevMonth = $months{$t1->inc_month(-1)->month}; my $t1 = DateTime::Precise->new; my $monthB4rLast = $months{$t1->inc_month(-2)->month}; my $t1 = DateTime::Precise->new; my $monthB4rLast1 = $months{$t1->inc_month(-3)->month}; print "This Month is $thisMonth\n"; print "Previous Month is $prevMonth\n"; print "Month before last is $monthB4rLast\n"; print "Month before 2 months is $monthB4rLast1\n"; Output: ------- ThisMonth is March Next Month is February Month before last is January Month before 2 months is December
Re: Month Dates
by shandor (Monk) on Mar 01, 2007 at 21:29 UTC
    instead of using a module, maybe you can use something like this:
    my $month = (localtime())[4]; my $last_month = (($month)%12); my %months = ( 0 => "Dec", 1 => "Jan", 2 => "Feb", 3 => "Mar", 4 => "Apr", 5 => "May", 6 => "Jun", 7 => "Jul", 8 => "Aug", 9 => "Sep", 10 => "Oct", 11 => "Nov", ); print "$months{$last_month}\n";
      I'm puzzled as to why you use a hash with December associated with zero and a modulo operation. That will only work for the first decrement of a month. To go back another month you would need a different hash with November associated with zero, and so on and so forth. I think it might be better to have a single hash with zero for January to eleven for December (as returned by localtime) and a simple algorith for decrementing the month value, something like

      my %months = ( 0 => q{Jan}, 1 => q{Feb}, 2 => q{Mar}, 3 => q{Apr}, 4 => q{May}, 5 => q{Jun}, 6 => q{Jul}, 7 => q{Aug}, 8 => q{Sep}, 9 => q{Oct}, 10 => q{Nov}, 11 => q{Dec}, ); my $month = (localtime)[4]; $month --; $month = 11 if $month < 0;

      This way you can keep decrementing the month until the cows come home.

      Cheers,

      JohnGG

Re: Month Dates
by Moron (Curate) on Mar 02, 2007 at 14:16 UTC
    yet another variation:
    my @lt = localtime(); print map ("month $_ is " . 1 + ($lt[4]-- % 12) . "\n", ( 0..-3 ));

    -M

    Free your mind

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://602779]
Approved by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (4)
As of 2024-04-19 16:53 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found