Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between ZonedDateTime and OffsetDateTime?

People also ask

Should I use ZonedDateTime or OffsetDateTime?

Use OffsetDateTime to store unique instants in the universal timelines irrespective of the timezones, such as keeping the timestamps in the database or transferring information to remote systems worldwide. Use ZonedDateTime for displaying timestamps to users according to their local timezone rules and offsets.

Should I use OffsetDateTime?

Therefore, we should always prefer storing OffsetDateTime in the database over the ZonedDateTime, as dates with a local time offset always represent the same instants in time. Moreover, unlike with the ZonedDateTime, adding an index over a column storing the OffsetDateTime won't change the meaning of the date.

What is the difference between ZonedDateTime and LocalDateTime?

A LocalDateTime instance represents a point in the local timeline. It cannot represent an instant on the universal timeline without additional information such as an offset or time zone. A ZonedDateTime instance represents an instant in the universal timeline. It is the combination of date, time and zone information.

What is a ZonedDateTime?

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.


Q: What's the difference between java 8 ZonedDateTime and OffsetDateTime?

The javadocs say this:

"OffsetDateTime, ZonedDateTime and Instant all store an instant on the time-line to nanosecond precision. Instant is the simplest, simply representing the instant. OffsetDateTime adds to the instant the offset from UTC/Greenwich, which allows the local date-time to be obtained. ZonedDateTime adds full time-zone rules."

Source: https://docs.oracle.com/javase/8/docs/api/java/time/OffsetDateTime.html

Thus the difference between OffsetDateTime and ZonedDateTime is that the latter includes the rules that cover daylight saving time adjustments and various other anomalies.

Stated simply:

Time Zone = ( Offset-From-UTC + Rules-For-Anomalies )


Q: According to documentation OffsetDateTime should be used when writing date to database, but I don't get why.

Dates with local time offsets always represent the same instants in time, and therefore have a stable ordering. By contrast, the meaning of dates with full timezone information is unstable in the face of adjustments to the rules for the respective timezones. (And these do happen; e.g. for date-time values in the future.) So if you store and then retrieve a ZonedDateTime the implementation has a problem:

  • It can store the computed offset ... and the retrieved object may then have an offset that is inconsistent with the current rules for the zone-id.

  • It can discard the computed offset ... and the retrieved object then represents a different point in the absolute / universal timeline than the one that was stored.

If you use Java object serialization, the Java 9 implementation takes the first approach. This is arguably the "more correct" way to handle this, but this doesn't appear to be documented. (JDBC drivers and ORM bindings are presumably making similar decisions, and are hopefully getting it right.)

But if you are writing an application that manually stores date/time values, or that rely on java.sql.DateTime, then dealing with the complications of a zone-id is ... probably something to be avoided. Hence the advice.

Note that dates whose meaning / ordering is unstable over time may be problematic for an application. And since changes to zone rules are an edge case, the problems are liable to emerge at unexpected times.


A (possible) second reason for the advice is that the construction of a ZonedDateTime is ambiguous at the certain points. For example in the period in time when you are "putting the clocks back", combining a local time and a zone-id can give you two different offsets. The ZonedDateTime will consistently pick one over the other ... but this isn't always the correct choice.

Now, this could be a problem for any applications that construct ZonedDateTime values that way. But from the perspective of someone building an enterprise application is a bigger problem when the (possibly incorrect) ZonedDateTime values are persistent and used later.


The accepted answer give very completed explanation, perhaps below code example can provide you short and clear picture:

Instant instant = Instant.now();
Clock clock = Clock.fixed(instant, ZoneId.of("America/New_York"));
OffsetDateTime offsetDateTime = OffsetDateTime.now(clock);
ZonedDateTime zonedDateTime = ZonedDateTime.now(clock);

System.out.println(offsetDateTime); // 2019-01-03T19:10:16.806-05:00
System.out.println(zonedDateTime);  // 2019-01-03T19:10:16.806-05:00[America/New_York]
System.out.println();

OffsetDateTime offsetPlusSixMonths = offsetDateTime.plusMonths(6);
ZonedDateTime zonedDateTimePlusSixMonths = zonedDateTime.plusMonths(6);

System.out.println(offsetPlusSixMonths); // 2019-07-03T19:10:16.806-05:00
System.out.println(zonedDateTimePlusSixMonths); // 2019-07-03T19:10:16.806-04:00[America/New_York]
System.out.println(zonedDateTimePlusSixMonths.toEpochSecond() - offsetPlusSixMonths.toEpochSecond()); // -3600

System.out.println();
System.out.println(zonedDateTimePlusSixMonths.toLocalDateTime()); // 2019-07-03T19:10:16.806
System.out.println(offsetPlusSixMonths.toLocalDateTime()); // 2019-07-03T19:10:16.806

In short, use ZonedDateTime only if you want to factor in Daylight saving, typically there will be one hour difference, as you can see the example above, the offset of ZonedDateTime change from -5:00 to -04:00, in most case, your business logic might end up with bug.

(code copy from https://www.youtube.com/watch?v=nEQhx9hGutQ)