Java ZonedDateTime Class

ZonedDateTime is an important class in the date-time API (java.time package) introduced in Java 8; it represents a date and time with a time zone. This class combines LocalDateTime and ZoneId to precisely represent a point in time in a specific time zone.

Main Features

  • Contains the date (year, month, day)
  • Contains the time (hour, minute, second, nanosecond)
  • Contains time zone information
  • Is an immutable and thread-safe class
  • Supports time zone conversion and automatic daylight saving time adjustment

Ways to Create ZonedDateTime

1. Creating with the current time

Example

// Get the current date and time in the system default time zone
ZonedDateTime now = ZonedDateTime.now();

// Get the current date and time in the specified time zone
ZonedDateTime nowInTokyo = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));

2. Creating from components

Example

// Specify year, month, day, hour, minute, second, and time zone
ZonedDateTime customDateTime = ZonedDateTime.of(
    2023, 12, 25, 15, 30, 0, 0,
    ZoneId.of("America/New_York")
);

3. Combining LocalDateTime and ZoneId

Example

LocalDateTime localDateTime = LocalDateTime.of(2023, 6, 15, 10, 30);
ZoneId zoneId = ZoneId.of("Europe/Paris");
ZonedDateTime parisTime = ZonedDateTime.of(localDateTime, zoneId);

Common Operation Methods

1. Getting time information

Example

ZonedDateTime zdt = ZonedDateTime.now();

int year = zdt.getYear();          // Year
Month month = zdt.getMonth();      // Month
int day = zdt.getDayOfMonth();     // Day
int hour = zdt.getHour();          // Hour
int minute = zdt.getMinute();      // Minute
int second = zdt.getSecond();      // Second
ZoneId zone = zdt.getZone();       // Time zone

2. Adding and subtracting time

Example

ZonedDateTime zdt = ZonedDateTime.now();

// Add 1 day
ZonedDateTime tomorrow = zdt.plusDays(1);

// Subtract 2 hours
ZonedDateTime twoHoursEarlier = zdt.minusHours(2);

// Add 3 weeks
ZonedDateTime threeWeeksLater = zdt.plusWeeks(3);

3. Time zone conversion

Example

ZonedDateTime tokyoTime = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));

// Convert to New York time
ZonedDateTime newYorkTime = tokyoTime.withZoneSameInstant(ZoneId.of("America/New_York"));

// Convert to UTC time
ZonedDateTime utcTime = tokyoTime.withZoneSameInstant(ZoneOffset.UTC);

Practical Application Examples

1. Calculating the time difference between two time zones

Example

ZonedDateTime londonTime = ZonedDateTime.now(ZoneId.of("Europe/London"));
ZonedDateTime sydneyTime = ZonedDateTime.now(ZoneId.of("Australia/Sydney"));

// Calculate the hour difference
long hoursBetween = ChronoUnit.HOURS.between(londonTime, sydneyTime);
System.out.println("Current time difference between London and Sydney: " + hoursBetween + "hours");

2. Handling meeting times across time zones

Example

// The meeting time in New York is 3 PM
ZonedDateTime meetingTimeNY = ZonedDateTime.of(
    LocalDate.now(),
    LocalTime.of(15, 0),
    ZoneId.of("America/New_York")
);

// Convert to Tokyo time
ZonedDateTime meetingTimeTokyo = meetingTimeNY.withZoneSameInstant(ZoneId.of("Asia/Tokyo"));
System.out.println("Tokyo attendees should be there at local time: " + meetingTimeTokyo);

3. Daylight saving time handling

Example

// Times before and after daylight saving time transition in New York
ZonedDateTime beforeDST = ZonedDateTime.of(
    LocalDateTime.of(2023, 3, 11, 1, 30),
    ZoneId.of("America/New_York")
);

ZonedDateTime afterDST = beforeDST.plusHours(1);
System.out.println("Actual time difference: " +
    Duration.between(beforeDST, afterDST).toHours() + "hours");

Converting ZonedDateTime and Other Date-Time Classes

1. Converting to Instant

Example

