PHP日期加减首选strtotime()处理简单场景,如"+3 days";复杂逻辑(跨月、时区、闰年)应使用DateTime类以确保精确性和可维护性。

PHP用strtotime()加减天数最简单
直接用 strtotime() 是多数场景下最快捷的方式,它能解析自然语言格式的相对时间表达式,比如 "+3 days"、"-1 week"。注意它返回的是 Unix 时间戳,不是日期字符串,需要再用 date() 格式化。
- 支持常见单位:
"days"、"weeks"、"months"、"years"(但months和years有边界问题,见下一条) - 别写成
"3 days"(缺+或-),否则会被当作绝对时间解析,结果可能出人意料 -
strtotime("+0 days", $timestamp)是合法的,可用于“归整”到当天零点,但更推荐用date('Y-m-d', $ts)拼接
echo date('Y-m-d', strtotime('+5 days', strtotime('2024-03-15'))); // 输出:2024-03-20
用DateTime类做精确加减更可靠
当涉及月末、闰年、时区或需要链式操作时,DateTime 类比 strtotime() 更可控。它的 modify() 方法行为明确,add() 方法接受 DateInterval 对象,适合重复计算或动态天数。
-
modify()接受和strtotime()类似的字符串,如$dt->modify('+7 days') -
add()必须用DateInterval::createFromDateString('7 days')或new DateInterval('P7D');注意格式是PnD(P 表示 period,D 表示 day) - 跨月计算时,
modify('+1 month')和add(new DateInterval('P1M'))行为一致,但都可能跳过“不存在的日期”,比如从 1 月 31 日加 1 个月会落到 3 月 3 日而非 2 月 28/29 日
$dt = new DateTime('2024-01-31');
$dt->modify('+1 month');
echo $dt->format('Y-m-d'); // 输出:2024-03-02(不是 2024-02-29)
小心strtotime()对“月末”的模糊处理
很多人想算“上个月最后一天”,写成 strtotime('last day of last month') 看似合理,但实际兼容性差——这个语法在 PHP 5.2+ 才支持,且部分旧版本解析不稳定。更稳妥的做法是先定位到当月第一天,再减 1 天。
- 错误写法:
strtotime('last day of -1 month')(语法不被识别) - 推荐写法:
strtotime('first day of this month -1 day')或用DateTime:(new DateTime('first day of this month'))->modify('-1 day') - 如果只是要“N 天前”,永远优先用
strtotime("-N days"),而不是strtotime("N days ago")——后者在某些 PHP 版本中解析失败率更高
性能差异小,但可读性和维护性差别大
单次调用 strtotime() 和 DateTime 的性能差距几乎可以忽略(纳秒级),真正影响项目长期维护的是代码是否自解释、是否容易改错。尤其在处理业务逻辑如“订单超时(创建时间 + 3 天)”“会员到期日(开通日 + 365 天)”时,用 DateTime 显式构造对象,比一长串 strtotime() 嵌套更易调试和单元测试。
立即学习“PHP免费学习笔记(深入)”;
- 不要为了“省一行代码”把多个
strtotime()套在一起,例如date('Y-m-d', strtotime('+3 days', strtotime($_POST['date'])))—— 一旦输入非法,整个链路静默失败 - 建议统一入口校验日期格式,再转成
DateTime实例,后续所有加减都基于该实例操作 - 时区敏感场景(如跨国系统)必须显式设置时区:
new DateTime('now', new DateTimeZone('Asia/Shanghai')),否则依赖服务器默认时区,上线后容易出错
strtotime() 适合快速脚本或简单表单处理;DateTime 是业务系统里的事实标准。最容易被忽略的不是语法,而是没验证输入日期是否有效——strtotime('2024-02-30') 不报错,只返回 false,接着 date() 就输出 1970 年。



















