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

Below is the code I'm using to calculate the number of months that have elapsed since a certain time (when our database was originally built). The following code currently works. My question is: I've fudged the months as being equal to "30" so the $elapsed_mons calculation will be correct (as of today anyways).

Other than using Date::Calc (which we don't have loaded and I'd like to avoid asking the dba's to load modules if possible - don't ask - politics) and Date::Manip which I hear is *really* *really* *really* impressive in it's flexibility but far beyond what I need (sledgehammer vs. toothpick?)... any ideas on how to better (more accurately) count the number of months since 6/30/99?

P.S.: $elapsed_mons returns "56" which is correct (as of today). Thanks for any advice/insight you can provide.

#!/usr/local/bin/perl5_8 use strict; use warnings; use Time::Local; #snipped stuff #Calculate elapsed months since today my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime; my $mo = $mon + 1; my $dy = $mday; my $yr = $year + 1900; #yep, extra steps but makes it clearer to me... my $now_date = "$yr/$mo/$dy"; my($ny, $nm, $nd) = $now_date =~ m<^(\d+)/(\d+)/(\d+)$>; my $ntime = timelocal(0, 0, 12, $nd, $nm-1, $ny); my $then_date = "1999/06/30"; # rpts will never go back beyond this d +ate my($ty, $tm, $td) = $then_date =~ m<^(\d+)/(\d+)/(\d+)$>; my $ttime = timelocal(0, 0, 12, $td, $tm-1, $ty); my $elapsed_mons = int(($ntime - $ttime)/( 60 * 60 * 24 * 30)); #use $elapsed_mons to generate drop down list of available report mont +hs #snipped stuff

Lori

Replies are listed 'Best First'.
Re: Time::Local - calculate months elapsed
by liz (Monsignor) on Feb 24, 2004 at 18:53 UTC
    Apart from the suggestions already made, you can just do the calculation of years and months if you're just interested in "whole" month numbers, and bypass the issue of what is a month altogether:
    sub months { my (undef,undef,undef,$day,$month,$year) = localtime; $_[0] =~ m#^(\d+)/(\d+)/(\d+)$#; (12 * (1900 + $year - $1)) + 1 + $month - $2 - ($day < $3); } print months( "1999/06/30" ),$/; print months( "2004/01/24" ),$/; print months( "2004/01/25" ),$/; __END__ 55 1 0
    Please note that I don't think "56" is the correct answer for today. It's still 6 days from the 30th, and only then we'd be 56 months from the given date. Check the other examples.

    Of course, all of this doesn't take into account anything like timezones. But if you're only interested in whole month granularity, I think that's pretty ok.

    Liz

      You're absolutely correct. I'm only really interested in whole months. The other solutions are equally workable but you've pointed out something I hadn't thought of: we're not quite at the end of the month. So, I think your solution will probably nail it for me most accurately.

      Thanks to all who responded!

      Lori

Re: Time::Local - calculate months elapsed
by Limbic~Region (Chancellor) on Feb 24, 2004 at 18:30 UTC
    Lori713,
    Here is a TIMTOWTDI solution. The Seconds2English module you will not find on CPAN as I wrote for learning purposes. The code has been cleaned up a bit - but that is on a hard drive sitting on a shelf.
    #!/usr/bin/perl -w use strict; use Time::Local; use Seconds2English; my $date1 = epoch('2004-02-24'); my $date2 = epoch('1999-06-30'); my $diff = Seconds2English->new('start' => $date2 - $date1); print "The difference is " , int $diff->in_months, " months\n"; sub epoch { my ($year, $month, $day) = split '-' , shift; return timelocal(0 , 0 , 12, $day , $month - 1, $year); } __END__ The difference is 56 months
    Of course, it is possible to change the definition of what a "month" is as well as all kinds of cool doodads. You only need to copy the module into the same directory as you are running your code.

    Cheers - L~R

Re: Time::Local - calculate months elapsed
by waswas-fng (Curate) on Feb 24, 2004 at 18:24 UTC
    Try 30.42 for the month number -- it is still not perfect but should give you a 30 year window of pretty accurate $elapsed_mons. You other options are install a date calculating module or take a peak at the source and roll your own into your script.


    -Waswas