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.
ZonedDateTime is an immutable representation of a date-time with a time-zone. This class stores all date and time fields, to a precision of nanoseconds, and a time-zone, with a zone offset used to handle ambiguous local date-times.
A ZonedDateTime represents a date-time with a time offset and/or a time zone in the ISO-8601 calendar system. On its own, ZonedDateTime only supports specifying time offsets such as UTC or UTC+02:00 , plus the SYSTEM time zone ID.
ZoneOffset describes a time-zone offset, which is the amount of time (typically in hours) by which a time zone differs from UTC/Greenwich. ZonedDateTime describes a date-time with a time zone in the ISO-8601 calendar system (such as 2007-12-03T10:15:30+01:00 Europe/Paris ).
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.
The example in the documentation is 2007-12-03T10:15:30+01:00[Europe/Paris]
. This happens not to be ISO compliant since ISO-8601 does not include the [Europe/Paris]
part. This was added by the java.time
developers in a compromise between getting as close to the standard as reasonable and still provding the time zone information in an unambiguous way.
So the real question may in fact be the opposite: if ZonedDateTime.toString()
includes the time zone information that ISO does not include, when is the result fully ISO compliant? What does “if the offset and ID are the same” mean? Here we have to remember that ZoneOffset
is a subclass of ZoneID
and may be used as a zone ID in ZonedDateTime
. In this case the offset and the ID are the same. Otherwise they are not. For a specific example, ZonedDateTime.now(ZoneOffset.ofHours(+2)).toString()
may produce 2017-04-26T15:04:59.828+02:00
. This is fully ISO compatible because the zone is given as just +02:00
, which is the same as the offset. Also ZonedDateTime.now(ZoneOffset.UTC).toString()
gives something in the format 2017-04-26T13:04:59.828Z
. Since Z
counts as an offset, this is compatible too.
I think that in most cases it won’t be very useful. If your zone is just an offset, you would usually prefer to use OffsetDateTime
over ZonedDateTime
, and if so, of course you don’t care whether ZonedDateTime.toString()
is ISO compatible or not.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With