ZetCode

Java ZonedDateTime Class

Last modified: April 16, 2025

The java.time.ZonedDateTime class represents a date-time with a timezone. It combines LocalDateTime with ZoneId to handle timezone rules. This class is immutable and thread-safe.

ZonedDateTime is used when timezone context is important. It handles daylight saving time automatically. The class provides precision up to nanoseconds and follows ISO-8601 calendar system.

ZonedDateTime Class Overview

ZonedDateTime provides methods to create, manipulate, and format date-time values. It can convert between timezones and handle daylight saving. The class is part of Java's modern date-time API introduced in Java 8.

public final class ZonedDateTime implements Temporal, ChronoZonedDateTime<LocalDate>, 
    Serializable {
    public static ZonedDateTime now();
    public static ZonedDateTime of(LocalDateTime localDateTime, ZoneId zone);
    public static ZonedDateTime parse(CharSequence text);
    public ZoneId getZone();
    public ZonedDateTime withZoneSameInstant(ZoneId zone);
    public LocalDateTime toLocalDateTime();
    public Instant toInstant();
    public boolean isBefore(ChronoZonedDateTime<?> other);
    public boolean isAfter(ChronoZonedDateTime<?> other);
}

The code above shows key methods of ZonedDateTime. These methods allow timezone-aware date-time operations. The class handles all timezone conversions and daylight saving adjustments automatically.

Creating ZonedDateTime Objects

ZonedDateTime objects can be created in several ways. The most common methods are now for current time and factory methods for specific values. Parsing from strings is also supported.

Main.java
package com.zetcode; 

import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.time.LocalDateTime;

public class Main {

    public static void main(String[] args) {
        
        // Current date-time with timezone
        ZonedDateTime now = ZonedDateTime.now();
        System.out.println("Current ZonedDateTime: " + now);
        
        // Specific timezone
        ZonedDateTime parisTime = ZonedDateTime.now(ZoneId.of("Europe/Paris"));
        System.out.println("Paris time: " + parisTime);
        
        // From LocalDateTime
        LocalDateTime ldt = LocalDateTime.of(2025, 6, 15, 10, 30);
        ZonedDateTime zdt = ZonedDateTime.of(ldt, ZoneId.of("America/New_York"));
        System.out.println("From LocalDateTime: " + zdt);
        
        // From string
        ZonedDateTime parsed = ZonedDateTime.parse("2025-01-01T12:00:00+01:00[Europe/Berlin]");
        System.out.println("Parsed from string: " + parsed);
    }
}

This example shows different ways to create ZonedDateTime objects. The output includes both the date-time and timezone information. Note how timezone affects the displayed time values.

Getting ZonedDateTime Components

ZonedDateTime can be decomposed into its components like year, month, and timezone. These values are useful for display or further calculations. The class provides getter methods for all components.

Main.java
package com.zetcode; 

import java.time.ZonedDateTime;
import java.time.ZoneId;

public class Main {

    public static void main(String[] args) {

        ZonedDateTime zdt = ZonedDateTime.now();
        
        // Get date and time components
        System.out.println("Year: " + zdt.getYear());
        System.out.println("Month: " + zdt.getMonth());
        System.out.println("Day: " + zdt.getDayOfMonth());
        System.out.println("Hour: " + zdt.getHour());
        System.out.println("Minute: " + zdt.getMinute());
        
        // Get timezone information
        ZoneId zone = zdt.getZone();
        System.out.println("Timezone: " + zone.getId());
        
        // Get offset from UTC
        System.out.println("Offset: " + zdt.getOffset());
    }
}

This example demonstrates how to extract components from a ZonedDateTime. The timezone information includes both the zone ID and UTC offset. All components reflect the values in the specified timezone.

Converting Timezones

ZonedDateTime can convert between different timezones while preserving the instant in time. This is useful for displaying the same moment in various locations. The conversion handles daylight saving automatically.

Main.java
package com.zetcode; 

import java.time.ZonedDateTime;
import java.time.ZoneId;

public class Main {

    public static void main(String[] args) {

        ZonedDateTime nyTime = ZonedDateTime.now(ZoneId.of("America/New_York"));
        System.out.println("New York time: " + nyTime);
        
        // Convert to London time
        ZonedDateTime londonTime = nyTime.withZoneSameInstant(ZoneId.of("Europe/London"));
        System.out.println("London time: " + londonTime);
        
        // Convert to Tokyo time
        ZonedDateTime tokyoTime = nyTime.withZoneSameInstant(ZoneId.of("Asia/Tokyo"));
        System.out.println("Tokyo time: " + tokyoTime);
        
        // Keep local time, change only timezone
        ZonedDateTime sameLocal = nyTime.withZoneSameLocal(ZoneId.of("Europe/Paris"));
        System.out.println("Same local time in Paris: " + sameLocal);
    }
}

