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"));
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")
);
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);
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
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);
// 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);
// 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");
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);
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");
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
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
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"));
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());
}
}
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
- Storage and transmission: When storing in a database or transmitting over a network, it is recommended to use Instant or ZonedDateTime in UTC time
- Display: Convert to the local time zone only when displaying in the user interface
- Comparison: When comparing times in different time zones, first convert them to the same time zone or Instant
- 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]" |