Representing UTC Time in Java

assorted clocks

Mind Your Time Zones

We have systems spread across multiple time zones. The time zone or UTC offset should be included in the date time data sent from one system to another, this way the receiving system can convert date times from the sending system into the identical time under the receiver’s time zone. One approach is to send up date times as strings that include the UTC offset - this can be done by formatting the date time using the DateTimeFormatter.ISO_OFFSET_DATE_TIME pattern.

Sending timestamps with the UTC offset

Here’s a way to get a date time string with UTC offset from the local date time (the date and time using the local time zone):

import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
 
// get the local date time
LocalDateTime now = LocalDateTime.now();

// convert local date time to offset date time using local time zone
OffsetDateTime offsetDateTimeWithLocalTimeZone = now.atZone(ZoneId.systemDefault())
        .toOffsetDateTime();

// convert offset date time with local time zone offset to equivalent utc date time
OffsetDateTime offsetDateTimeUtc = offsetDateTimeWithLocalTimeZone
        .withOffsetSameInstant(ZoneOffset.UTC);

System.out.println("local date time with utc offset: "
        + offsetDateTimeWithLocalTimeZone.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
System.out.println("equivalent utc date time: "
        + offsetDateTimeUtc.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));

We can now send the offsetDateTimeWithLocalTimeZone value from the code block above to another system for processing that needs to be sensitive to time zone differences.

Processing received timestamps with the UTC offset

Now on the receiving system we need to take the date time from the sender (which includes UTC offset) and convert it to the same point in time under the receiver’s time zone:

import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
 
// for example: a date time under the mountain time zone was received
OffsetDateTime offsetDateTimeMountainTimeZone = ZonedDateTime.now()
        .withZoneSameInstant(ZoneId.of("America/Phoenix")).toOffsetDateTime();

// convert the mountain date time (with UTC offset) to the equivalent date time under the
// local time zone
ZonedDateTime zonedDateTime = offsetDateTimeMountainTimeZone
        .atZoneSameInstant(ZoneId.systemDefault());

System.out.println("mountain date time: "
        + offsetDateTimeMountainTimeZone.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
System.out.println("equivalent local date time: "
        + zonedDateTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));

The zonedDateTime value from the block above is the equivalent to the date time under the mountain time zone, but now under the time zone of the receiving system.

And there you have it: a recipe for creating and processing a timestamp in different timezones using the UTC offset - it’s easy as pie thanks to the Java time API.

Here are the above code snippets combined for your convenience: