[php] PHP calculate age

I'm looking for a way to calculate the age of a person, given their DOB in the format dd/mm/yyyy.

I was using the following function which worked fine for several months until some kind of glitch caused the while loop to never end and grind the entire site to a halt. Since there are almost 100,000 DOBs going through this function several times a day, it's hard to pin down what was causing this.

Does anyone have a more reliable way of calculating the age?

//replace / with - so strtotime works
$dob = strtotime(str_replace("/","-",$birthdayDate));       
$tdate = time();

$age = 0;
while( $tdate > $dob = strtotime('+1 year', $dob))
{
    ++$age;
}
return $age;

EDIT: this function seems to work OK some of the time, but returns "40" for a DOB of 14/09/1986

return floor((time() - strtotime($birthdayDate))/31556926);

This question is related to php

The answer is


Figured I'd throw this on here since this seems to be most popular form of this question.

I ran a 100 year comparison on 3 of the most popular types of age funcs i could find for PHP and posted my results (as well as the functions) to my blog.

As you can see there, all 3 funcs preform well with just a slight difference on the 2nd function. My suggestion based on my results is to use the 3rd function unless you want to do something specific on a person's birthday, in which case the 1st function provides a simple way to do exactly that.

Found small issue with test, and another issue with 2nd method! Update coming to blog soon! For now, I'd take note, 2nd method is still most popular one I find online, and yet still the one I'm finding the most inaccuracies with!

My suggestions after my 100 year review:

If you want something more elongated so that you can include occasions like birthdays and such:

function getAge($date) { // Y-m-d format
    $now = explode("-", date('Y-m-d'));
    $dob = explode("-", $date);
    $dif = $now[0] - $dob[0];
    if ($dob[1] > $now[1]) { // birthday month has not hit this year
        $dif -= 1;
    }
    elseif ($dob[1] == $now[1]) { // birthday month is this month, check day
        if ($dob[2] > $now[2]) {
            $dif -= 1;
        }
        elseif ($dob[2] == $now[2]) { // Happy Birthday!
            $dif = $dif." Happy Birthday!";
        };
    };
    return $dif;
}

getAge('1980-02-29');

But if you just simply want to know the age and nothing more, then:

function getAge($date) { // Y-m-d format
    return intval(substr(date('Ymd') - date('Ymd', strtotime($date)), 0, -4));
}

getAge('1980-02-29');

See BLOG


A key note about the strtotime method:

Note:

Dates in the m/d/y or d-m-y formats are disambiguated by looking at the 
separator between the various components: if the separator is a slash (/), 
then the American m/d/y is assumed; whereas if the separator is a dash (-) 
or a dot (.), then the European d-m-y format is assumed. If, however, the 
year is given in a two digit format and the separator is a dash (-, the date 
string is parsed as y-m-d.

To avoid potential ambiguity, it's best to use ISO 8601 (YYYY-MM-DD) dates or 
DateTime::createFromFormat() when possible.

If you want to only get fullyears as age, there is a supersimple way on doing that. treat dates formatted as 'YYYYMMDD' as numbers and substract them. After that cancel out the MMDD part by dividing the result with 10000 and floor it down. Simple and never fails, even takes to account leapyears and your current server time ;)

Since birthdays or mostly provided by full dates on birth location and they are relevant to CURRENT LOCAL TIME (where the age check is actually done).

$now = date['Ymd'];
$birthday = '19780917'; #september 17th, 1978
$age = floor(($now-$birthday)/10000);

so if you want to check if someone is 18 or 21 or below 100 on your timezone (nevermind the origin timezone) by birthday, this is my way to do this


this is my function to calculating DOB with the specific return of age by year, month, and day

function ageDOB($y=2014,$m=12,$d=31){ /* $y = year, $m = month, $d = day */
date_default_timezone_set("Asia/Jakarta"); /* can change with others time zone */

$ageY = date("Y")-intval($y);
$ageM = date("n")-intval($m);
$ageD = date("j")-intval($d);

if ($ageD < 0){
    $ageD = $ageD += date("t");
    $ageM--;
    }
if ($ageM < 0){
    $ageM+=12;
    $ageY--;
    }
if ($ageY < 0){ $ageD = $ageM = $ageY = -1; }
return array( 'y'=>$ageY, 'm'=>$ageM, 'd'=>$ageD );
}

