最稳妥的方式是用 strtotime() 转为时间戳再比较;需检查返回值是否为 false,避免隐式转换导致逻辑错误;对复杂场景(如时区、精度)应选用 DateTime 类。

直接用 strtotime() 转成时间戳再比较最稳妥
PHP 中字符串日期(如 "2024-03-15" 或 "2024/03/15 14:30:00")不能直接用 >、 比较,否则会按字典序比,结果不可靠。必须先统一转为整型时间戳或 DateTime 对象。
最常用且兼容性最好的方式是 strtotime():
if (strtotime("2024-03-20") > strtotime("2024-03-15")) {
echo "后一个日期更大";
}
-
strtotime()自动识别常见格式(Y-m-d、Y/m/d、Y-m-d H:i:s等),返回 Unix 时间戳(秒数) - 返回
false表示解析失败,务必检查:例如strtotime("2024-02-30")会返回false,直接参与比较可能隐式转为0导致逻辑错误 - 对含时区的字符串(如
"2024-03-15T10:00:00+08:00")也支持,但注意 PHP 版本 —— 5.2+ 更稳定
用 DateTime 类做面向对象式比较更安全
当需要处理时区、微秒、或多次复用日期对象时,DateTime 是更现代、更可控的选择。它重载了比较运算符,可直接用 、>、==。
$d1 = new DateTime("2024-03-15 09:00:00");
$d2 = new DateTime("2024-03-15 17:30:00");
if ($d1 < $d2) {
echo "d1 在 d2 之前";
}
// 也可用 diff() 获取具体差值
$diff = $d1->diff($d2);
echo $diff->h . " 小时 " . $diff->i . " 分钟";
- 构造失败时抛出
Exception,比strtotime()的静默false更易暴露问题 - 默认使用当前时区(
date_default_timezone_get()),若源字符串含时区(如"2024-03-15 UTC"),会自动转换;若不希望自动转换,可用DateTimeImmutable+ 显式setTimezone() - 避免在循环中频繁 new
DateTime—— 构造开销略高于strtotime(),但差异极小,优先选可读性和健壮性
别踩坑:字符串直接比较可能“看起来对”,实则错
像 "2024-03-10" > "2024-03-09" 这种写法,在标准 Y-m-d 格式下确实能碰巧成立,但属于格式依赖行为,非常危险。
立即学习“PHP免费学习笔记(深入)”;
- 换成
"2024-3-10"和"2024-3-9"(无前导零),字符串比较就失效:"2024-3-10" (因为)'1''9' - 中文格式如
"2024年3月10日"、英文格式如"Mar 10, 2024"完全无法直比 - 数据库返回的
DATE字段通常是字符串,不要假设它“刚好能比”——显式转换才是底线
涉及数据库或用户输入时,先校验再转换
从表单或 API 接收的日期字符串,格式不确定、可能为空、可能非法。直接丢给 strtotime() 或 DateTime 容易崩或得错值。
- 用
DateTime::createFromFormat()指定期望格式,比strtotime()更严格:$date = DateTime::createFromFormat("Y-m-d", $_POST['date']); if (!$date || $date->format("Y-m-d") !== $_POST['date']) { die("日期格式错误"); } - 对 MySQL 的
DATETIME字段,建议用UNIX_TIMESTAMP()在 SQL 层转时间戳,减少 PHP 层解析压力 - 时区混乱是高频问题:确认
date_default_timezone_set()已设(如"Asia/Shanghai"),且前后端约定好传的是本地时间还是 UTC
strtotime() 加空值/失败检查就足够;剩下 10% 需要精度、时区控制或链式操作时,才值得上 DateTime。别为了“看起来高级”而绕远路,但一定要堵住 false 和 null 这两个最常被忽略的漏洞。










