I want to produce an ISO-8601 string from a DateTime
object in PHP 8.2. The Date
class has two related predefined constants for the date_format()
function:
DATE_ISO8601
- "Y-m-d\\TH:i:sO"
Note: This format is not compatible with ISO-8601, but is left this way for backward compatibility reasons. Use DateTimeInterface::ISO8601_EXPANDED, DateTimeInterface::ATOM for compatibility with ISO-8601 instead. (ref ISO8601:2004 section 4.3.3 clause d)
DATE_ISO8601_EXPANDED
- "X-m-d\\TH:i:sP"
This format allows for year ranges outside of ISO-8601's normal range of 0000-9999 by always including a sign character. It also addresses that that timezone part (+01:00) is compatible with ISO-8601.
The DATE_ISO8601_EXPANDED
format adds a leading +
character to the string, which is NOT recognized by ISO8601 parsers in other languages (specifically Swift):
+2023-03-29T05:54:21+00:00
The output of DATE_ISO8601
is:
2023-03-29T05:54:21+0000
I cannot determine what the warning about DATE_ISO8601
means. Does it mean:
or
Hilariously, section 4 of ISO 8601 is not publicly available without purchase, so I can't read it. But the "expanded" format doesn't appear to be standard ISO8601 either, since the spec calls for a leading +
symbol only when the year is greater than 9999.
The note means that the format DATE_ISO8601
is not at all compatible with ISO-8601 and you should not use it, instead use either DATE_ISO8601_EXPANDED
or DATE_ATOM
. The compatibility problem is not related to whether or not you use a date with a year beyond 0000-9999. You can read more about that here.
The DATE_ISO8601_EXPANDED
format differs from DATE_ATOM
only in the year representation, DATE_ISO8601_EXPANDED
uses 'X'
instead of 'Y'
:
"Y-m-d\\TH:i:sP"
"X-m-d\\TH:i:sP"
So if you don't need expanded year representation for values outside 0-9999, use DATE_ATOM
.
Expanded representation should be used only by prior agreement, this is probably why some parsers will not correctly handle the sign before the year. Although I'm also not sure if DATE_ISO8601_EXPANDED
is compatible with ISO-8601, because it talks about a constant number of digits for expanded year representation.
You can find some links to ISO-8601 without paying here: https://github.com/php/doc-en/pull/1619