http://www.perlmonks.org?node_id=913352

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

I'm very new to Perl and have been reading lots of documents, PDF's, how-to and tutorials on line and can't find exactly what I'm looking for. I'm hoping for a portable solution, (so don't want to install CPAN modules to do this) as this isn't an option on the machines this script is being use on. So based off of current date have one scalar variable to determine yesterdays date in the form of %Y%m%d and and a second scalar variable with same date format but a week ago from yesterdays date. Thank you for taking the time to review this desperate plea for assistance.

Replies are listed 'Best First'.
Re: Portable previous dates
by BrowserUk (Patriarch) on Jul 08, 2011 at 15:02 UTC

    Should be portable, and probably quicker than most other methods:

    #! perl -slw use strict; sub formatYMD { my( $y, $m, $d ) = ( localtime shift )[ 5,4,3 ]; return sprintf "%4d%02d%02d", $y+1900, $m+1, $d; } my $today = my $yesterday = time; $yesterday -= 43200 while substr( localtime( $today ), 0, 3 ) eq substr( localtime( $yesterday ), 0, 3 ); my $lastweek = $yesterday - 13 * 43200; $lastweek -= 43200 while substr( localtime( $yesterday ), 0, 3 ) ne substr( localtime( $lastweek ), 0, 3 ); print ' today: ', formatYMD( $today ); print 'yesterday: ', formatYMD( $yesterday ); print ' lastweek: ', formatYMD( $lastweek ); __END__ c:\test>junk4 today: 20110708 yesterday: 20110707 lastweek: 20110630

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      Thank you for the feedback BrowserUK, gave me some good insight how to accomplish what I want. Darryl
Re: Portable previous dates
by jethro (Monsignor) on Jul 08, 2011 at 14:26 UTC
    If you can't install them, copy them. Just use a CPAN module for this, but bundle it and any depending modules with your script. You can either do this by hand (i.e. use copy-and-paste on the sources) or use something like PAR PAR::Packer and pp to package the modules together with your script.
      Thanks Jethro, was not aware of pp will look into this further to use with other projects. Darryl
Re: Portable previous dates
by Anonymous Monk on Jul 08, 2011 at 14:20 UTC

    I'm hoping for a portable solution, (so don't want to install CPAN modules to do this) as this isn't an option on the machines this script is being use on.

    Sure it is :) This is a FAQ (Frequently Asked Question) :) Yes, even you can use CPAN

    Doing date math by yourself sucks :) DateTime, Date::Manip, Time::gmtime, Time::...

Re: Portable previous dates
by vt220 (Scribe) on Jul 09, 2011 at 00:31 UTC

    A long while back, after finding these:

    http://alcor.concordia.ca/~gpkatch/gdate-algorithm.html
    http://www.smart.net/~mmontes/ushols.html

    I put together the following subs. Please note that I add or subtract 3 in the conversion routines. This allows a modulo function to return the day of the week with 0 equaling Sunday. As in:

    $DoW = $gdate % 7;

    I humbly submit the following for review...

    #=================================================================== # d2g() Convert year, month, and day to date factor G. sub d2g { my($y, $m, $d) = @_; my $g; $m = ($m + 9) % 12; $y = $y - int($m/10); $g = 365*$y + int($y/4) - int($y/100) + int($y/400) + int(($m*306 ++ 5)/10) + ($d - 1); #------- $g += 3; return $g; } #==================================================================== # g2d() Convert date factor G to year, month, and day. sub g2d { my($g) = @_; my($y, $m, $d, $M, $D); #----------------------------------- $g -= 3; #------- $y = int((10000*$g + 14780)/3652425); $D = $g - (365*$y + int($y/4) - int($y/100) + int($y/400)); if ( $D < 0 ) { $y = $y - 1; $D = $g - (365*$y + int($y/4) - int($y/100) + int($y/400)); } $M = int((100*$D + 52)/3060); $m = ($M + 2)%12 + 1; $y = $y + int(($M + 2)/12); $d = $D - int(($M*306 + 5)/10) + 1; return ($y, $m, $d); } #==================================================================== # ValidYMD() Returns true if given year, month, and day is valid. sub ValidYMD { my($y, $m, $d) = @_; my($Y, $M, $D) = g2d( d2g($y, $m, $d) ); return $y == $Y && $m == $M && $d == $D; }
      Thanks for the response vt220, will review this code and see what I can learn from it. Darryl