
用 DateTime 和 diff() 算年龄最可靠
PHP 原生不提供“直接算年龄”的函数,date_diff() 或对象的 diff() 方法是唯一推荐路径。用 strtotime() 手动减秒数再除以 86400 是错的——闰年、夏令时、月份天数不均都会导致偏差。
实操建议:
- 始终用
DateTime对象初始化出生日期和当前日期,避免字符串隐式转换出错 - 调用
diff()得到DateInterval,它自带y、m、d属性,精确到天级无歧义 - 别依赖
DateInterval::format('%a')获取总天数——它返回的是绝对天数差,不反映“活了多少年月日”,和用户认知的“年龄”不是一回事
$born = new DateTime('2000-03-15');
$now = new DateTime();
$diff = $born->diff($now);
echo $diff->y . '岁' . $diff->m . '个月' . $diff->d . '天'; // 24岁3个月12天(示例)注意 DateTime 构造时的时区陷阱
如果出生日期没带时区,而当前 DateTime() 使用了默认时区(比如 Asia/Shanghai),跨时区比较可能让结果偏移一天——尤其在生日当天凌晨或跨午夜时刻。
常见错误现象:用户填 “1995-01-01”,程序算出来是 “29岁0个月-1天” 或 “28岁11个月30天”。
立即学习“PHP免费学习笔记(深入)”;
实操建议:
- 统一用 UTC 初始化两个时间点:
new DateTime('1995-01-01', new DateTimeZone('UTC')) - 或者显式指定相同本地时区,比如都用
new DateTimeZone('Asia/Shanghai') - 避免直接传入无时区字符串后不做处理就调
diff()
需要纯天数差?用 getTimestamp() 要小心精度
如果业务只要“从出生到今天一共多少天”,不用分年月日,那 getTimestamp() 相减再除 86400 看似简单,但有坑。
性能 / 兼容性影响:PHP 7.1+ 的 DateInterval 支持 %a 格式符,比时间戳法更准;PHP 5.6 及更早版本中,getTimestamp() 在 Windows 下对早于 1970 年的日期会返回 false。
实操建议:
- 优先走
$born->diff($now)->days(PHP 5.3+),它内部已处理闰秒与日历边界 - 若必须用时间戳,确保两个
DateTime对象在同一时区,且出生日期不早于 Unix epoch(1970-01-01) - 别用
floor((time() - strtotime($birth)) / 86400)——strtotime()解析模糊字符串极不可靠
前端传来的日期格式不一致怎么办
用户输入可能是 “2000/03/15”、“2000-3-15”、“15/03/2000”,DateTime 默认解析规则有限,容易失败或误判。
使用场景:表单提交、API 接收、CSV 导入。
实操建议:
- 先用正则或
str_replace()统一成YYYY-MM-DD格式再构造DateTime - 用
DateTime::createFromFormat()指定格式,比如DateTime::createFromFormat('d/m/Y', $input),失败时检查DateTime::getLastErrors() - 永远验证构造结果:
if (!$dt instanceof DateTime) { /* 处理错误 */ }
实际用下来,最难的不是写代码,是说服产品接受“年龄不能简单用两个日期相减得出”——尤其是当用户生日刚好在 2 月 29 日,而今年不是闰年时,diff() 返回的 d 是 0 还是 1,取决于你把“今年生日”算在哪天。这个逻辑得提前跟业务方对齐。











