On Mon, Feb 28, 2005 at 07:43:47AM -0800, Hill, Ronald wrote:
> Sven Ingebrigt Ulland wrote:
> > For some time now, I've been trying to figure out how
> > to calculate how many days left before a given date
> > of birth, to easily keep track of my friends' birthdays.
> 
> This might get you started. (untested)
> 
> use strict;
> use warnings;
> use DateTime;
> use DateTime::Format::Strptime;
> use DateTime::Duration;
> 
> my $dt   = DateTime->today();
> my $Strp = new DateTime::Format::Strptime(
>   pattern   => '%Y-%m-%d',
>   time_zone => 'floating',
> );
> 
> my %family = ();
> 
> while (<DATA>) {
>     my ( $name, $date ) = split ();
> 
>     my $birthday = $Strp->parse_datetime($date);

So far I'm with you, but the following line,

>     my $current_birthday = $birthday->clone()->set( year => $dt->year );

..assumes that the year of birth has the same leap year properties as
this year. In practice, this will break if birthday is after 28th of
February, and:

-year of birth is a leap year, while this year is not.
-year of birth is a normal year, while this year is a leap year.

Both of the above are only valid for some "today" dates. To tell
you the truth, I tried to think about it now, but my brain has
trouble visualizing it. I might be totally wrong, or slightly
off. A flawless pseudo algorithm for this would be nice to see,
if your suggestion is indeed flawed, that is.

>     if ( $dt > $current_birthday ) {
>         $current_birthday->add( DateTime::Duration->new( years => 1 ) );
>     }

Here is a step by step example for when this approach might
fail (mostly for my understanding):

Today = 2007-03-02
DOB   = 1981-03-01 #Date of birth.

First, we set the year of birth to this year:
DOB   = 2007-03-01

Now, this date has already passed in this year, so we add a year:
DOB   = 2008-03-01

Now, when we calculate the duration from Today to DOB, it will
actually include the 29th of February since 2008 is a leap year,
and thus miss by one day. Again, I might be totally off here;
please comment.

>     $family{$name} = $current_birthday;
> 
> }
> 
> print map {
>     $_, ": ", $family{$_}->delta_days($dt)->in_units('days'),
>       " days til birthday\n";
> } sort keys %family;
> 
> __DATA__
> wife 1965-06-10
> son 1997-06-27
> daughter 1993-08-22
> 
> I hope this helps :-)

Thank you very much for the code suggestion, Ron. However,
there doesn't seem to be a really simple solution (a few
statements) to this problem, if in fact my thoughts are
correct. One of these days I'll see if I can understand
the thinking behind the problem, and set up the proper
conditional expressions needed. Am I free to use your
code?

regards,
Sven

Reply via email to