Just another Perl shrine PerlMonks

### Calculating a persons age based on their birthday.

by artful (Initiate)
 on May 03, 2000 at 02:49 UTC Need Help??

artful has asked for the wisdom of the Perl Monks concerning the following question:

I need to calculate someone's age based on their birthday. The birthday is being pulled from MySQL so I have the FROM_DAYS() function which will give me the number of days they have been alive. I cannot just divide by 365 because of leap years and all. Any advice on accurately calculating someone's age?
• Comment on Calculating a persons age based on their birthday.

Replies are listed 'Best First'.
Re: Calculating a persons age based on their birthday.
by cciulla (Friar) on May 03, 2000 at 03:19 UTC
Check out Date::Calc at CPAN.

The following code was shamelessly copied from Date::Calc's documentation:

```  use Date::Calc qw( Decode_Date_EU Today leap_year Delta_Days );
\$date = <STDIN>; # get birthday
(\$year1,\$month1,\$day1) = Decode_Date_EU(\$date);
(\$year2,\$month2,\$day2) = Today();
if ((\$day1 == 29) && (\$month1 == 2) && !leap_year(\$year2))
{ \$day1--; }
if ( ((\$year2 - \$year1) >  18) ||
( ((\$year2 - \$year1) == 18) &&
(Delta_Days(\$year2,\$month1,\$day1, \$year2,\$month2,\$day2) >= 0) ) )
{
print "Ok - you are over 18.\n";
}
else
{
print "Sorry - you aren't 18 yet!\n";
}
Re: Calculating a persons age based on their birthday.
by buzzcutbuddha (Chaplain) on May 03, 2000 at 15:50 UTC
IMHO a better way to tell if someone's age in years is to calc this way:
```     use integer;  # speeds up the math
my @date = localtime(time);
# convert year to months and add current number of months
my \$yearnow = (((\$date[5] + 1900) * 12) + (\$date[4] + 1));
print "Enter an 8 digit birthdate.  eg: 01/01/1970\n";
my (\$monththen, \$daythen, \$yearthen)  = split /\//, <STDIN>;
# we'll fly without error-checking now and just add what they e
+ntered for month
my \$modyearthen = ((\$yearthen * 12) + (\$monththen));
# subtract the totals and divide by 12, convert to int (redunda
+nt for safety sake)
# and voila actual number of years alive
\$numyears = int ((\$yearnow - \$modyearthen)/12);
print "You've been around \$numyears years!\n";

This way, you are also accounting for the months. For example, I was born in
August, and if you just subtract the years from each other right now, it says I'm 25,
which isn't right. You need to account for the total number of months, and then take
the integer part of the division by 12 which gives you the year and remainder. It's more
work, but it's a hair more accurate. Certainly for the sake of accuracy, you could take
it down to days...but I'll leave that to someone else! :)
RE: Calculating a persons age based on their birthday.
by Simplicus (Monk) on May 03, 2000 at 20:20 UTC
If all you want is the "year value" of a person's age, you
could divide by 365, after you added one to the number
of days for each of the leap years since the person's birth.
You could calculate this offset by subtracting their
birth year from the current year and dividing the result by
four. This works becuase they can't have been born both
before and after Feb 29th. Something like:
```
use integer;

#...code ommited; obtain \$days from FROM_DAYS()
#                 and \$birth_year from database

my \$this_year;
my @time;
my \$raw_years;
my \$num_leaps;
my \$int_years;
my \$float_years;

@time = localtime(time);
\$this_year = \$time[5] + 1900;
\$raw_years = \$this_year - \$birth_year;
\$num_leaps = \$raw_years / 4;
\$days += \$num_leaps;

\$int_years = \$days / 365;

no integer;

\$float_years = \$days / 365;

if (\$int_years == \$float_years) {
}

#...Then do whatever else you're going to do
I used a few more variable declarations than I would normally
but I wanted to clarify what I was doing. It's
quick and dirty, but probably works...
Simplicus
If you want to be slightly more accurate (not that this matters for another 100 years, but hey!) the leap year formula is that a leap year is divisable by 4, but not 100 (except if divisable by 400). Of course, the amount of error induced by leap years wouldn't effect your program unless the person was over a thousand years old (one day of error every four years would take a long time to become relevant), otherwise its safe to just div by 365.

I'm not sure how clear I was in the previous post. I was rather tired and stuff. The original question was:

I need to calculate someone's age based on their birthday. The birthday is being pulled from MySQL so I have the FROM_DAYS() function which will give me the number of days they have been alive. I cannot just divide by 365 because of leap years and all. Any advice on accurately calculating someone's age?

So I was trying to say that leap years are irrelevant. You have the birth date. So you just divide the number of days by 365. This will be off by one day every four years, meaning that their birthday will appear to creep at the rate of 6 hours a year. This shouldn't be a big deal though... it just means that their birthday will move forward a day every four years. This means that if a person enters a birth date for an age verification system, it would let them by 4 days before their 18th birthday or 5 days before their 21st. In almost any other application, the error is negligable.
Re: Calculating a persons age based on their birthday.
by btrott (Parson) on May 03, 2000 at 03:13 UTC
Well, what exactly are you looking for? Something like "I've been alive 10 years", or "I've been alive 10.6293 years"? :) Or "I've been alive 10 years, 7 months, etc."?

Take a look at Date::Calc and Date::Manip.

I was just looking for the number of years alive. So like when their birthday rolls around I can say happy birthday your 10 years old. Or hey everyone John Doe is 10 years old today.
Date::Calc (or, heaven forbid, Date::Manip) is probably overkill since you only want age in years. All you really want to know is whether the birthday has passed this year.
```sub age {
# Assuming \$birth_month is 0..11
my (\$birth_day, \$birth_month, \$birth_year) = @_;

my (\$day, \$month, \$year) = (localtime)[3..5];
\$year += 1900;

my \$age = \$year - \$birth_year;
\$age-- unless sprintf("%02d%02d", \$month, \$day)
>= sprintf("%02d%02d", \$birth_month, \$birth_day);
return \$age;
}
Of course, if you're only using this on a person's birthday, all you need to do is subtract their birth year from the current year :-)
Re: Calculating a persons age based on their birthday.
by Maqs (Deacon) on May 03, 2000 at 14:12 UTC
As far as I understand, you would like to know the number of full years the person is alive?
So, assuming you have only the number of day, we can do the following:
---
my \$year = (localtime)[5]+1900;
my \$fullyears=0;
\$nod = xxxx; #number of days goes here...
while (\$nod > 365)
{ if ( \$year % 4) {\$nod=\$nod-365} else {\$nod=\$nod-366}; #check for the leap year.
\$year--; \$fullyears++;
};

print "\$fullyears\n";
---
Rather simple but m.b. not so gracefull solution :) You see, you do not need any special modules.
Sholdn't the
```if (\$year % 4) {\$nod=\$nod-365} else {\$nod=\$nod-366}; #check for the le
+ap year.
be
```if (((\$year % 4 == 0) && (\$year % 100 != 0)) || (\$year % 400) == 0) {\$
+nod=\$nod-365} else {\$nod=\$nod-366}; #check for the leap year.
To handle Y2K (and others) correct... /t0mas
Sorry - It should be
```if (((\$year % 4 == 0) && (\$year % 100 != 0)) || (\$year % 400) == 0) {\$
+nod=\$nod-366} else {\$nod=\$nod-365}; #check for the leap year.
365 and 366 swiched places....

Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://9995]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (2)
As of 2022-07-01 23:29 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?