this how to use it

$age = ageDOB(1984,5,8); /* with my local time is 2014-07-01 */
echo sprintf("age = %d years %d months %d days",$age['y'],$age['m'],$age['d']); /* output -> age = 29 year 1 month 24 day */

$birthday_timestamp = strtotime('1988-12-10');  

// Calculates age correctly
// Just need birthday in timestamp
$age = date('md', $birthday_timestamp) > date('md') ? date('Y') - date('Y', $birthday_timestamp) - 1 : date('Y') - date('Y', $birthday_timestamp);

Ready to use function that returns full result (year, month, day, hour, min, sec). Regarding date above current date, it will return negative values that can be useful for countdown function.

/* By default,
* format is 'us'
* and delimiter is '-'
*/

function date_calculate($input_date, $format = 'us', $delimiter = '-')
{
    switch (strtolower($format)) {
        case 'us': // date in 'us' format (yyyy/mm/dd), like '1994/03/01'
            list($y, $m, $d) = explode($delimiter, $input_date);
            break;
        case 'fr': // date in 'fr' format (dd/mm/yyyy), like '01/03/1994'
            list($d, $m, $y) = explode($delimiter, $input_date);
            break;
        default: return null;
    }

    $tz          = new \DateTimeZone('UTC'); // TimeZone. Not required but can be useful. By default, server TimeZone will be returned
    $format_date = sprintf('%s-%s-%s', $y, $m, $d);
    $cur_date    = new \DateTime(null, $tz);
    $user_date   = new \DateTime($format_date, $tz);
    $interval    = $user_date->diff($cur_date);

    return [
        'year'  => $interval->format('%r%y'),
        'month' => $interval->format('%r%m'),
        'day'   => $interval->format('%r%d'),
        'hour'  => $interval->format('%r%H'),
        'min'   => $interval->format('%r%i'),
        'sec'   => $interval->format('%r%s'),
    ];
}

var_dump(date_calculate('06/09/2016', 'fr', '/'));
var_dump(date_calculate('2016-09-06'));

More++:


This function will return the age in years. Input value is a date formated (YYYY-MM-DD) day of birth string eg: 2000-01-01

It works with day - precision

function getAge($dob) {
    //calculate years of age (input string: YYYY-MM-DD)
    list($year, $month, $day) = explode("-", $dob);

    $year_diff  = date("Y") - $year;
    $month_diff = date("m") - $month;
    $day_diff   = date("d") - $day;

    // if we are any month before the birthdate: year - 1 
    // OR if we are in the month of birth but on a day 
    // before the actual birth day: year - 1
    if ( ($month_diff < 0 ) || ($month_diff === 0 && $day_diff < 0))
        $year_diff--;   

    return $year_diff;
}

Cheers, nira


I use Date/Time for this:

$age = date_diff(date_create($bdate), date_create('now'))->y;

Try any of these using DateTime object

$hours_in_day   = 24;
$minutes_in_hour= 60;
$seconds_in_mins= 60;

$birth_date     = new DateTime("1988-07-31T00:00:00");
$current_date   = new DateTime();

$diff           = $birth_date->diff($current_date);

echo $years     = $diff->y . " years " . $diff->m . " months " . $diff->d . " day(s)"; echo "<br/>";
echo $months    = ($diff->y * 12) + $diff->m . " months " . $diff->d . " day(s)"; echo "<br/>";
echo $weeks     = floor($diff->days/7) . " weeks " . $diff->d%7 . " day(s)"; echo "<br/>";
echo $days      = $diff->days . " days"; echo "<br/>";
echo $hours     = $diff->h + ($diff->days * $hours_in_day) . " hours"; echo "<br/>";
echo $mins      = $diff->h + ($diff->days * $hours_in_day * $minutes_in_hour) . " minutest"; echo "<br/>";
echo $seconds   = $diff->h + ($diff->days * $hours_in_day * $minutes_in_hour * $seconds_in_mins) . " seconds"; echo "<br/>";

