http://www.perlmonks.org?node_id=928016


in reply to Re: Happy unbirthday! (To all, with a challenge)
in thread Happy unbirthday!

Well, you put out your challenge for the newcomers, however, I could not resist trying. I have added error checking in for days, months, and years. I put a little personalization into the resulting messages. Also, I have added days until your next birthday. For the latter, there are still kinks I am still trying to work out regarding the previous two months which returns a negative number of days until the next birthday. Today is September 27, 2011. Any dates between July 28 and August 31 create the negative days until the next birthday.

So, here is the expanded code with error checking. I used the built in features of Date::Calc to do months instead of reinvention.

#!/usr/bin/perl use strict; use warnings; use Date::Calc qw(:all); use Lingua::EN::Inflect qw(ORD); sub commify { local $_ = shift; 1 while s/^([-+]?\d+)(\d{3})/$1,$2/; return $_; } sub birth_year { print "What year were you born? (YYYY) "; chomp(my $b_year = <>); # Checking for a 4 digit year. if ($b_year !~ /\d{4}/) { print "Sorry, please use the full year.\n"; $b_year = birth_year(); } return $b_year; } sub birth_month { print "What month were you born? (MM or name) "; chomp(my $b_month = <>); # This is language specific for English. if ($b_month =~ /[a-z]+/i) { $b_month = Decode_Month($b_month,1); # If the month doesn't match, it will try again. # Decode_Month had error checking in mind. if ($b_month =~ /0/) { print "Sorry, that is not a month.\n"; $b_month = birth_month(); } } return $b_month; } sub birth_day { my ($b_year,$b_month) = @_; my $month_name = Month_to_Text($b_month); print "What day were you born? (DD) "; chomp(my $b_day = <>); # Checking for 0. if (!$b_day or $b_day == 0) { print "Sorry, you did not specify a date.\n"; $b_day = birth_day($b_year,$b_month); } # Checking days for February first. elsif ($b_month =~ /^(0?[2])$/) { if ($b_year % 4 == 0 && $b_day > 29) { print "Sorry, $month_name in $b_year only had 29 days.\n"; $b_day = birth_day($b_year,$b_month); } elsif ($b_day > 28) { print "Sorry, $month_name in $b_year only had 28 days.\n"; $b_day = birth_day($b_year,$b_month); } } # Checking for the months with 31 days. elsif ($b_month =~ /^(0?[13578]|1[02])$/ && $b_day > 31) { print "Sorry, $month_name only has 31 days.\n"; $b_day = birth_day($b_year,$b_month); } # Checking for the months with 30 days. elsif ($b_month =~ /^(0?[469]|11)$/ && $b_day > 30) { print "Sorry, $month_name only has 30 days.\n"; $b_day = birth_day($b_year,$b_month); } return $b_day; } # Let's personalize it a bit. :) print "What's your name? "; chomp(my $name = <>); my $birth_year = birth_year(); my $birth_month = birth_month(); my $birth_day = birth_day($birth_year,$birth_month); my $year = (localtime)[5] + 1900; my $month = (localtime)[4] + 1; my $day = (localtime)[3]; # The following counts how many birthdays there has been. # It also figures out the next year for a birthday. # I'm still working on the kinks in the next birthday. my $birthdays; my $next_year; if ($birth_month > $month) { $birthdays = $year - $birth_year - 1; $next_year = $year; } else { if ($birth_day > $day) { $birthdays = $year - $birth_year - 1; $next_year = $year; } else { $birthdays = $year - $birth_year; $next_year = $year + 1; } } my @birth = ($birth_year,$birth_month,$birth_day); my @next_bday = ($next_year,$birth_month,$birth_day); my @today = ($year,$month,$day); my $days_alive = Delta_Days(@birth,@today); my $days_til_next_bday = Delta_Days(@today,@next_bday); my $unbirthdays = ORD(commify($days_alive - $birthdays)); print "\nHappy $unbirthdays unbirthday, $name!\n"; print "You have $days_til_next_bday days until your next birthday.\n";
Have a cookie and a very nice day!
Lady Aleena