ZonedDateTime toString compatability with ISO 8601

theyuv picture theyuv · Apr 26, 2017 · Viewed 19.4k times · Source

I am trying to ensure that calling toString() on my ZonedDateTime Object will comply with ISO-8601 format.

The documentation for the toString() method states:

...The output is compatible with ISO-8601 if the offset and ID are the same

Does this mean that there exists a situation where calling zdt.getOffset() will return something different than zdt.getZone().getRules().getOffset(zdt.toInstant()) ?

This doesn't seem to make sense.

Can someone provide an example in which the offset and ID are not the same (ie: where toString() does not comply with ISO-8601) so that I can better understand the description in the documentation.

Answer

JodaStephen picture JodaStephen · Apr 26, 2017

This is the complete specification:

 * Outputs this date-time as a {@code String}, such as
 * {@code 2007-12-03T10:15:30+01:00[Europe/Paris]}.
 * <p>
 * The format consists of the {@code LocalDateTime} followed by the {@code ZoneOffset}.
 * If the {@code ZoneId} is not the same as the offset, then the ID is output.
 * The output is compatible with ISO-8601 if the offset and ID are the same.

The Javadoc specification refers to the case where the ZonedDateTime is constructed with a ZoneOffset rather than a named ZoneId, thus where the offset and ID are the same:

System.out.println(ZonedDateTime.now(ZoneId.of("Europe/Paris")));
// 2017-04-26T15:13:12.006+02:00[Europe/Paris]

System.out.println(ZonedDateTime.now(ZoneOffset.ofHours(2)));
// 2017-04-26T15:13:12.016+02:00

As can be seen, in the second case, where a ZoneOffset is used, the toString() format omits the square bracket section at the end. By omitting that section, the result is ISO-8601 compatible.

boolean iso8601Compatible = zdt.getZone() instanceof ZoneOffset;

To guarantee an ISO-8601 compatible output use toOffsetDateTime():

String isoCompatible = zdt.toOffsetDateTime().toString();

or a formatter.