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

Fellow Monks -- I am in need of a subroutine that calculates days since 1900. I saw the sub in Date::Manip, however, that is only since 1970.
Your help us greatly apreciated.
Thanks.
  • Comment on subroutine for calculating day since 1900 needed

Replies are listed 'Best First'.
Re: subroutine for calculating day since 1900 needed
by ikegami (Patriarch) on May 12, 2006 at 17:03 UTC
    sub days_since_1900 { use integer; my ($d, $m, $y) = @_; # $d: 1-based Day of the month (1..31) # $m: 0-based Month (Jan=0..Dec=11) # $y: 2 or 4 digit year $y += 1900 if $y < 1000; my $i = ($m + 10) % 12; my $j = $y - $i/10; return $d + 365*$j + $j/4 - $j/100 + $j/400 + ($i*306 + 5)/10 - 693 +902; }

    Based on Time::Local's internals.

    Update: Fixed a misnamed variable. Thanks liverpole.
    Update: Added missing - 693902. Thanks rodion. Where was my head when I posted this?!

      Oops, you need to subtract 693902 in the return line to make it return days since Jan 1 1900. In case it's of interest, the formula is valid back to 1752 for most parts of the world, and back to 1582 for most places outside of British control. Differences have to do with when people switched to the gregorian calendar. (Some still haven't.)
      Awesome, best routine I have found on this subject. Works perfectly! THANKS!
Re: subroutine for calculating day since 1900 needed
by dragonchild (Archbishop) on May 12, 2006 at 17:02 UTC
    DateTime and Date::Calc are both good solutions.

    Alternately, you could just precalculate the number of days in each year into an array (with 1900 in index 0, 1901 in index 1), then convert the month/day into number of days since Jan 1st of the current year. Of course, that assumes you know how to calculate the number of days in a year. You do know how to do that, right?


    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
Re: subroutine for calculating day since 1900 needed
by jmcnamara (Monsignor) on May 13, 2006 at 00:28 UTC

    Here is one way using Date::Calc, but there are a lot of other modules you could use as well. This assumes that the epoch is 0/0/1900 as opposed to 1/1/1900 but either way it is easy to change.
    #!/usr/bin/perl -wl use strict; use Date::Calc 'Delta_Days'; print days_since_1900(1900, 1, 1); print days_since_1900(2006, 5, 13); sub days_since_1900 { my $years = $_[0]; my $months = $_[1] || 1; my $days = $_[2] || 1; my @date = ($years, $months, $days); my @epoch = (1900, 1, 1, ); my ($days_since_1900) = Delta_Days(@epoch, @date); return 1 + $days_since_1900; }

    --
    John.

Re: subroutine for calculating day since 1900 needed
by MonkE (Hermit) on May 12, 2006 at 20:18 UTC
    I feel I should point out that leap years occur according to the following rule:

    The year must be divisible by 4, but not by 100. However the divisible-by-100 rule doesn't apply if the year is also divisible by 400.

    So the year 2000 was a leap year, but 1900 was not -- the year 1900 had 365 days. I recommend Wikipedia's Gregorian Calendar article if you want to know more about the Gregorian calendar system.
Re: subroutine for calculating day since 1900 needed
by liverpole (Monsignor) on May 12, 2006 at 17:01 UTC
    That should be fairly easy, since there are always going to be 365 or 366 days in any year between 1900 and the present.  Besides which, the algorithms for calculating whether a year is a leap year or not is trivial.

    Have you thought about just writing your own subroutine to do it?


    s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
      You have to keep in mind that 2000 was a non leap year leap year to account for the 4 century drift as the year is 365.24 and the leap years system drifts .1 every leap year so every 4 centuries you skip a leap year. Except if it is divisible by 4. http://tf.nist.gov/general/leaps.htm
      "No matter where you go, there you are." BB
        Sorry that 2000 was a leap year not a non leap year
        "No matter where you go, there you are." BB