ZonedDateTime zdt = ZonedDateTime.now();
Instant instant = zdt.toInstant();  // Convert to UTC timestamp

2. Converting to LocalDateTime

Example

ZonedDateTime zdt = ZonedDateTime.now();
LocalDateTime ldt = zdt.toLocalDateTime();  // Loses time zone information

3. Creating from Instant

Example

Instant instant = Instant.now();
ZonedDateTime zdt = instant.atZone(ZoneId.of("Asia/Shanghai"));

Comprehensive Example

Example

import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;

public class ZonedDateTimeDemo {
    public static void main(String[] args) {
        // 1. Get the current time in the current time zone
        ZonedDateTime now = ZonedDateTime.now();
        System.out.println("Current time zone time: " + now);
       
        // 2. Get the current time in the specified time zone
        ZonedDateTime tokyoTime = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
        System.out.println("Tokyo time: " + tokyoTime);
       
        // 3. Create a specific date-time with a time zone
        ZonedDateTime specificTime = ZonedDateTime.of(
            2023, 5, 15, 10, 30, 0, 0,
            ZoneId.of("America/New_York")
        );
        System.out.println("Specific time in New York: " + specificTime);
       
        // 4. Time zone conversion
        ZonedDateTime londonTime = specificTime.withZoneSameInstant(ZoneId.of("Europe/London"));
        System.out.println("Corresponding London time: " + londonTime);
       
        // 5. Formatting output
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
        System.out.println("Formatted time: " + now.format(formatter));
       
        // 6. Get information for each component
        System.out.println("Time zone: " + now.getZone());
        System.out.println("Year: " + now.getYear());
        System.out.println("Month: " + now.getMonth());
        System.out.println("Hour: " + now.getHour());
    }
}

The output is similar to the following:

当前时区时间: 2025-05-01T11:29:07.411467+08:00[Asia/Shanghai]
东京时间: 2025-05-01T12:29:07.417938+09:00[Asia/Tokyo]
纽约特定时间: 2023-05-15T10:30-04:00[America/New_York]
对应的伦敦时间: 2023-05-15T15:30+01:00[Europe/London]
格式化时间: 2025-05-01 11:29:07 CST
时区: Asia/Shanghai
年份: 2025
月份: MAY
小时: 11

Best Practices

  1. Storage and transmission: When storing in a database or transmitting over a network, it is recommended to use Instant or ZonedDateTime in UTC time
  2. Display: Convert to the local time zone only when displaying in the user interface
  3. Comparison: When comparing times in different time zones, first convert them to the same time zone or Instant
  4. Daylight saving time: Always use the full time zone ID (e.g., "America/New_York") instead of a simple offset (e.g., "-05:00")

ZonedDateTime is a powerful tool for handling time zone-sensitive applications; using it correctly can avoid many common date-time problems.

Static Factory Methods

