DateTimeImmutable 是处理日期时间的默认选择,因其不可变性避免副作用;应禁用 strtotime() 等模糊解析函数,改用 DateTimeImmutable::createFromFormat() 显式解析;时区必须显式声明,禁止依赖 date_default_timezone_set() 全局设置。

DateTime 类是 PHP 中处理日期时间的唯一推荐入口,PSR-12 和 PSR-2 虽未直接规定时间处理细节,但其隐含的可读性、可维护性与明确性原则,天然排斥 strtotime()、date()、mktime() 等过程式函数的随意使用。
为什么 PSR 不允许裸用 strtotime()
PSR 标准不禁止某个函数,但它的实践逻辑强烈反对模糊解析——而 strtotime() 正是典型。它会接受 "next Monday"、"last day of next month"、甚至 "tomorrow + 3 days" 这类自然语言表达,但结果高度依赖上下文和当前系统时区设置。
- 同一字符串在不同 PHP 版本或 locale 下可能解析出不同时间(例如 "01/02/2023" 在 en-US 是 Jan 2,en-GB 是 Feb 1)
- 没有显式错误抛出机制:输入非法(如 "2023-02-30")时返回
false,若未检查就传给date(),会静默变成 1970-01-01 - 无法与类型系统协同:
int|false返回值破坏静态分析工具(如 PHPStan)的推断链
PSR-12 的「可预测性」要求,意味着时间解析必须是确定的、可测试的、可追溯的——这只有 DateTime::createFromFormat() 或 DateTimeImmutable::createFromFormat() 能满足。
DateTimeImmutable 应该是默认选择
PSR-2 的「避免副作用」原则,在时间对象上体现得尤为尖锐。DateTime 是可变对象:调用 add()、modify()、setTimezone() 都会原地修改自身,容易在多处引用同一实例时引发竞态。
- 函数参数传入
DateTime对象后被意外修改,调用方后续逻辑出错 - 循环中复用对象却忘了
clone,导致下一轮迭代时间错乱 - 无法安全地作为数组键或缓存 key(因为内容会变)
DateTimeImmutable 强制每次操作返回新实例,天然符合函数式编程习惯,也更契合 PSR 倡导的「显式优于隐式」。哪怕只是做一次加减,也应写成:
立即学习“PHP免费学习笔记(深入)”;
$dt = new DateTimeImmutable('2026-05-26');
$newDt = $dt->add(new DateInterval('P7D'));
而不是:
$dt = new DateTime('2026-05-26');
$dt->add(new DateInterval('P7D')); // 修改了原对象
时区处理必须显式声明,不能依赖 date_default_timezone_set()
PSR-12 明确反对全局状态污染。date_default_timezone_set() 属于脚本级副作用,它会影响所有后续未指定时区的 date()、strtotime()、甚至 new DateTime() 调用,且无法被局部隔离。
- 一个库调用
date_default_timezone_set('UTC'),可能破坏主应用原本设为'Asia/Shanghai'的逻辑 - 并发请求中,时区设置可能被交叉覆盖(尤其在 SAPI 复用场景如 PHP-FPM)
- 单元测试难以 mock 或重置,导致测试间相互污染
正确做法是:所有时间对象创建都带明确时区,例如:
$tz = new DateTimeZone('Asia/Shanghai');
$dt = new DateTimeImmutable('now', $tz);
或从字符串解析时一并指定:
$dt = DateTimeImmutable::createFromFormat('Y-m-d H:i:s', '2026-05-26 10:30:00', $tz);
数据库存储统一用 UTC,展示前再用 setTimezone() 转换——这个流程本身没问题,但转换动作必须发生在明确的业务层,而非靠全局配置“自动生效”。
最常被忽略的一点:PSR 不强制你用什么类,但它通过代码可维护性倒逼你放弃“能跑就行”的时间写法。哪怕只改一行——把 strtotime($input) 换成 DateTimeImmutable::createFromFormat('Y-m-d', $input) ?: throw new InvalidArgumentException(...)——就已经踩进了 PSR 所期待的实践水位线。



















