Why
echo date('c');
不等于
$datetime = new DateTime();
echo $datetime->format(DateTime::ISO8601);
结果:
2016-07-07T21:18:22+03:00
2016-07-07T21:18:22+0300
两者都必须以ISO8601格式提供当前时间。在维基百科中,正确的格式是2016-07-07T21:18:22+03:00
但一些银行在API中使用2016-07-07T21:18:22+0300
格式。为什么?
2016-07-07T21:18:22+03:00
是正确的ISO 8601:2004表示。
2016-07-07T21:18:22+0300
不正确,当日期和时间采用扩展格式时,区域指示符可能不是基本格式。
ISO 8601:2004 4.3 日期和时间:
[...]表达式应完全采用基本格式,在 在这种情况下,所需的最小分隔符数量 使用表达式或完全采用扩展格式,在这种情况下 应使用额外的分隔符 [...]
更新 1:
ISO 8601 指定了三种不同的日期表示形式:日历、序号和周日期。这些格式可以格式化为基本格式(最小分隔符数)或扩展格式(包含其他分隔符的基本格式的扩展)。ISO 8601 要求生成的表达式要么始终采用基本格式,要么始终采用扩展格式。
日历日期和时间(以本地时间表示)与 UTC 的差异的组合:
2016-07-07T21:18:22+03:00 (extended format)
20160707T211822+0300 (basic format)
本地时间中与 UTC 不同的序号日期和时间的组合:
2016-189T21:18:22+03:00 (extended format)
2016189T211822+0300 (basic format)
以当地时间表示的周日期和时间的组合,与 UTC 的差异:
2016-W27-4T21:18:22+03:00 (extended format)
2016W274T211822+0300 (basic format)
上述所有表示表示本地时间的相同日期和时间,与 UTC(和即时)不同。如果 API 记录它接受带有时间和区域指示符(也称为完整表示)的 ISO 8601 日期,则应接受上述所有表示以符合 ISO 8601。
更新 2:
我遇到的大多数错误都源于使用strftime()
以本地时间输出ISO 8601日期和时间,与扩展格式的UTC不同。由于z
转换说明符的限制,标准strftime()
只能以基本格式输出兼容表示:
日历日期和时间(以本地时间表示)与 UTC 的差异的组合:
Format: Example:
%Y%m%dT%H%M%S%z 20160707T211822+0300
本地时间中与 UTC 不同的序号日期和时间的组合:
Basic format: Example:
%Y%jT%H%M%S%z 2016189T211822+0300
以当地时间表示的周日期和时间的组合,与 UTC 的差异:
Basic format: Example:
%GW%V%uT%H%M%S%z 2016W274T211822+0300
GNU strftime 实现支持在百分比和z
转换说明符之间有一个:
标志,以指定区域指示符应以扩展格式格式化:
日历日期和时间(以本地时间表示)与 UTC 的差异的组合:
Format: Example:
%Y-%m-%dT%H:%M:%S%:z 2016-07-07T21:18:22+03:00
本地时间中与 UTC 不同的序号日期和时间的组合:
Format: Example:
%Y-%jT%H:%M:%S%:z 2016-189T21:18:22+03:00
以当地时间表示的周日期和时间的组合,与 UTC 的差异:
Format: Example:
%G-W%V-%uT%H:%M:%S%:z 2016-W27-4T21:18:22+03:00
当给定毫秒时,PHP 仍然无法正确解释ISO8601,即使使用 DateTime::ATOM。
$d=DateTime::createFromFormat(DateTime::ATOM,"2018-01-10T01:00:00.000Z");
// null
或使用碳:
echo CarbonCarbon::createFromFormat(CarbonCarbon::ATOM,"2018-01-10T01:00:00.000Z","UTC");
// InvalidArgumentException with message 'The timezone could not be found in the database'
最好的方法是让Carbon或日期时间自己弄清楚:
$d = new CarbonCarbon("2018-01-10T01:00:00.000Z");
// -> 2018-01-10 01:00:00
$d = new CarbonCarbon("2018-01-10T01:00:00Z");
// -> 2018-01-10 01:00:00