应优先使用 DateTimeImmutable 替代 DateTime,构造时必须显式指定时区,避免 strtotime() 和字符串比较,时区转换需先明确原始时区再调用 setTimezone()。

别用 strtotime() 和 date() 做跨时区、加减、比较或解析用户输入——它们不是“不够用”,而是会在你没注意时悄悄改掉日期(比如把 2 月 31 日自动变成 3 月 3 日),且无法携带时区上下文。
DateTime 构造时传错参数,结果完全不对
构造 DateTime 对象是第一步,也是最容易翻车的地方:
- 传
null或空字符串:new DateTime('')会取系统默认时区的当前时间,但你根本不知道它是什么——显式写new DateTime('now')更可读 - 只传日期字符串:
new DateTime('2024-05-20')得到的是当天 00:00:00,但时区取决于当前date_default_timezone_set()设置;若想确保是 UTC,必须写成new DateTime('2024-05-20', new DateTimeZone('UTC')) - 传 Unix 时间戳:必须带
@前缀,new DateTime('@1716220800')才对;写成new DateTime(1716220800)会被当成公元 1716 年解析
比较两个时间,别用字符串或 strtotime() 直接比
字符串比较(如 '2024-01-15' )在 ISO 格式下看似可行,但一旦格式不统一(比如数据库存 <code>'15/01/2024'),结果就不可靠;strtotime() 又容易因模糊解析出错(如 '31-02-2024' 被强行转成 3 月 2 日)。
正确做法是统一转为 DateTime 对象再比:
$a->diff($b)
- 用户填的是“2024-01-01 10:00”,且明确是上海时间 → 构造时就指定:
new DateTime('2024-01-01 10:00', new DateTimeZone('Asia/Shanghai')) - 再转存 UTC:
$dt->setTimezone(new DateTimeZone('UTC')),然后format('Y-m-d\TH:i:s\Z')
漏掉构造时的时区声明,后面所有转换都是空中楼阁。
最常被忽略的一点:DateTime 构造失败默认抛 Exception,而 strtotime() 失败只返回 false——这意味着你得主动检查返回值,否则 date('Y-m-d', false) 会输出 1970-01-01。用面向对象方式,错误更早暴露,也更容易定位。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











