最稳妥的php日期比较方式是统一转为时间戳或使用datetime类。strtotime()需校验false返回,datetime则应显式指定时区并检查构造结果,数据库日期比较应下推至sql层以避免性能与索引问题。

用 strtotime() 转成时间戳再比较最稳
PHP 里直接用 > 或 == 比字符串格式的日期(比如 "2024-03-15")看似能跑通,但一遇到 "2024-3-5"、"15/03/2024" 或时区差异就出错。真正靠谱的做法是统一转成整数时间戳再比。
原因很简单:时间戳是纯数字,大小关系明确,不受格式、语言环境、时区隐式影响。
-
strtotime("2024-03-15")返回1710460800,strtotime("2024-03-16")返回1710547200,直接>就行 - 如果输入可能为空或非法(如
"abc"),strtotime()会返回false,必须先判断:if (false === $ts) { /* 处理错误 */ } - 注意默认时区:没设
date_default_timezone_set()时,strtotime()按系统时区解析,可能和你预期不一致
用 DateTime 类对象比较更安全、可读性更强
当日期来源复杂(含时间、有时区、要复用计算逻辑),DateTime 是更现代的选择。它内部封装了时区、格式解析和算术逻辑,避免手动处理边界。
关键点在于:两个 DateTime 对象可以直接用 、<code>==、> 比较,PHP 会自动调用其 getTimestamp() 做数值比对。
立即学习“PHP免费学习笔记(深入)”;
- 构造时建议显式传时区:
new DateTime("2024-03-15", new DateTimeZone("Asia/Shanghai")) - 如果一个有时间、一个只有日期(如
"2024-03-15"vs"2024-03-15 14:30:00"),直接比可能不符合业务意图——前者会被当成当天零点,后者是具体时刻,得看你要“是否同一天”还是“是否早于该时刻” - 别用
format()后字符串比较:$a->format("Y-m-d") === $b->format("Y-m-d")看似直观,但丢失了时间精度,且多一次格式化开销
小心 date_create() 返回 false 导致空指针错误
date_create() 和 new DateTime() 行为基本一致,但前者在失败时不抛异常,而是静默返回 false。如果直接拿这个结果去调方法,比如 date_format(date_create("invalid"), "U"),就会报 Warning: date_format() expects parameter 1 to be DateTime, bool given。
- 必须检查返回值:
$dt = date_create($input); if (!$dt) { throw new InvalidArgumentException("Invalid date: $input"); } - 不要链式调用:
date_format(date_create($input), "U")是危险写法,date_create()失败后整个表达式崩掉 - 用
DateTime::createFromFormat()时更要谨慎——它允许宽松匹配,比如"Y-m-d"格式下传入"2024/03/15"可能返回对象但解析错误(年份变成 20240315),得配合DateTime::getLastErrors()验证
MySQL 时间字段直接在 SQL 里比,别全量取回 PHP 再比
如果你查的是数据库里的日期(比如 created_at 字段),在 PHP 里取出来再用 strtotime() 比,是典型低效操作。尤其数据量稍大或要做范围筛选时,应该把比较逻辑下推到 SQL 层。
- 写
WHERE created_at > "2024-03-01",MySQL 自动按 datetime 类型索引走,快且准 - 避免
WHERE DATE(created_at) = "2024-03-15"—— 这会让索引失效,改用WHERE created_at >= "2024-03-15" AND created_at - PHP 只需传参,别拼 SQL 字符串:
$stmt = $pdo->prepare("SELECT * FROM logs WHERE created_at > ?"); $stmt->execute([$threshold]);
日期比较看着简单,实际最容易栽在隐式类型转换、时区漂移和非法输入上。哪怕只是临时脚本,也建议统一用 DateTime 构造 + 显式时区 + 失败校验这三板斧——省得半夜被一个 "0000-00-00" 或 "13/13/2024" 报错叫醒。










