Daniel Wolf
Daniel Wolf

Reputation: 13663

Compatibility between Instant and ZonedDateTime

It is my understanding that a ZonedDateTime is really an enhanced version of an Instant. It has all the data an Instant has (precise value along UTC timeline), plus time zone information. So my naïve assumption was that a ZonedDateTime is-an Instant and that any method taking an Instant will happily take a ZonedDateTime instead. Furthermore, I expected isBefore(), isAfter() etc. to work seamlessly between Instants and ZonedDateTimes.

Looking at the API documentation for Instant and ZonedDateTime, none of this is the case. I can compare Instants with Instants and ZonedDateTimes with ZonedDateTimes, but the two classes seem to be incompatible. What's more, third-party code like ThreeTen-Extra's Interval seem to work exclusively with Instants.

Is there a reason why Instant and ZonedDateTime are not meant to be mixed?

Upvotes: 13

Views: 4034

Answers (3)

Lars Christian Jensen
Lars Christian Jensen

Reputation: 1642

Instant and ZonedDateTime have different rules for arithmetic. That is the only reason I can see for avoiding polymorphism for these two types. For example, adding n days to an Instant means adding n times 86400 seconds to it. Always. That would not be the case if ZonedDateTime was a sub-class of Instant, because of rules for daylight savings time.

My understanding is that an Instant is similar to a ZonedDateTime with time zone UTC, so you could argue that Instant is-a ZonedDateTime instead. However, this would make Instant more complicated than it is today, since it would allow arithmetic with TemporalUnits such as MONTHS. Arithmetic with months are time zone dependent, so Instant forces the programmer to select an explicit time zone before doing it.

Anyway, it is unfortunate that Instant and ZonedDateTime aren't more compatible, since they both represent time unambiguously. It looks like they lack a common base class or interface without any methods for arithmetic.

Upvotes: 1

Smutje
Smutje

Reputation: 18163

Because the translation is not injective. Take Sunday, October 30th 2016 2:15 AM in Germany/Munich for example: Which Instant does this date/time represent? This is not independently answerable without some assumptions because you don't know if this time should be translated into the Instant before or after the offset for daylight saving time (DST) should be applied. Or Sunday, March 27th 2016 2:15 AM in Germany/Munich: This date/time combination should not exist, as the clock should be set to 3 AM when reaching 2 AM.

Without DST the three possible cases for translating a LocalDateTime into an Instant (exact match, summertime-gap, wintertime-overlap) would be reduced to one and the conversion would be injective, AFAIK.

Edit: "Hands on" this problem, when displaying date/time in our JSF based application, we always pass the offset calculated accordingly to the current state of the DST into the formatter.

Upvotes: 7

JodaStephen
JodaStephen

Reputation: 63405

Instant and ZonedDateTime have different state - Instant is just a number of nanoseconds from the epoch, while ZonedDateTime consists of a LocalDateTime, ZoneId and ZoneOffset. As such, the two classes can be converted to/from each other, but are not the same (and you lose information when converting ZonedDateTime to Instant).

The behaviour of isBefore() and isAfter() matches exactly between the two however. Whereas the implementation of Comparable matches the recommended behaviour, which is that "It is strongly recommended (though not required) that natural orderings be consistent with equals." ie. compareTo() takes account of the local date-time, time-zone and offset, whereas isBefore() and isAfter() only consider the instant.

Writing a comparator to compare an Instant and a ZonedDateTime is relatively simple:

Comparator<TemporalAccessor> comparator =
    (a, b) -> Instant.from(a).compareTo(Instant.from(b));

which can also be written as:

Comparator<TemporalAccessor> comparator = Comparator.comparing(Instant::from);

Upvotes: 10

Related Questions