PHP точно вычисляет ближайший возраст для данного DOB

Я пытаюсь рассчитать ближайший возраст на основе DOB, но я не могу понять, как это сделать. Я пробовал некоторые методы, которые оценивают, но этого недостаточно. Нам нужно рассчитать дни от сегодняшнего дня до следующего дня рождения, будь то в текущем году или в следующем году. а также снова рассчитать дни с сегодняшнего дня и последний день рождения, будь то в текущем году или в прошлом году.

Какие-либо предложения?


person M. of CA    schedule 28.08.2011    source источник
comment
Взгляните на этот ответ и класс DateTime. Кроме того, если вы хотите просто использовать date(), тогда strtotime() вам в помощь. .   -  person Peter Ajtai    schedule 28.08.2011
comment
@Peter Питер, это то, на что я смотрел, я просто не могу понять, как это реализовать.   -  person M. of CA    schedule 28.08.2011
comment
Да, это может быть несколько утомительно. Я попробовал ниже . -- Я думаю, что это работает и заботится о днях високосного года и обо всем, но это не очень элегантно.   -  person Peter Ajtai    schedule 28.08.2011
comment
Что, если текущее время находится точно между последним и следующим днями рождения? Какой возраст вернуть?   -  person Bailey Parker    schedule 28.08.2011
comment
@PhpMyCoder - Спросите у мамы время рождения.   -  person Peter Ajtai    schedule 28.08.2011
comment
@ Питер, я думаю, нам придется начать называть это минутой рождения, а не днем ​​​​рождения.   -  person Bailey Parker    schedule 28.08.2011


Ответы (3)


Я думаю, это то, что вы хотите .... конечно, вы могли бы просто получить возраст человека с точностью до дня и округлить его до ближайшего года в большую или меньшую сторону ... что, вероятно, я должен был сделать.

Это довольно грубая сила, поэтому я уверен, что вы можете сделать это лучше, но что он делает, так это проверяет количество дней до дня рождения в этом году, в следующем году и в прошлом году (я проверил каждый из этих трех по отдельности вместо того, чтобы вычитать из 365 , так как date() заботится о високосных годах, а я этого не хочу). Затем он вычисляет возраст по ближайшему из этих дней рождения.

Рабочий пример

<?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.";
?>

Изменить: удалены ненужные date() в расчетах $time_until.

person Peter Ajtai    schedule 28.08.2011
comment
это выводит, что вам 10 лет. это неправильно, это должно вывести 11 ваших старых. потому что этому человеку 11 лет. - person M. of CA; 28.08.2011
comment
@М. CA - Вы попробовали это до того, как я исправил опечатку. Попробуйте прямо сейчас с указанным примером ( codepad.viper-7.com/fPp2lj ) - person Peter Ajtai; 28.08.2011
comment
я думаю, что это все ... вау, вы редактировали это примерно 8 раз за последние 15 минут ... можем ли мы изменить это, чтобы мы могли указать дату вместо сегодняшнего дня. - person M. of CA; 28.08.2011
comment
@М. CA - везде, где указано time(), замените отметку времени Unix нужной даты. - также необходимо изменить strtotime('+1 год') и strtotime('-1 год'), чтобы складывать и вычитать из введенной даты. - person Peter Ajtai; 28.08.2011
comment
date() вокруг strtotime совершенно не нужен и работает по чистому совпадению. - person deceze♦; 28.08.2011

Если я правильно понимаю, вы хотите "округлить" возраст? Тогда как насчет чего-то в этом роде:

$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');
}
person deceze♦    schedule 28.08.2011
comment
это не работает. Bday '1990-09-03' дает мне 20, он должен дать мне 21, потому что этот человек ближе к своему следующему дню рождения, чем к его последнему дню рождения. это не простой раунд. особенно по месяцам, потому что дни тоже имеют значение. Как я могу считать дни до его следующего дня рождения. и как я могу считать дни до его последнего дня рождения. - person M. of CA; 28.08.2011
comment
Интересно, будет ли достаточно просто добавить 6 месяцев к дню рождения? - person maaudet; 28.08.2011
comment
@М. CA Это была опечатка в формате. С добавлением % он возвращает 21. Однако он точен только до месяца. 6 месяцев — это не обязательно 182,5 дня, поэтому они могут немного отличаться. - person deceze♦; 28.08.2011
comment
Что, если прошлогодний день рождения самый близкий? - person Peter Ajtai; 28.08.2011
comment
@Peter Ну, $diff здесь - возраст человека. Если человеку 20 лет 5 месяцев, выбираем 20. Если ему 20 лет 7 месяцев, выбираем 21. Не надо возиться с днями рождения. Я должен признать, что это только очень слабо протестировано и вполне может не делать именно то, что предполагается. :) - person deceze♦; 28.08.2011
comment
@deceze - О да, понятно. Это, кажется, путь. Получите возраст, а затем округлите его в большую или меньшую сторону. - Гораздо проще, когда вы смотрите на это так. - person Peter Ajtai; 28.08.2011

Изменить: переписано для использования DateInterval

Это должно помочь вам...

$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;
person Anthony Jack    schedule 28.08.2011