How can I calculate the age of a person in year, month, days?

I want to calculate the age of a person given the date of birth and the current date in years, months and days relative to the current date.

For example:

>>> calculate_age(2008, 01, 01)
1 years, 0 months, 16 days

Any pointer to an algorithm that does that will be appreciated.


First, note the assumption that if, for example, you were born on February 1st then on the following March 1st, you are exactly 1 month old, even though your age in days is only 28 -- less than the length of an average month. Years also have variable length (due to leap years) which means your age on your birthday is usually not an exact integer number of years. If you want to express the exact amount of time you've been alive in years/months/days, see my other answer. But more likely you want to fudge it just right so that being born on February 1st means that every February 1st you are X years, 0 months, and 0 days old, and on the 1st of any month you are X years, Y months, and 0 days.

In that case, read on. (NB: the following only works for dates in the past.)

Given a date of birth, (y,m,d), the current date, (ynow,mnow,dnow), and a function tm() that gives unix/epoch time for a given date, the following will output a 3-element list giving age as {years, months, days}:

t0 = y*12 + m - 1;        # total months for birthdate.
t = ynow*12 + mnow - 1;   # total months for Now.
dm = t - t0;              # delta months.    
if(dnow >= d) return [floor(dm/12), mod(dm,12), dnow-d];
dm--; t--;
return [floor(dm/12), mod(dm,12), 
        (tm({ynow,mnow,dnow}) - tm({floor(t/12), mod(t,12)+1, d}))/60/60/24];

Following is an equivalent algorithm if you don't like all the floors and mods. But I think the above is better. For one thing it avoids calling tm() when it doesn't need to.

{yl, ml} = {ynow, mnow};
if(mnow < m || mnow == m && dnow < d) yl--;
if(dnow < d) ml--;
years = yl - y;
months = ml + 12*(ynow - yl) - m;
yl = ynow;
if(ml == 0) { ml = 12; yl--; }
days = (tm({ynow, mnow, dnow}) - tm({yl, ml, d}))/60/60/24;
return [years, months, days];

That is not an easy question, since above days (if we don't take into account leap-seconds) there are not easy formulas.

Months can consist of 28, 29, 30, or 31 days; years can be 365 or 366 days. Therefore, problems arise when you try to calculate full units of time for months and years.

Here is an interesting article that takes into account all the complex aspects to solve your question in Java.


Others here have the right idea - you simply need be able to extend it to other languages. Many computer systems count time in seconds from a specific point (the "epoch" or "reference date") and figure out the date from there, as well as offering methods to convert from seconds to dates. You should be able to get the current time in seconds, convert the birth date to seconds from the epoch, subtract the two values, then divide that by the number of seconds in a day:

int timenow = time(0);
struct tm birthday = { tm_mday = 16 , .tm_mon = 1 , .tm_year = 1963 };
int timebirth = mktime( &birthday_tm );
int diff_sec = timenow - timebirth;
int days = diff_sec / ( 24 * 60 * 60);
printf("%d - %d = %d seconds, or %d days\n", timenow, timebirth, diff_sec, days);

The bug in this particular code is that mktime() can't deal with dates before the epoch, which is Jan 1 1970 in Unix based systems. Similar issues will exist on other systems depending on how they count time. The general algorithm should work, you just have to know your limits on specific systems.