Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Re: perl basic count days between two dates

by marinersk (Priest)
on Oct 02, 2013 at 19:43 UTC ( [id://1056671]=note: print w/replies, xml ) Need Help??


in reply to perl basic count days between two dates

There are modules that will do this for you. I acknowledge you indicate you do not wish to use a module.

So the first step is to figure out the algorithm you wish to use. Grab pencil and paper (or a whiteboard for you youngins), and start trying to figure out how you would do the math by hand.

Then try to write code that would do the same thing you did by hand.

The number of things you are likely to overlook or get wrong are controllable in this example, but high enough to reward your use of a Module where someone else (or several someone elses) took the time to iron out the bugs for you.

But if you just gotta write the code yourself, Step 1 is to figure out how to do it by hand.

P.S. I would suggest researching Leap Year Rules. Assuming your needs do not extend to earlier than Friday, October 15, 1582 in Catholic countries, 1698 or 1752 in principalities headed by Protestants, or 1918 in Russia, a shortcut to use only the modern computation should suffice.

In that computation, the base assumption is that every year has 365 days unless it is declared to be a leap year, in which case it has 366.

More specifically, February would have 29 days rather than the hard-coded 28 you presume in your code.

Research the Leap Year Rules, and you should be able to devise a subroutine which can determine if any given year is a leap year.

From there, you should have all the tools you need to compute number of days between dates, given sufficient forethought to the construction of either your computational algorithms, or your foreach loops -- or some combination thereof.

Update: Okay, fine, here's one example of the many things a module could do for you that you would have to grind through to do by hand:

sub isLeapyear { my ($year, @extraStuff) = @_; if (!defined $year) { $year = 0; } my $leapYearFlag = 0; # Assume not a leap year until proven + otherwise. if ($year % 4) { # Not divisible by 4. Cannot be a leap year. $leapYearFlag = 0; } else { # Divisible by 4. Possibly a leap year. if ($year % 100) { # Is not divisible by 100. It is a leap year. $leapYearFlag = 1; } else { # Is divisible by 100. May not be a leap year. if ($year % 400) { # Is not divisible by 400. Cannot be a leap year. $leapYearFlag = 0; } else { # Is divisible by 400. IS a leap year. $leapYearFlag = 1; } } } return $leapYearFlag; }

Replies are listed 'Best First'.
Re^2: perl basic count days between two dates
by talexb (Chancellor) on Oct 03, 2013 at 21:04 UTC

    There's always more than one way to do it .. I like to switch things around and test for the least likely outcome first .. check to see if the year is divisible by 400, then 100, and finally 4. I think it also makes the code a little more transparent, but everyone's got their own style ..

    #!/usr/bin/perl use strict; use warnings; my %testData = ( 1900 => 0, 1904 => 1, 1972 => 1, 1973 => 0, 1999 => 0, 2000 => 1, 2001 => 0, 2004 => 1 ); { foreach my $this ( keys %testData ) { if ( $testData{$this} == leapYear($this) ) { print "Correct - $this year " . ( $testData{$this} ? "is" : "is not" ) . " a leap year.\n"; } else { print "Error with $this entry ..\n"; } } } sub leapYear { my $year = shift; if ( $year % 400 ) { if ( $year % 100 ) { # 3. Simple case: it's a leap year if it's divisible by 4 return ( $year % 4 ) ? 0 : 1; } else { # 2. If it's divisible by 100: it's not a leap year. return 0; } } else { # 1. If it's divisible by 400: it's a leap year. return 1; } }

    I've numbered the comments to make it a little clearer which result might be returned first, although this could be made even clearer by reversing the meaning of the conditionals so that the routine looks like this:

    sub leapYear { my $year = shift; if ( $year % 400 == 0 ) { # 1. If it's divisible by 400: it's a leap year. return 1; } else { if ( $year % 100 == 0 ) { # 2. If it's divisible by 100: it's not a leap year. return 0; } else { # 3. Simple case: it's a leap year if it's divisible by 4 return ( $year % 4 ) ? 0 : 1; } } }

    Alex / talexb / Toronto

    Thanks PJ. We owe you so much. Groklaw -- RIP -- 2003 to 2013.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (6)
As of 2024-04-23 13:57 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found