Reference http://www.calculator.net/age-calculator.html


  function dob ($birthday){
    list($day,$month,$year) = explode("/",$birthday);
    $year_diff  = date("Y") - $year;
    $month_diff = date("m") - $month;
    $day_diff   = date("d") - $day;
    if ($day_diff < 0 || $month_diff < 0)
      $year_diff--;
    return $year_diff;
  }

How about launching this query and having MySQL calculating it for you:

SELECT 
username
,date_of_birth
,(PERIOD_DIFF( DATE_FORMAT(CURDATE(), '%Y%m') , DATE_FORMAT(date_of_birth, '%Y%m') )) DIV 12 AS years
,(PERIOD_DIFF( DATE_FORMAT(CURDATE(), '%Y%m') , DATE_FORMAT(date_of_birth, '%Y%m') )) MOD 12 AS months
FROM users

Result:

r2d2, 1986-12-23 00:00:00, 27 , 6 

The user has 27 years and 6 months (it counts an entire month)


Here is the process that is more simple and works both for the formats dd/mm/yyyy and dd-mm-yyyy. This is working great for me:

    <?php

       $birthday = '26/04/1994';

       $dob = strtotime(str_replace("/", "-", $birthday));
       $tdate = time();
       echo date('Y', $tdate) - date('Y', $dob);

   ?>

And if you care about your time zone just add above date_default_timezone_set("Asia/Dhaka"); change the zone with yours.


Following the first logic, you have to use = in the comparison.

<?php 
    function age($birthdate) {
        $birthdate = strtotime($birthdate);
        $now = time();
        $age = 0;
        while ($now >= ($birthdate = strtotime("+1 YEAR", $birthdate))) {
            $age++;
        }
        return $age;
    }

    // Usage:

    echo age(implode("-",array_reverse(explode("/",'14/09/1986')))); // format yyyy-mm-dd is safe!
    echo age("-10 YEARS") // without = in the comparison, will returns 9.

?>

here's the simple function to calculate age:

<?php
    function age($birthDate){
      //date in mm/dd/yyyy format; or it can be in other formats as well
      //explode the date to get month, day and year
      $birthDate = explode("/", $birthDate);
      //get age from date or birthdate
      $age = (date("md", date("U", mktime(0, 0, 0, $birthDate[0], $birthDate[1], $birthDate[2]))) > date("md")
        ? ((date("Y") - $birthDate[2]) - 1)
        : (date("Y") - $birthDate[2]));
     return $age;
    }

    ?>

    <?php
    echo age('11/05/1991');
    ?>

I have found this script reliable. It takes the date format as YYYY-mm-dd, but it could be modified for other formats pretty easily.

/*
* Get age from dob
* @param        dob      string       The dob to validate in mysql format (yyyy-mm-dd)
* @return            integer      The age in years as of the current date
*/
function getAge($dob) {
    //calculate years of age (input string: YYYY-MM-DD)
    list($year, $month, $day) = explode("-", $dob);

    $year_diff  = date("Y") - $year;
    $month_diff = date("m") - $month;
    $day_diff   = date("d") - $day;

    if ($day_diff < 0 || $month_diff < 0)
        $year_diff--;

    return $year_diff;
}

$tz  = new DateTimeZone('Europe/Brussels');
$age = DateTime::createFromFormat('d/m/Y', '12/02/1973', $tz)
     ->diff(new DateTime('now', $tz))
     ->y;

As of PHP 5.3.0 you can use the handy DateTime::createFromFormat to ensure that your date does not get mistaken for m/d/Y format and the DateInterval class (via DateTime::diff) to get the number of years between now and the target date.


If you don't need great precision, just the number of years, you could consider using the code below ...

 print floor((time() - strtotime("1971-11-20")) / (60*60*24*365));

You only need to put this into a function and replace the date "1971-11-20" with a variable.

Please note that precision of the code above is not high because of the leap years, i.e. about every 4 years the days are 366 instead of 365. The expression 60*60*24*365 calculates the number of seconds in one year - you can replace it with 31536000.

Another important thing is that because of the use of UNIX Timestamp it has both the Year 1901 and Year 2038 problem which means the the expression above will not work correctly for dates before year 1901 and after year 2038.

If you can live with the limitations mentioned above that code should work for you.


Due to leap year, it is not wise just to subtract one date from another and floor it to number of years. To calculate the age like the humans, you will need something like this:

