Hi -
I noticed this thread and wanted to update the forum on a similar mod I devised a few weeks ago (with help from JPD, of course
). Turned out my code was buggy and I had to separate it into two subroutines, which I added to html.pl. I'm sure there's a more efficient way to code it, but I'm new to Perl and just glad I got it to work.
It's part of a database of membership profiles for a parents' support group, so the dates are converted to ages differently, depending on age: newborns in days or weeks, older babies in months, older kids in years/part years, etc. It allows for a freestyle text field to have dynamic ages embedded, so if the user enters "I have two boys, 20-Jan-1994 and 06-Jul-1998 old", it will be converted (today) to "I have two boys, 5 years and 15 months old".
Code:
sub html_dates_to_ages {
### Expected parameter is a text string containing birthdates.
### (Will also work for anniversaries, etc.) All patterns matching
### the date format dd-mmm-yyyy (case insensitive) will be converted to a
### current age using the results of sub html_date_to_age, which will also
### (sort of) validate the day of month. Year must be between 1900 and 2099.
my ($string) = $_[0];
my ($age) = "?";
my (@dates);
@dates = ($string =~ /\d{2}-(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(?:19|20)\d{2}/iog) ;
for $dates (@dates) {
$age = &html_date_to_age(lc($dates));
$string =~ s/$dates/$age/ ;
}
return $string;
}
######################
sub html_date_to_age {
### Expected parameter is a date in the form dd-mmm-yyyy.
### The "dd" has not been validated, other than being digits.
my ($bd_day, $bd_month, $bd_year) = split(/-/, $_[0]);
### At this point, if $bd_day is not between 1 and 31 then we'll
### return the original value $_[0] unconverted as it is not a valid date.
### NOTE: This will not catch impossible dates like 31-Feb-1990.
$bd_day = int($bd_day);
unless ($bd_day && ($bd_day <= 31)) {return $_[0];}
### Continuing...
my ($sec, $min, $hour, $day, $month, $year, $dweek, $dyear, $daylight) = localtime(time());
my ($age);
my ($units) = " day"; ### This will be changed if the child's age != 1 day.
my (%months) = ("jan" => 0, "feb" => 1, "mar" => 2, "apr" => 3, "may" => 4, "jun" => 5,
"jul" => 6, "aug" => 7, "sep" => 8, "oct" => 9, "nov" => 10,"dec" => 11);
### Convert $bd_month to a number between 1 and 12.
$bd_month = $months{$bd_month};
### Convert $bd_year to the same format as $year.
$bd_year = $bd_year - 1900;
### Now we can determine the age in days. The constants used are the
### average num of days in a year or month - close enough for this routine.
$age = int( (365.25 * ($year - $bd_year ))
+ ( 30.44 * ($month - $bd_month))
+ ($day - $bd_day) );
### No birthday party until you're born!
if ($age < 0) { return $_[0]; }
### Older than 24 months (730)?
if ($age > 730) {
$age = sprintf("%.1f",$age/365.25); # convert $age to years, round to nearest tenth.
if ($age >= 5) {$age = int($age)} # 5 or older? No need for tenths.
else { $age =~ s/\.0// } # No need for age to end with ".0"
$units = " years";
}
### Between 8 weeks and 24 months? Convert $age to nearest whole month (30.44 days)
elsif ($age > 56) {
$age = int(($age/30.44)+.5);
$units = " months";
}
### Between 2 weeks and 8 weeks? Convert $age to nearest whole week
elsif ($age >= 14) {
$age = int(($age/7)+.5);
$units = " weeks";
}
### Use correct grammar
elsif ($age != 1) { $units = " days"; }
### Return the converted string in colored text. The color indicates that it is "dynamic",
### so if someone enters an age directly (not dynamic) then viewers will be able to tell
### that it's not necessarily current. If you prefer regular text color, use...
### return ($age . $units);
return ('<FONT COLOR=navy>' . $age . $units . '</FONT>');
}
It will not work with autogenerated record displays. To apply the conversion to a field called "Children", you'd simply find "$rec{'Children'}" in sub html_record, and replace it with &html_dates_to_ages($rec{'Children'})
Another cool use for this would be something like a profile field in which someone could enter "We have been married for 25-Dec-1990 and still love each other!"
Scott
noelles@teleport.com