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