strtotime不计算时间差,仅转换字符串为时间戳;直接相减再除86400易因时区、夏令时等出错;正确做法是用DateTime::diff获取DateInterval对象。

strtotime 计算时间差容易出错的根本原因
strtotime 本身不计算时间差,它只把字符串转成时间戳(int)。很多人误以为 strtotime('2025-03-10') - strtotime('2025-03-01') 就是“9天”,但结果其实是秒数(777600),直接除以 86400 才得天数——而这个过程在时区切换、夏令时、闰秒等场景下会悄悄出错。
正确用法:先转时间戳,再用 date_diff 或手动换算
PHP 7.0+ 推荐用 DateTime 对象配合 diff() 方法,避免手动算秒数。如果必须用 strtotime,只用于生成时间戳,后续逻辑交给 DateInterval 处理:
$start = new DateTime('@' . strtotime('2025-03-01'));
$end = new DateTime('@' . strtotime('2025-03-10'));
$diff = $start->diff($end);
echo $diff->days; // 输出 9-
strtotime的返回值必须传给DateTime构造函数时加@前缀,否则会被当作本地时区时间解析 - 不要对
strtotime结果直接相减后除 86400——跨月/跨年时可能因 DST 导致偏差(比如某天只有 23 小时) - 若输入含时间(如
'2025-03-01 14:30'),确保时区一致,否则diff()会按实际秒差计算,不是“日历天数”
strtotime 参数陷阱:相对时间表达不等于绝对时间差
strtotime('+7 days', $timestamp) 是“从某时刻起加 7 天”,不是“计算和现在相差 7 天”。它受当前时区、DST 影响,且不能反向推导差值:
-
strtotime('+1 month')不等于加 30 天,而是“下个月同日”,遇到 1 月 31 日 → 2 月 28 日(非闰年) -
strtotime('last day of next month')这类表达式很易读,但无法用它反推出两个日期的间隔天数 - 若需“N 天后”的时间戳,用
strtotime("+{$n} days", $base_ts)安全;若需“差多少天”,必须用DateTime::diff
性能与兼容性提醒
频繁调用 strtotime 解析相同格式字符串(如循环中解析 'Y-m-d')效率低。可提前缓存或改用 DateTime::createFromFormat:
立即学习“PHP免费学习笔记(深入)”;
$date = DateTime::createFromFormat('Y-m-d', '2025-03-01');-
strtotime在 PHP 8.2+ 已标记为“soft deprecated”,虽未移除,但官方建议优先用DateTime系列 - 中文语义如
'三天后'或'下周一'在部分 locale 下不可靠,建议统一用英文关键词('next Monday') - 如果只是比较大小(如判断是否过期),直接比时间戳最快:
$now > strtotime($expire_str),但别拿它算“差几天”
真正需要“时间差”的地方,DateTime::diff 返回的 DateInterval 对象才是唯一可靠来源;strtotime 只该出现在初始化阶段,不该参与差值逻辑。











