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