php时间怎么计算_strtotime函数计算时间差的应用【方法】

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

$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 只该出现在初始化阶段,不该参与差值逻辑。