ISO 8601, for example 2026-09-14T09:46:00.123Z.
A zero utc_offset_min is rendered as Z; any other offset is
rendered as +HH:MM or -HH:MM, so the text always identifies the
instant rather than quietly presenting local time as UTC.
When utc_offset_known is false no designator is written at all.
ISO 8601 calls that a local time, which is exactly what it is: the
alternative, a Z the processor never justified, would be a wrong
instant rather than an incomplete one.
Built with zfill rather than an internal write: the I0.N edit
descriptor and list-directed output are processor dependent, and this
text is compared byte for byte by tests and golden files.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(datetime_t), | intent(in) | :: | dt |
pure function format_iso8601(dt) result(text) !! ISO 8601, for example `2026-09-14T09:46:00.123Z`. !! !! A zero `utc_offset_min` is rendered as `Z`; any other offset is !! rendered as `+HH:MM` or `-HH:MM`, so the text always identifies the !! instant rather than quietly presenting local time as UTC. !! !! When `utc_offset_known` is false no designator is written at all. !! ISO 8601 calls that a local time, which is exactly what it is: the !! alternative, a `Z` the processor never justified, would be a wrong !! instant rather than an incomplete one. !! !! Built with `zfill` rather than an internal `write`: the `I0.N` edit !! descriptor and list-directed output are processor dependent, and this !! text is compared byte for byte by tests and golden files. type(datetime_t), intent(in) :: dt character(len=:), allocatable :: text text = pad(dt%year, 4)//"-"//pad(dt%month, 2)//"-"//pad(dt%day, 2)//"T"// & pad(dt%hour, 2)//":"//pad(dt%minute, 2)//":"//pad(dt%second, 2)//"."// & pad(dt%millisecond, 3) if (dt%utc_offset_known) text = text//offset_text(dt%utc_offset_min) end function format_iso8601