3

I am trying to calculate the nearest Age based on DOB, but i cant wrap my head around how to do it. I have tried some methods which estimates but this is not good enough. We need to calculate the days from today and the next birthday, whether it is in the current year or next year. and also calculate the days from today and the last birthday again whether it is in the current year or last year.

Any suggestions?

hakre
  • 193,403
  • 52
  • 435
  • 836
M. of CA
  • 1,496
  • 2
  • 22
  • 32
  • Take a look at [this answer](http://stackoverflow.com/questions/676824/how-to-calculate-the-difference-between-two-dates-using-php/3923228#3923228) and the [DateTime class](http://php.net/manual/en/book.datetime.php). Also, if you want to just use `date()` then [strtotime()](http://php.net/manual/en/function.strtotime.php) is your friend. – Peter Ajtai Aug 28 '11 at 01:11
  • @Peter ya this is what i have looked at, i just cant figure out how to implement it. – M. of CA Aug 28 '11 at 01:24
  • Yeah, it might be somewhat tedious. I [gave it a shot](http://stackoverflow.com/questions/7218388/php-accurately-calculate-nearest-age-for-a-given-dob/7218594#7218594) below. -- I think it works and takes care of leap year days and everything, but it's not very elegant. – Peter Ajtai Aug 28 '11 at 02:13
  • What if the current time is exactly between the last and next birthdays? Which age should be returned? – Bailey Parker Aug 28 '11 at 02:24
  • 1
    @PhpMyCoder - Ask the mom for the time of birth. – Peter Ajtai Aug 28 '11 at 02:29
  • @Peter I guess we'll have to start calling it a birthminute instead of a birthday. – Bailey Parker Aug 28 '11 at 02:53

3 Answers3

1

If I understand correctly you want to "round" the age? Then how about something along these lines:

$dob = new DateTime($birthday);
$diff = $dob->diff(new DateTime);

if ($diff->format('%m') > 6) {
    echo 'Age: ' . ($diff->format('%y') + 1);
} else {
    echo 'Age: ' . $diff->format('%y');
}
deceze
  • 510,633
  • 85
  • 743
  • 889
  • this doesnt work. Bday '1990-09-03' gives me "20" it should give me 21 because this person is closer to his next birthday then his last birthday. its not a simple round. specially by month, because days matter too. How can i count the days to his next birthday. and how can i count the days to his last birthday. – M. of CA Aug 28 '11 at 01:23
  • I wonder if simply adding 6 months to the birthday would be enough. – maaudet Aug 28 '11 at 01:33
  • @M. of CA It was a typo in the format. With added `%` it returns 21. It's only "accurate" to the month though. 6 months aren't necessarily 182.5 days, so it may be slightly off. – deceze Aug 28 '11 at 01:44
  • What if last year's birthday is the closest? – Peter Ajtai Aug 28 '11 at 02:19
  • @Peter Well, the `$diff` here is the age of the person. If the person is 20 years, 5 months old, we choose "20". If he's 20 years, 7 months old, we choose "21". No need to tinker with birthdays. I have to admit this is only very lightly tested though and may well not do exactly what it's supposed to. :) – deceze Aug 28 '11 at 02:24
  • @deceze - Oh yes, I see. This seems to be the way to go. Get the age, and then round it up or down. - Much simpler when you look at it like that. – Peter Ajtai Aug 28 '11 at 02:27
1

I think this is what you want.... of course, you could just get a persons age accurate to the day and round it up or down to the closest year..... which is probably what I should have done.

It's quite brute force, so I'm sure you can do it better, but what it does is check the number of days until this year's, next year's, and last year's birthday (I checked each of those three separately instead of subtracting from 365, since date() takes care of leap years, and I don't want to). Then it calculates age from whichever one of those birthdays is closest.

Working example

<?php
$bday = "September 3, 1990";
// Output is 21 on 2011-08-27 for 1990-09-03

// Check the times until this, next, and last year's bdays
$time_until = strtotime(date('M j', strtotime($bday))) - time();
$this_year = abs($time_until);

$time_until = strtotime(date('M j', strtotime($bday)).' +1 year') - time();
$next_year = abs($time_until);

$time_until = strtotime(date('M j', strtotime($bday)).' -1 year') - time();
$last_year = abs($time_until);

$years = array($this_year, $next_year, $last_year);

// Calculate age based on closest bday
if (min($years) == $this_year) {
    $age = date('Y', time()) - date('Y', strtotime($bday));
}
if (min($years) == $next_year) {
    $age = date('Y', strtotime('+1 year')) - date('Y', strtotime($bday));
}
if (min($years) == $last_year) {
    $age = date('Y', strtotime('-1 year')) - date('Y', strtotime($bday));
}

echo "You are $age years old.";
?>

Edit: Removed unnecessary date()s in the $time_until calcs.

Peter Ajtai
  • 56,972
  • 13
  • 121
  • 140
  • this outputs you are 10 years old. this is not correct, this should output 11 yours old. becuase this person is 11 years old. – M. of CA Aug 28 '11 at 02:08
  • @M. of CA - You tried it before I fixed a typo. Try it now with the example listed ( http://codepad.viper-7.com/fPp2lj ) – Peter Ajtai Aug 28 '11 at 02:21
  • i think this is it... wow u edited this like 8 times in the last 15 min... can how we modify this so we can supply a date instead of today. – M. of CA Aug 28 '11 at 02:33
  • @M. of CA - wherever it says `time()` replace with the Unix timestamp of the date you want. - also the strtotime('+1 year') and strtotime('-1 year') have to be modified to add and subtract from the inputed date. – Peter Ajtai Aug 28 '11 at 02:46
  • 1
    `date()` around `strtotime` is entirely unnecessary and just happens to work through pure coincidence. – deceze Aug 28 '11 at 03:51
0

Edit: rewrote to use DateInterval

This should do the trick for you...

$birthday = new DateTime('1990-09-03');
$today = new DateTime();
$diff = $birthday->diff($today, TRUE);
$age = $diff->format('%Y');
$next_birthday = $birthday->modify('+'. $age + 1 . ' years');
$halfway_to_bday = $next_birthday->sub(DateInterval::createFromDateString('182 days 12 hours'));

if($today >= $halfway_to_bday)
{
    $age++;
}

echo $age;
Anthony Jack
  • 5,333
  • 7
  • 28
  • 47