Method Description Example
static ZonedDateTime now() Get the current date-time in the current time zone ZonedDateTime.now()
static ZonedDateTime now(ZoneId zone) Get the current date-time in the specified time zone ZonedDateTime.now(ZoneId.of("Asia/Shanghai"))
static ZonedDateTime of(int year, int month, int day, int hour, int minute, int second, int nano, ZoneId zone) Create with specified parameters ZonedDateTime.of(2023, 6, 15, 14, 30, 0, 0, ZoneId.of("GMT+8"))
static ZonedDateTime of(LocalDate date, LocalTime time, ZoneId zone) Create by combining LocalDate, LocalTime, and time zone ZonedDateTime.of(LocalDate.now(), LocalTime.now(), ZoneId.systemDefault())
static ZonedDateTime of(LocalDateTime localDateTime, ZoneId zone) Create from LocalDateTime and time zone ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("America/New_York"))
static ZonedDateTime ofInstant(Instant instant, ZoneId zone) Create from Instant and time zone ZonedDateTime.ofInstant(Instant.now(), ZoneId.of("UTC"))
static ZonedDateTime parse(CharSequence text) Parse from a string ZonedDateTime.parse("2023-06-15T14:30:45+08:00[Asia/Shanghai]")
static ZonedDateTime parse(CharSequence text, DateTimeFormatter formatter) Parse using a specified format ZonedDateTime.parse("2023-06-15 14:30 CST", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm z"))

Getting Date-Time Information

Method Description Example
int getYear() Get the year 2023
Month getMonth() Get the month (Month enum) Month.JUNE
int getMonthValue() Get the month value (1-12) 6
int getDayOfMonth() Get the day of the month 15
int getDayOfYear() Get the day of the year 166
DayOfWeek getDayOfWeek() Get the day of the week (DayOfWeek enum) DayOfWeek.THURSDAY
int getHour() Get the hour (0-23) 14
int getMinute() Get the minute (0-59) 30
int getSecond() Get the second (0-59) 45
int getNano() Get the nanosecond 0
ZoneId getZone() Get the time zone Asia/Shanghai
ZoneOffset getOffset() Get the time zone offset +08:00

Date-Time Operations

Method Description Example
ZonedDateTime plusDays(long days) Add days zdt.plusDays(5)
ZonedDateTime plusHours(long hours) Add hours zdt.plusHours(2)
ZonedDateTime plusMinutes(long minutes) Add minutes zdt.plusMinutes(30)
ZonedDateTime plusSeconds(long seconds) Add seconds zdt.plusSeconds(45)
ZonedDateTime plusNanos(long nanos) Add nanoseconds zdt.plusNanos(1000000)
ZonedDateTime minusDays(long days) Subtract days zdt.minusDays(5)
ZonedDateTime minusHours(long hours) Subtract hours zdt.minusHours(2)
ZonedDateTime minusMinutes(long minutes) Subtract minutes zdt.minusMinutes(30)
ZonedDateTime minusSeconds(long seconds) Subtract seconds zdt.minusSeconds(45)
ZonedDateTime minusNanos(long nanos) Subtract nanoseconds zdt.minusNanos(1000000)
ZonedDateTime withYear(int year) Modify the year zdt.withYear(2024)
ZonedDateTime withMonth(int month) Modify the month zdt.withMonth(12)
ZonedDateTime withDayOfMonth(int day) Modify the day of the month zdt.withDayOfMonth(1)
ZonedDateTime withHour(int hour) Modify the hour zdt.withHour(0)
ZonedDateTime withMinute(int minute) Modify the minute zdt.withMinute(0)
ZonedDateTime withSecond(int second) Modify the second zdt.withSecond(0)
ZonedDateTime withNano(int nano) Modify the nanosecond zdt.withNano(0)
ZonedDateTime withZoneSameInstant(ZoneId zone) Convert time zone (keeping the same instant) zdt.withZoneSameInstant(ZoneId.of("UTC"))
ZonedDateTime withZoneSameLocal(ZoneId zone) Convert time zone (keeping the local time) zdt.withZoneSameLocal(ZoneId.of("UTC"))

Conversion Methods

Method Description Example
LocalDate toLocalDate() Convert to LocalDate zdt.toLocalDate()
LocalTime toLocalTime() Convert to LocalTime zdt.toLocalTime()
LocalDateTime toLocalDateTime() Convert to LocalDateTime zdt.toLocalDateTime()
OffsetDateTime toOffsetDateTime() Convert to OffsetDateTime zdt.toOffsetDateTime()
Instant toInstant() Convert to Instant zdt.toInstant()

Comparison Methods

Method Description Example
boolean isAfter(ChronoZonedDateTime<?> other) Whether after the specified date-time zdt1.isAfter(zdt2)
boolean isBefore(ChronoZonedDateTime<?> other) Whether before the specified date-time zdt1.isBefore(zdt2)
boolean isEqual(ChronoZonedDateTime<?> other) Whether equal to the specified date-time zdt1.isEqual(zdt2)
int compareTo(ChronoZonedDateTime<?> other) Compare two date-times zdt1.compareTo(zdt2)

Formatting and String Conversion

Methods Description Example
String format(DateTimeFormatter formatter) Format as string zdt.format(DateTimeFormatter.ISO_ZONED_DATE_TIME)
String toString() Convert to ISO format string "2023-06-15T14:30:45+08:00[Asia/Shanghai]"
Other extensions