Skip to content
On this page

ZonedDateTime

LocalDateTime always represents local date and time, but to represent a date and time with a time zone, we need ZonedDateTime.

You can simply think of ZonedDateTime as LocalDateTime combined with ZoneId. ZoneId is a new time zone class introduced in java.time, distinct from the old java.util.TimeZone.

To create a ZonedDateTime object, you can use several methods, one of which is the now() method to return the current time:

java
import java.time.*;

public class Main {
    public static void main(String[] args) {
        ZonedDateTime zbj = ZonedDateTime.now(); // Default time zone
        ZonedDateTime zny = ZonedDateTime.now(ZoneId.of("America/New_York")); // Get current time in specified time zone
        System.out.println(zbj);
        System.out.println(zny);
    }
}

When you observe the printed ZonedDateTime, you’ll find that they have different time zones but represent the same moment (the millisecond difference is due to execution time):

2019-09-15T20:58:18.786182+08:00[Asia/Shanghai]
2019-09-15T08:58:18.788860-04:00[America/New_York]

Another way to create a ZonedDateTime is by attaching a ZoneId to a LocalDateTime, thus converting it to ZonedDateTime:

java
import java.time.*;

public class Main {
    public static void main(String[] args) {
        LocalDateTime ldt = LocalDateTime.of(2019, 9, 15, 15, 16, 17);
        ZonedDateTime zbj = ldt.atZone(ZoneId.systemDefault());
        ZonedDateTime zny = ldt.atZone(ZoneId.of("America/New_York"));
        System.out.println(zbj);
        System.out.println(zny);
    }
}

In this way, the ZonedDateTime created has the same date and time as the LocalDateTime, but different attached time zones, thus representing two different moments:

2019-09-15T15:16:17+08:00[Asia/Shanghai]
2019-09-15T15:16:17-04:00[America/New_York]

Time Zone Conversion

To convert time zones, you first need a ZonedDateTime object. You can then convert the associated time zone to another time zone using withZoneSameInstant(), which adjusts the date and time accordingly.

The following code demonstrates how to convert Beijing time to New York time:

java
import java.time.*;

public class Main {
    public static void main(String[] args) {
        // Get current time in China time zone:
        ZonedDateTime zbj = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
        // Convert to New York time:
        ZonedDateTime zny = zbj.withZoneSameInstant(ZoneId.of("America/New_York"));
        System.out.println(zbj);
        System.out.println(zny);
    }
}

It’s important to note that due to daylight saving time, the results of conversions may differ for different dates. Here’s the conversion result for Beijing time on September 15:

2019-09-15T21:05:50.187697+08:00[Asia/Shanghai]
2019-09-15T09:05:50.187697-04:00[America/New_York]

And here’s the conversion result for November 15:

2019-11-15T21:05:50.187697+08:00[Asia/Shanghai]
2019-11-15T08:05:50.187697-05:00[America/New_York]

Notice the 1-hour difference in New York time due to daylight saving.

Note: When dealing with time zones, avoid manually calculating time differences, as this can complicate handling daylight saving time.

With ZonedDateTime, converting it to local time is straightforward:

java
ZonedDateTime zdt = ...
LocalDateTime ldt = zdt.toLocalDateTime();

This conversion discards the time zone information.

Exercise

A flight from Beijing to New York takes 13 hours and 20 minutes. Calculate the local date and time of arrival in New York based on the departure date and time in Beijing:

java
import java.time.*;

public class Main {
    public static void main(String[] args) {
        LocalDateTime departureAtBeijing = LocalDateTime.of(2019, 9, 15, 13, 0, 0);
        int hours = 13;
        int minutes = 20;
        LocalDateTime arrivalAtNewYork = calculateArrivalAtNY(departureAtBeijing, hours, minutes);
        System.out.println(departureAtBeijing + " -> " + arrivalAtNewYork);
        
        // Test:
        if (!LocalDateTime.of(2019, 10, 15, 14, 20, 0)
                .equals(calculateArrivalAtNY(LocalDateTime.of(2019, 10, 15, 13, 0, 0), 13, 20))) {
            System.err.println("Test failed!");
        } else if (!LocalDateTime.of(2019, 11, 15, 13, 20, 0)
                .equals(calculateArrivalAtNY(LocalDateTime.of(2019, 11, 15, 13, 0, 0), 13, 20))) {
            System.err.println("Test failed!");
        }
    }

    static LocalDateTime calculateArrivalAtNY(LocalDateTime bj, int h, int m) {
        return bj; // Implementation needed
    }
}

Hint: ZonedDateTime still provides operations like plusDays() for adding or subtracting time.

Summary

ZonedDateTime represents date and time with a time zone, making it useful for time zone conversions.

You can convert between ZonedDateTime and LocalDateTime.

ZonedDateTime has loaded