最直接的方法是用 strtotime() 将时间字符串转为 unix 时间戳后相减;若时间来源不可控或涉及时区,应改用 datetime 类并显式指定时区。

用 strtotime() 转时间字符串再相减最直接
PHP 里没有专门的“秒数差”函数,但最常用、最稳妥的方式就是把两个时间转成 Unix 时间戳(即从 1970-01-01 开始的秒数),然后直接相减。前提是两个时间都能被 strtotime() 正确解析。
比如计算 "2024-05-20 14:30:00" 和 "2024-05-20 12:00:00" 的秒数差:
$t1 = strtotime("2024-05-20 14:30:00");
$t2 = strtotime("2024-05-20 12:00:00");
$seconds = $t1 - $t2; // 结果是 9000
- 结果恒为整数,单位是秒;若
$t1更早,结果为负 -
strtotime()支持常见格式:Y-m-d H:i:s、Y/m/d、d M Y 等,也支持相对时间如"+1 day" - 如果输入格式不标准(比如
"20-05-2024"或含中文),strtotime()可能返回false,相减后变成-1,务必检查返回值
用 DateTime 类更可靠,尤其处理时区或异常格式
当时间来自用户输入、数据库字段,或涉及不同时区时,DateTime 比 strtotime() 更可控。它能明确指定时区,也能在解析失败时抛出异常而非静默返回 false。
示例(默认使用当前时区):
$dt1 = new DateTime("2024-05-20 14:30:00");
$dt2 = new DateTime("2024-05-20 12:00:00");
$seconds = $dt1->getTimestamp() - $dt2->getTimestamp();
- 推荐显式传入时区,避免服务器默认时区干扰:
new DateTime("...", new DateTimeZone("Asia/Shanghai")) - 若时间格式非法(如
"2024-13-01"),DateTime构造会抛出Exception,需用try/catch捕获 - 不要用
$dt1->diff($dt2)->s—— 它只返回“秒部分”(0–59),不是总秒数;要用->format('%a') * 86400 + ...太绕,没必要
注意 microtime(true) 不适合算历史时间间隔
有人看到 microtime(true) 返回浮点秒数,就误以为它能算任意两个时间点的差。但它只适用于“当前运行中”的计时场景,比如测某段代码执行耗时。
- 它返回的是当前时刻的高精度时间戳(含微秒),不能反向解析字符串时间
- 拿它和
strtotime()结果相减,数值上虽可得秒数,但语义混乱、易误导,且丢失时区信息 - 真正需要毫秒级精度的历史时间差(如日志分析),应统一存为
DateTime对象或带毫秒的时间戳(PHP 7.3+ 支持DateTime::createFromFormat('Y-m-d H:i:s.u', ...))
MySQL 时间字段直接用 SQL 计算更高效
如果两个时间都存在 MySQL 表里(比如 created_at 和 updated_at),别在 PHP 层取出来再算——既增加网络开销,又多一次类型转换。
- 用
TIMESTAMPDIFF(SECOND, start_time, end_time)直接得整数秒数 - 注意参数顺序:
TIMESTAMPDIFF第一个参数是单位,第二个是起点,第三个是终点;和 PHP 相减顺序相反 - 若字段是
DATETIME或TIMESTAMP类型,无需额外转换;但如果是字符串(VARCHAR),先用STR_TO_DATE()转一下
实际写的时候,多数情况用 strtotime() 就够了,但只要时间来源不可控,或者逻辑里混着不同时区,就得切到 DateTime 并显式设时区——这点容易被跳过,一上线就发现凌晨生成的时间差是负的。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











