Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

simple stupid time question

by lindex (Friar)
on Sep 14, 2000 at 06:13 UTC ( [id://32413]=perlquestion: print w/replies, xml ) Need Help??

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

What is the perlish way to get the number of days in a month, based on month and year ?


lindex
/****************************/ jason@gost.net, wh@ckz.org http://jason.gost.net /*****************************/

Replies are listed 'Best First'.
RE: simple stupid time question
by chromatic (Archbishop) on Sep 14, 2000 at 06:39 UTC
    I'd just write a simple routine to do it. Something like the following wouldn't be awful, in a dozen lines of code or so:
    sub days_in_month { my $month = shift; my $year = shift; my @mdays = qw( 31 28 31 30 31 30 31 31 30 31 30 31 ); if ($month == 2) { if ($year % 4 == 0) { # normal leap year if ($year % 100 == 0) { # century year, not a leap year return 28 unless ($year % 400 == 0); # century AND leap year } return 29; } } return $mdays[$month - 1]; # fudge the index }

    Update: Foggy and Adam contributed the current state of (now tested) not-so-bugginess. Seems like I should have actually *looked it up* in my library before I tried to recreate this wheel from memory.

    I originally intended this to be straightforward teaching code, but Adam's second snippet is much better.

      Your leap year code is still wrong. It should be:
      if ($month == 2) { if ( ( $year % 4 == 0 ) # normal leap year && ( ( $year % 100 != 0 ) # century year || ( $year % 400 == 0 ) # leap century ) ) { return 29; } }
      Also, you declare my $days = 0 but you don't use it.

      Update: All those parens are ugly, how about:

      if( 2 == $month ) { return 29 if 0 == $year % 4 and 0 != $year % 100 or 0 == $year % 400; }
      That works thanks to short circuitry and precedence. (yeah I could remove the 0 != part, but I wanted to retain explicit readability.)

      I think the leap year formula has become a frequently asked question, so I posted the answer here as well.

      Update: Chromatic's code will now work. It a slightly different way to look at it, using if and unless, but it works.

      Is it possible for a leap century to occur on a leap year? Couldn't you get 30 days in February as a result? I'm wondering if there isn't already a module that does this...

        Nope, you can't have a 30-day February specifically because the construct actually looks like:

        if ((($year % 4) = 0) && (($year % 100) != 0)) { $feb += 1; } #leap year elsif (($year % 400) = 0) { $feb +=1; } #leap century

        So, since a regular "leap year" doesn't occur at the end of a century, the two conditions are never simultaneously satisfied.

        Spud Zeppelin * spud@spudzeppelin.com

Re: simple stupid time question
by jptxs (Curate) on Sep 14, 2000 at 06:50 UTC

    a truly 'perlish' way is to grab a module :)

    I use Date::Business for this myself, but Date::Calc is an option too.

    -- I'm a solipsist, and so is everyone else. (think about it)

Re: simple stupid time question
by Foggy (Initiate) on Sep 14, 2000 at 07:03 UTC
    One nit in your code...it should be
    ... if($month == 1) { ...
    instead of 2 (since you decrement it to match the index)
RE: simple stupid time question
by turnstep (Parson) on Sep 14, 2000 at 14:49 UTC

    It would be nice to see something this small, simple, and often used put into perl itself at some point. Bob knows I've written a subrotine like the one above more than a few times. Yes, there are modules, but something with constants as basic as this should be accessible without the overhead of calling a module or writing a subroutine just to get a 12 member array (and a minor leap year calc). my ($0.02);

RE: simple stupid time question
by extremely (Priest) on Sep 15, 2000 at 03:46 UTC

    I always liked:

    sub leap { use Time::Local; my ($mo,$yr)=@_; #assumes month in 0-11 form ($yr++, $mo=0) if ++$mo>11; return (localtime(timelocal(0,0,0,1,$mo,$yr)-86400))[3]; }

    Seeing that someone else has done all the hard work for me.
    Plus it has bonus inscrutableness.

    --
    $you = new YOU;
    honk() if $you->love(perl)

Re: simple stupid time question
by tye (Sage) on Sep 15, 2000 at 20:06 UTC

    Given $mo and $yr set properly and not the way struct tm gives them (Jan is 1 not 0 and 2000 is 2000 not 100):

    (0,31,29-!(!($yr%4)&&$yr%100||not$yr%400),((31,30)x2,31)x2)[$mo]

    Just a lark! (not intended for production code)

            - tye (but my friends call me "Tye")

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (5)
As of 2024-04-18 21:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found