Conversion of java.util.Date to OffsetDateTime

In our codebase I’ve run into this code converting current timestamp into OffsetDateTime:

public static OffsetDateTime getUTCTime(){
    Date date = new Date();
    // Convert Date object to UTC OffsetDateTime object
    Instant instant = date.toInstant();
    return instant.atOffset(ZoneOffset.UTC);
}

I wonder whether it is possible to replace this code with this:

public static OffsetDateTime getUTCTime(){
    return OffsetDateTime.now(ZoneOffset.UTC);
}

Will the returned value be equivalent for both snippets?

  • 2

    Write unit tests and try it out

    – 

There is a difference in accuracy.

In your first code snippet you provide new Date() which uses currentTimeMillis().
When converted into an OffsetDateTime, it can only show up to milliseconds.

Example: “2024-02-02T14:09:04.042Z”

Your second code snippet directly uses the OffsetDateTime object, which is nano second accurate.

Example: “2024-02-02T14:09:04.042471300Z”

Maybe there is a requirement to “only” show/persist the millisecond or if persisted as a string the first one would obviously need less space.
Apart from that, I can’t tell you if one of them is more efficient.

TLDR;

It should return similar value in most cases, but precision might be different.
OffsetDateTime converted from Date could only represent up to millisecond, where OffsetDateTime.now could represent up to nanosecond.

It may sounds okay at first, but as per my personal experience, this could lead to different issues, like:

  • When doing comparison, some test could fail because of higher precision.
  • The value before saving to database could be different to the value retrieved after saving to database, due to inconsistent precision.
  • The formatted datetime, toString() may looks different
    e.g.
    2024-02-02T13:47:18.838Z vs
    2024-02-02T13:47:18.838890Z

Why are they different?

From documentation of Date,

The class Date represents a specific instant in time, with millisecond precision.

Obviously, the precision of OffsetDateTime converted from Date is limited to millisecond.

And if we check the source code of OffsetDateTime.now,

public static OffsetDateTime now(ZoneId zone) {
    return now(Clock.system(zone));
}
public static OffsetDateTime now(Clock clock) {
    Objects.requireNonNull(clock, "clock");
    final Instant now = clock.instant();  // called once
    return ofInstant(now, clock.getZone().getRules().getOffset(now));
}

We can see the instant is retrieved from Clock.system(zone), by referring to Clock documentation.

The system factory methods provide clocks based on the best available system clock. This may use System.currentTimeMillis(), or a higher resolution clock if one is available.

Hence it could have higher precision, if available.

Yes, the two code snippets you provided should be equivalent in terms of functionality. Both snippets aim to obtain the current timestamp in UTC as an OffsetDateTime object.

The first snippet uses the older Date class to capture the current timestamp, converts it to an Instant, and then creates an OffsetDateTime using the UTC offset.

The second snippet uses the more modern OffsetDateTime.now(ZoneOffset.UTC) method, which directly provides an OffsetDateTime object representing the current UTC time.

In summary, you can safely replace the first code snippet with the second one, and the returned value should be equivalent. The second snippet is more concise and leverages the updated date and time API introduced in Java 8.

Leave a Comment