最可靠方法是用datetime::diff()获取dateinterval对象并取$interval->y。需用datetime::createfromformat()安全解析各种生日格式,避免strtotime()和时间戳相减等错误方式。

PHP用DateTime类计算年龄最可靠
直接用时间戳相减再除以365会出错——闰年、月份天数不均、时区偏移都会让结果偏差1岁。PHP内置的DateTime和DateInterval才是正确解法,它按日历逻辑逐级计算年、月、日差值。
核心思路:构造两个DateTime对象(出生日期和当前时间),调用diff()得到DateInterval,取$interval->y即整岁数。
注意:不要用strtotime()转成时间戳再算,尤其对1970年前或2038年后日期会失败;也不要手动解析字符串拼年份。
$birth = new DateTime('2000-03-15');
$now = new DateTime();
$interval = $birth->diff($now);
echo $interval->y; // 输出:24(截至2024年)
处理DateTime构造失败的边界情况
用户输入的生日格式五花八门:"15/03/2000"、"2000.3.15"、甚至"2000年3月15日"。PHP默认只认ISO格式(Y-m-d)或英文格式("15 March 2000"),其他会返回false。
- 先用
DateTime::createFromFormat()指定格式解析,比new DateTime()更可控 - 检查返回值是否为
false,避免后续调用diff()报致命错误 - 对模糊输入(如只有年份
"1995"),补全为当年1月1日,否则diff()可能抛异常
$input = '15/03/2000';
$birth = DateTime::createFromFormat('d/m/Y', $input);
if (!$birth || !$birth->format('d/m/Y')) {
throw new InvalidArgumentException('生日格式不合法');
}
$age = $birth->diff(new DateTime())->y;
为什么不用date_diff()函数?
date_diff()只是DateTime::diff()的函数式封装,行为完全一致,但可读性和链式调用不如面向对象写法。真正要避开的是这些常见错误写法:
-
(time() - strtotime($birth)) / (365 * 24 * 3600)→ 忽略闰年,误差可达1~2天,累积后可能差1岁 -
date('Y') - date('Y', strtotime($birth))→ 没考虑生日是否已过,1月出生的人到12月就多算1岁 - 用
strftime()或date('z')算天数差再除 → 同样受闰年干扰,且不处理跨月逻辑
所有这些都绕开了日历语义,而DateTime::diff()内部做了完整的日历运算,包括2月29日、大小月、时区转换等。
需要精确到月或判断是否满周岁时怎么处理
仅看$interval->y不够——比如今天是2024-03-14,出生日是2000-03-15,$interval->y是23,但严格说还没满24周岁。这时得结合$interval->m和$interval->d判断:
- 如果
$interval->m > 0或$interval->d > 0,说明还没到生日,周岁 =$interval->y - 如果
$interval->m === 0 && $interval->d === 0,刚好满$interval->y周岁 - 要算“虚岁”,才在
$interval->y基础上+1(中国部分场景用,但无国际标准)
别硬编码加减,DateInterval对象里的字段就是为此设计的,直接用。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