$birthday_date = '1977-04-01';
$age = date('Y') - substr($birthday_date, 0, 4);
if (strtotime(date('Y-m-d')) - strtotime(date('Y') . substr($birthday_date, 4, 6)) < 0)
{
    $age--;
}

The following works great for me and seems to be a lot simpler than the examples that have already been given.

$dob_date = "01";
$dob_month = "01";
$dob_year = "1970";
$year = gmdate("Y");
$month = gmdate("m");
$day = gmdate("d");
$age = $year-$dob_year; // $age calculates the user's age determined by only the year
if($month < $dob_month) { // this checks if the current month is before the user's month of birth
  $age = $age-1;
} else if($month == $dob_month && $day >= $dob_date) { // this checks if the current month is the same as the user's month of birth and then checks if it is the user's birthday or if it is after it
  $age = $age;
} else if($month == $dob_month && $day < $dob_date) { //this checks if the current month is the user's month of birth and checks if it before the user's birthday
  $age = $age-1;
} else {
  $age = $age;
}

I've tested and actively use this code, it might seem a little cumbersome but it is very simple to use and edit and is quite accurate.


// Age Calculator

function getAge($dob,$condate){ 
    $birthdate = new DateTime(date("Y-m-d",  strtotime(implode('-', array_reverse(explode('/', $dob))))));
    $today= new DateTime(date("Y-m-d",  strtotime(implode('-', array_reverse(explode('/', $condate))))));           
    $age = $birthdate->diff($today)->y;

    return $age;
}

$dob='06/06/1996'; //date of Birth
$condate='07/02/16'; //Certain fix Date of Age 
echo getAge($dob,$condate);

Write a PHP script to calculate the current age of a person.

Sample date of birth : 11.4.1987

Sample Solution:

PHP Code:

<?php
$bday = new DateTime('11.4.1987'); // Your date of birth
$today = new Datetime(date('m.d.y'));
$diff = $today->diff($bday);
printf(' Your age : %d years, %d month, %d days', $diff->y, $diff->m, $diff->d);
printf("\n");
?>

Sample Output:

Your age : 30 years, 3 month, 0 days


Simple method for calculating Age from dob:

$_age = floor((time() - strtotime('1986-09-16')) / 31556926);

31556926 is the number of seconds in a year.


i18n :

function getAge($birthdate, $pattern = 'eu')
{
    $patterns = array(
        'eu'    => 'd/m/Y',
        'mysql' => 'Y-m-d',
        'us'    => 'm/d/Y',
    );

    $now      = new DateTime();
    $in       = DateTime::createFromFormat($patterns[$pattern], $birthdate);
    $interval = $now->diff($in);
    return $interval->y;
}

// Usage
echo getAge('05/29/1984', 'us');
// return 28

I did it like this.

$geboortedatum = 1980-01-30 00:00:00;
echo leeftijd($geboortedatum) 

function leeftijd($geboortedatum) {
    $leeftijd = date('Y')-date('Y', strtotime($geboortedatum));
    if (date('m')<date('m', strtotime($geboortedatum)))
        $leeftijd = $leeftijd-1;
    elseif (date('m')==date('m', strtotime($geboortedatum)))
       if (date('d')<date('d', strtotime($geboortedatum)))
           $leeftijd = $leeftijd-1;
    return $leeftijd;
}

I use the following method to calculate age:

$oDateNow = new DateTime();
$oDateBirth = new DateTime($sDateBirth);

// New interval
$oDateIntervall = $oDateNow->diff($oDateBirth);

// Output
echo $oDateIntervall->y;

This function works fine. It's a slight imporvement of the code of Parkyprg

function age($birthday){
 list($day,$month,$year) = explode("/",$birthday);
 $year_diff  = date("Y") - $year;
 $month_diff = date("m") - $month;
 $day_diff   = date("d") - $day;
 if ($day_diff < 0 && $month_diff==0){$year_diff--;}
 if ($day_diff < 0 && $month_diff < 0){$year_diff--;}
 return $year_diff;
}

Try this :

<?php
  $birth_date = strtotime("1988-03-22");
  $now = time();
  $age = $now-$birth_date;
  $a = $age/60/60/24/365.25;
  echo floor($a);
?>