This example shows timezone conversions with ZonedDateTime. The withZoneSameInstant method changes the timezone while keeping the same instant. withZoneSameLocal keeps the local time values.

Comparing ZonedDateTime

ZonedDateTime objects can be compared chronologically. The comparison considers both the instant in time and the timezone rules. This ensures accurate ordering of events across timezones.

Main.java
package com.zetcode; 

import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.time.Duration;

public class Main {

    public static void main(String[] args) {

        ZonedDateTime nyTime = ZonedDateTime.now(ZoneId.of("America/New_York"));
        ZonedDateTime londonTime = nyTime.withZoneSameInstant(ZoneId.of("Europe/London"));
        ZonedDateTime futureTime = nyTime.plusHours(2);
        
        System.out.println("NY before London: " + nyTime.isBefore(londonTime));
        System.out.println("NY after future: " + nyTime.isAfter(futureTime));
        System.out.println("Compare NY and London: " + nyTime.compareTo(londonTime));
        
        // Time difference between zones
        Duration offsetDiff = Duration.between(nyTime.toLocalTime(), londonTime.toLocalTime());
        System.out.println("Time difference: " + offsetDiff.toHours() + " hours");
    }
}

This example demonstrates comparing ZonedDateTime objects. The comparison methods consider the actual instant in time, not just the local time values. The time difference calculation shows the current offset between timezones.

Working with Daylight Saving Time

ZonedDateTime automatically handles daylight saving time transitions. It adjusts the time values according to the timezone rules. This ensures correct time representation throughout the year.

Main.java
package com.zetcode; 

import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.time.Month;

public class Main {

    public static void main(String[] args) {

        ZoneId nyZone = ZoneId.of("America/New_York");
        
        // Before DST transition (March 10, 2025 1:59 AM)
        ZonedDateTime beforeDST = ZonedDateTime.of(2025, 3, 10, 1, 59, 0, 0, nyZone);
        System.out.println("Before DST: " + beforeDST);
        
        // After DST transition (1 hour later)
        ZonedDateTime afterDST = beforeDST.plusHours(1);
        System.out.println("After DST: " + afterDST);
        
        // Check if DST is in effect
        System.out.println("Is DST: " + afterDST.getZone().getRules().isDaylightSavings(afterDST.toInstant()));
        
        // November DST end
        ZonedDateTime endDST = ZonedDateTime.of(2025, 11, 2, 1, 59, 0, 0, nyZone);
        System.out.println("Before DST end: " + endDST);
        System.out.println("After DST end: " + endDST.plusHours(1));
    }
}

This example shows ZonedDateTime handling daylight saving time transitions. The spring forward and fall back transitions are handled automatically. The DST status can be checked for any specific instant.

Converting to Other Types

ZonedDateTime can be converted to other date-time types like LocalDateTime or Instant. These conversions are useful when timezone information is no longer needed or when working with legacy APIs.

Main.java
package com.zetcode; 

import java.time.ZonedDateTime;
import java.time.LocalDateTime;
import java.time.Instant;
import java.time.OffsetDateTime;

public class Main {

    public static void main(String[] args) {

        ZonedDateTime zdt = ZonedDateTime.now();
        
        // Convert to LocalDateTime (loses timezone)
        LocalDateTime ldt = zdt.toLocalDateTime();
        System.out.println("LocalDateTime: " + ldt);
        
        // Convert to Instant (UTC)
        Instant instant = zdt.toInstant();
        System.out.println("Instant: " + instant);
        
        // Convert to OffsetDateTime (keeps offset but not zone ID)
        OffsetDateTime odt = zdt.toOffsetDateTime();
        System.out.println("OffsetDateTime: " + odt);
        
        // Convert back to ZonedDateTime
        ZonedDateTime back = instant.atZone(zdt.getZone());
        System.out.println("Back to ZonedDateTime: " + back);
    }
}

This example demonstrates conversions between ZonedDateTime and other date-time types. Each conversion serves different purposes depending on whether timezone, offset, or UTC time is needed. The original ZonedDateTime can be reconstructed.

Source

Java ZonedDateTime Class Documentation

In this article, we've covered the essential methods and features of the Java ZonedDateTime class. Understanding these concepts is crucial for accurate timezone handling in modern Java applications.

Author

My name is Jan Bodnar, and I am a dedicated programmer with many years of experience in the field. I began writing programming articles in 2007 and have since authored over 1,400 articles and eight e-books. With more than eight years of teaching experience, I am committed to sharing my knowledge and helping others master programming concepts.

List all Java tutorials.