format() 是 PHP 中将 DateTime 对象转为 ISO 8601 字符串的唯一可靠方式;必须用 "c"(RFC 3339 兼容)而非 DateTimeInterface::ISO8601,且需显式设时区为 UTC 才能确保输出正确 UTC 时间。

format() 是 PHP 中把 DateTime 对象转成 ISO 8601 字符串的唯一可靠方式。别用 date() 或 gmdate(),它们不处理时区偏移,也压根不认识 ISO 8601 的结构。
用 "c" 还是 DateTimeInterface::ISO8601?
两者都合法,但输出细节不同,选错可能被 API 拒绝:
-
"c"输出2026-08-31T11:28:00+00:00(带冒号的时区偏移) -
DateTimeInterface::ISO8601输出2026-08-31T11:28:00+0000(无冒号) - RFC 3339(常用于 REST API)明确要求冒号,所以优先用
"c" - 某些老旧系统或日志规范硬性要求无冒号格式,才考虑
DateTimeInterface::ISO8601
为什么直接 new DateTime("2026-08-31") 不够?
构造时没指定时区,PHP 默认按 date_default_timezone_get() 解析——比如你服务器在东八区,"2026-08-31" 就会被当成 2026-08-31T00:00:00+0800,再用 format("c") 输出就是带 +08:00 的字符串,不是 UTC。
要确保是 UTC 时间,必须显式调用 setTimezone():
$dt = new DateTime("2026-08-31");
$dt->setTimezone(new DateTimeZone("UTC"));
echo $dt->format("c"); // → "2026-08-31T00:00:00+00:00"
解析已有 ISO8601 字符串时的坑
如果输入本身就是 ISO8601 格式(如 "2026-08-31T11:28:00+08:00"),DateTime 构造函数能自动识别时区并正确解析时间值,但注意:
立即学习“PHP免费学习笔记(深入)”;
- 不要手动去掉时区再重设——
new DateTime("2026-08-31T11:28:00")会丢失原始偏移,变成本地时区时间 - 若需统一转为 UTC 输出,仍需
setTimezone(new DateTimeZone("UTC")),此时时间值会自动换算(比如 +08:00 的 11:28 变成 UTC 的 03:28) - 含毫秒的字符串(如
"2026-08-31T11:28:00.123Z")也能被正确解析,无需额外处理
别碰 idate() 和 DATE_ISO8601
idate() 只返回整数,根本拼不出 ISO 8601 字符串;DATE_ISO8601 是个过时常量,自 PHP 5.2 起就建议用 DateTimeInterface::ISO8601 替代,而且它和 "c" 不是同一层级的东西——前者是常量,后者是 format 字符,不能混用。
最易被忽略的点:时区设置必须在 format() 之前完成,且 setTimezone() 会真实改变对象内部的时间戳值,不是只改显示效果。



