If you want to caculate the Age of using the dob, you can also use this function. It uses the DateTime object.

function calcutateAge($dob){

        $dob = date("Y-m-d",strtotime($dob));

        $dobObject = new DateTime($dob);
        $nowObject = new DateTime();

        $diff = $dobObject->diff($nowObject);

        return $diff->y;

}

//replace / with - so strtotime works
$dob = strtotime(str_replace("/","-",$birthdayDate));       
$tdate = time();
return date('Y', $tdate) - date('Y', $dob);

Looking over the provided solutions I'm always think about drawbacks of modern education in IT field. Most of the developers are forgetting that even modern CPU's suffer from executing conditional operators, while arithmetics operations, especially with powers of 2 are faster. So on the purpose I'm showing this solution in PHP thread without any optimizations:

  list($year,$month,$day) = explode("-",$birthday);
  $age=floor(((date("Y")-$year)*512+(date("m")-$month)*32+date("d")-$day)/512);

In other languages which have strict type definitions and capable replacing * and / by shifts, this formula will "fly". Also changing divisor you can calculate age in months, weeks &etc. Be carefull, the order of operands in differences is essential


You can use the Carbon library, which is an API extension for DateTime.

You can:

function calculate_age($date) {
    $date = new \Carbon\Carbon($date);
    return (int) $date->diffInYears();
}

or:

$age = (new \Carbon\Carbon($date))->age;

If you can't seem to use some of the newer functions, here's something I whipped up. Probably more than you need, and I'm sure there are better ways, but it's easy to read, so it should do the job:

function get_age($date, $units='years')
{
    $modifier = date('n') - date('n', strtotime($date)) ? 1 : (date('j') - date('j', strtotime($date)) ? 1 : 0);
    $seconds = (time()-strtotime($date));
    $years = (date('Y')-date('Y', strtotime($date))-$modifier);
    switch($units)
    {
        case 'seconds':
            return $seconds;
        case 'minutes':
            return round($seconds/60);
        case 'hours':
            return round($seconds/60/60);
        case 'days':
            return round($seconds/60/60/24);
        case 'months':
            return ($years*12+date('n'));
        case 'decades':
            return ($years/10);
        case 'centuries':
            return ($years/100);
        case 'years':
        default:
            return $years;
    }
}

Example Use:

echo 'I am '.get_age('September 19th, 1984', 'days').' days old';

Hope this helps.


It is a problem when you use strtotime with DD/MM/YYYY. You cant use that format. Instead of it you can use MM/DD/YYYY (or many others like YYYYMMDD or YYYY-MM-DD) and it should work properly.


I find this works and is simple.

Subtract from 1970 because strtotime calculates time from 1970-01-01 (http://php.net/manual/en/function.strtotime.php)

function getAge($date) {
    return intval(date('Y', time() - strtotime($date))) - 1970;
}

Results:

Current Time: 2015-10-22 10:04:23

getAge('2005-10-22') // => 10
getAge('1997-10-22 10:06:52') // one 1s before  => 17
getAge('1997-10-22 10:06:50') // one 1s after => 18
getAge('1985-02-04') // => 30
getAge('1920-02-29') // => 95

The top answer for this is OK but only calualtes the year a person was born, I tweaked it for my own purposes to work out the day and month. But thought it was worth sharing.

This works by taken a timestamp of the the users DOB, but feel free to change that

$birthDate = date('d-m-Y',$usersDOBtimestamp);
$currentDate = date('d-m-Y', time());
//explode the date to get month, day and year
$birthDate = explode("-", $birthDate);
$currentDate = explode("-", $currentDate);
$birthDate[0] = ltrim($birthDate[0],'0');
$currentDate[0] = ltrim($currentDate[0],'0');
//that gets a rough age
$age = $currentDate[2] - $birthDate[2];
//check if month has passed
if($birthDate[1] > $currentDate[1]){
      //user birthday has not passed
      $age = $age - 1;
} else if($birthDate[1] == $currentDate[1]){ 
      //check if birthday is in current month
      if($birthDate[0] > $currentDate[0]){
            $age - 1;
      }


}
   echo $age;

 $date = new DateTime($bithdayDate);
 $now = new DateTime();
 $interval = $now->diff($date);
 return $interval->y;