Java ZonedDateTime Tutorial with Examples

ZonedDateTime class represent a date-time with a time-zone in the ISO-8601 calendar system, such as 2016-05-16T10:15:30+01:00 Asia/Singapore. This class is immutable and thread-safe, stores all date and time fields, to a precision of nanoseconds, and a time-zone, with a zone offset used to handle ambiguous local date-times.

Creating a ZonedDateTime

We can create a ZonedDateTime in several ways:

The time zones are represented by the ZoneId class. You can create a ZoneId object using the ZoneId.now() method.

ZonedDateTimeInitExample.java
import java.time.Clock;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;

public class ZonedDateTimeInitExample {

    public static void main(String[] args) {
        ZonedDateTime zonedDT1 = ZonedDateTime.now();
        System.out.println("ZonedDateTime1 : " + zonedDT1);

        ZonedDateTime zonedDT2 = ZonedDateTime.now(Clock.systemUTC());
        System.out.println("ZonedDateTime2 : " + zonedDT2);
        
        ZonedDateTime zonedDT3 = ZonedDateTime.now(ZoneId.of("Asia/Jakarta"));
        System.out.println("ZonedDateTime3 : " + zonedDT3);
        
        ZonedDateTime zonedDT4 = ZonedDateTime.of(1980, 4, 9, 20, 15, 45, 345875000, ZoneId.systemDefault());
        System.out.println("ZonedDateTime4 : " + zonedDT4);
        
        ZonedDateTime zonedDT5 = ZonedDateTime.of(LocalDate.now(), LocalTime.of(15, 50, 25), ZoneId.systemDefault());
        System.out.println("ZonedDateTime5 : " + zonedDT5);
        
        ZonedDateTime zonedDT6 = ZonedDateTime.of(LocalDateTime.now(), ZoneId.systemDefault());
        System.out.println("ZonedDateTime6 : " + zonedDT6);
        
        ZonedDateTime zonedDT7 = ZonedDateTime.ofInstant(Instant.now(), ZoneId.systemDefault());
        System.out.println("ZonedDateTime7 : " + zonedDT7);
        
        ZonedDateTime zonedDT8 = ZonedDateTime.ofInstant(LocalDateTime.now(), ZoneOffset.UTC, ZoneId.systemDefault());
        System.out.println("ZonedDateTime8 : " + zonedDT8);
        
        ZonedDateTime zonedDT9 = ZonedDateTime.ofLocal(LocalDateTime.now(), ZoneId.systemDefault(), ZoneOffset.UTC);
        System.out.println("ZonedDateTime9 : " + zonedDT9);
        
        ZonedDateTime zonedDT10 = ZonedDateTime.ofStrict(LocalDateTime.now(), ZoneOffset.ofHours(8), ZoneId.of("Asia/Singapore"));
        System.out.println("ZonedDateTime10: " + zonedDT10);
        
        ZonedDateTime zonedDT11 = ZonedDateTime.parse("2017-10-10T18:30:45+01:00[Europe/London]");
        System.out.println("ZonedDateTime11: " + zonedDT11);
        
        ZonedDateTime zonedDT12 = ZonedDateTime.parse("2018-04-22T08:40:15+10:00[Australia/Sydney]", DateTimeFormatter.ISO_DATE_TIME);
        System.out.println("ZonedDateTime12: " + zonedDT12);
    }
}
                    

ZonedDateTime1 : 2019-08-27T00:12:55.333+08:00[Asia/Singapore]
ZonedDateTime2 : 2019-08-26T16:12:55.334Z
ZonedDateTime3 : 2019-08-26T23:12:55.334+07:00[Asia/Jakarta]
ZonedDateTime4 : 1980-04-09T20:15:45.345875+07:30[Asia/Singapore]
ZonedDateTime5 : 2019-08-27T15:50:25+08:00[Asia/Singapore]
ZonedDateTime6 : 2019-08-27T00:12:55.335+08:00[Asia/Singapore]
ZonedDateTime7 : 2019-08-27T00:12:55.335+08:00[Asia/Singapore]
ZonedDateTime8 : 2019-08-27T08:12:55.335+08:00[Asia/Singapore]
ZonedDateTime9 : 2019-08-27T00:12:55.335+08:00[Asia/Singapore]
ZonedDateTime10: 2019-08-27T00:12:55.335+08:00[Asia/Singapore]
ZonedDateTime11: 2017-10-10T18:30:45+01:00[Europe/London]
ZonedDateTime12: 2018-04-22T08:40:15+10:00[Australia/Sydney]

Getting Information from a ZonedDateTime

Following methods can be used to access Date and/or Time information from a ZonedDateTime:

And following methods can be used to get another class (or convert) from a ZonedDateTime instance:

ZonedDateTimeInfoExample.java
import java.time.ZonedDateTime;
import java.time.temporal.ChronoField;

public class ZonedDateTimeInfoExample {
    
    public static void main(String[] args) {
        ZonedDateTime zonedDT = ZonedDateTime.now();
        System.out.println("ZonedDateTime     : " + zonedDT);
        System.out.println("DayOfMonth        : " + zonedDT.getDayOfMonth());
        System.out.println("MonthValue        : " + zonedDT.getMonthValue());
        System.out.println("Year              : " + zonedDT.getYear());
        
        System.out.println("Hour              : " + zonedDT.getHour());
        System.out.println("Minute            : " + zonedDT.getMinute());
        System.out.println("Second            : " + zonedDT.getSecond());
        System.out.println("Nano              : " + zonedDT.getNano());
        
        System.out.println("DayOfWeek         : " + zonedDT.getDayOfWeek());
        System.out.println("Month             : " + zonedDT.getMonth());
        System.out.println("DayOfYear         : " + zonedDT.getDayOfYear());

        System.out.println("DAY_OF_MONTH      : " + zonedDT.get(ChronoField.DAY_OF_MONTH));        
        System.out.println("MONTH_OF_YEAR     : " + zonedDT.get(ChronoField.MONTH_OF_YEAR));
        System.out.println("YEAR              : " + zonedDT.get(ChronoField.YEAR));
        
        System.out.println("HOUR_OF_DAY       : " + zonedDT.get(ChronoField.HOUR_OF_DAY));        
        System.out.println("MINUTE_OF_HOUR    : " + zonedDT.get(ChronoField.MINUTE_OF_HOUR));
        System.out.println("SECOND_OF_MINUTE  : " + zonedDT.get(ChronoField.SECOND_OF_MINUTE));
        
        System.out.println("MINUTE_OF_DAY     : " + zonedDT.getLong(ChronoField.MINUTE_OF_DAY));
        System.out.println("SECOND_OF_DAY     : " + zonedDT.getLong(ChronoField.SECOND_OF_DAY));
        
        System.out.println("Chronology        : " + zonedDT.getChronology()); 
        
        System.out.println("toEpochSecond()   : " + zonedDT.toEpochSecond());
        System.out.println("toInstant()       : " + zonedDT.toInstant());
        System.out.println("toLocalDate()     : " + zonedDT.toLocalDate());
        System.out.println("toLocalDateTime() : " + zonedDT.toLocalDateTime());
        System.out.println("toLocalTime()     : " + zonedDT.toLocalTime());
        System.out.println("toOffsetDateTime(): " + zonedDT.toOffsetDateTime());
    }
}
                    

ZonedDateTime     : 2019-08-27T01:14:16.255+08:00[Asia/Singapore]
DayOfMonth        : 27
MonthValue        : 8
Year              : 2019
Hour              : 1
Minute            : 14
Second            : 16
Nano              : 255000000
DayOfWeek         : TUESDAY
Month             : AUGUST
DayOfYear         : 239
DAY_OF_MONTH      : 27
MONTH_OF_YEAR     : 8
YEAR              : 2019
HOUR_OF_DAY       : 1
MINUTE_OF_HOUR    : 14
SECOND_OF_MINUTE  : 16
MINUTE_OF_DAY     : 74
SECOND_OF_DAY     : 4456
Chronology        : ISO
toEpochSecond()   : 1566839656
toInstant()       : 2019-08-26T17:14:16.255Z
toLocalDate()     : 2019-08-27
toLocalDateTime() : 2019-08-27T01:14:16.255
toLocalTime()     : 01:14:16.255
toOffsetDateTime(): 2019-08-27T01:14:16.255+08:00

Add/Subtract Operations on ZonedDateTime

Following methods used for add/subtract operation in a ZonedDateTime:

ZonedDateTimeAddSubstractExample.java
import java.time.Duration;
import java.time.ZonedDateTime;
import java.time.Period;
import java.time.temporal.ChronoUnit;

public class ZonedDateTimeAddSubstractExample {

    public static void main(String[] args) {
        ZonedDateTime zonedDT = ZonedDateTime.parse("1984-08-13T18:30:15+08:00[Asia/Singapore]");
        System.out.println("ZonedDateTime       : " + zonedDT);
        
        // Adding/subtracting days
        System.out.println("10 days before      : " + zonedDT.minusDays(10));
        System.out.println("15 days later       : " + zonedDT.plusDays(15));
        
        // Adding/subtracting months
        System.out.println("Minus 4 months      : " + zonedDT.minusMonths(4));
        System.out.println("Plus 5 months       : " + zonedDT.plusMonths(5));
        
        // Adding/subtracting weeks
        System.out.println("Minus 20 weeks      : " + zonedDT.minusWeeks(20));
        System.out.println("Plus 30 weeks       : " + zonedDT.plusWeeks(30));
        
        // Adding/subtracting years
        System.out.println("Minus 12 years      : " + zonedDT.minusYears(12));
        System.out.println("Plus 4 years        : " + zonedDT.plusYears(4));
        
        // Adding/subtracting hours
        System.out.println("12 hours before     : " + zonedDT.minusHours(12));
        System.out.println("6 hours later       : " + zonedDT.plusHours(6));
        
        // Adding/subtracting minutes
        System.out.println("Minus 40 minutes    : " + zonedDT.minusMinutes(40));
        System.out.println("Plus 15 minutes     : " + zonedDT.plusMinutes(15));
        
        // Adding/subtracting seconds
        System.out.println("Minus 30 seconds    : " + zonedDT.minusSeconds(30));
        System.out.println("Plus 20 seconds     : " + zonedDT.plusSeconds(20));
        
        // Adding/subtracting Nanos
        System.out.println("Minus 20000 nanos   : " + zonedDT.minusNanos(20000));
        System.out.println("Plus 340000 nanos   : " + zonedDT.plusNanos(340000));
        
        // Using DAYS
        System.out.println("30 days before      : " + zonedDT.minus(30, ChronoUnit.DAYS));
        // Using WEEKS
        System.out.println("3 weeks before      : " + zonedDT.minus(3, ChronoUnit.WEEKS));
        // Using MONTHS
        System.out.println("6 months later      : " + zonedDT.plus(6, ChronoUnit.MONTHS));
        // Using YEARS
        System.out.println("2 years later       : " + zonedDT.plus(2, ChronoUnit.YEARS));
        
        // Using HOURS
        System.out.println("8 hours before      : " + zonedDT.minus(8, ChronoUnit.HOURS));
        // Using MINUTES
        System.out.println("35 minutes before   : " + zonedDT.minus(35, ChronoUnit.MINUTES));
        // Using SECONDS
        System.out.println("125 seconds later   : " + zonedDT.plus(125, ChronoUnit.SECONDS));
        // Using NANOS
        System.out.println("42357500 nanos later: " + zonedDT.plus(42357500, ChronoUnit.NANOS));
        
        // Using TemporalAmount - Period 
        System.out.println("5 years later       : " + zonedDT.plus(Period.ofYears(5)));
        // Using TemporalAmount - Duration 
        System.out.println("60 days before      : " + zonedDT.minus(Duration.ofDays(60)));
        System.out.println("160 minutes before  : " + zonedDT.minus(Duration.ofMinutes(160)));
        System.out.println("2 hours later       : " + zonedDT.plus(Duration.ofHours(2)));        
    }
}
                    

ZonedDateTime       : 1984-08-13T18:30:15+08:00[Asia/Singapore]
10 days before      : 1984-08-03T18:30:15+08:00[Asia/Singapore]
15 days later       : 1984-08-28T18:30:15+08:00[Asia/Singapore]
Minus 4 months      : 1984-04-13T18:30:15+08:00[Asia/Singapore]
Plus 5 months       : 1985-01-13T18:30:15+08:00[Asia/Singapore]
Minus 20 weeks      : 1984-03-26T18:30:15+08:00[Asia/Singapore]
Plus 30 weeks       : 1985-03-11T18:30:15+08:00[Asia/Singapore]
Minus 12 years      : 1972-08-13T18:30:15+07:30[Asia/Singapore]
Plus 4 years        : 1988-08-13T18:30:15+08:00[Asia/Singapore]
12 hours before     : 1984-08-13T06:30:15+08:00[Asia/Singapore]
6 hours later       : 1984-08-14T00:30:15+08:00[Asia/Singapore]
Minus 40 minutes    : 1984-08-13T17:50:15+08:00[Asia/Singapore]
Plus 15 minutes     : 1984-08-13T18:45:15+08:00[Asia/Singapore]
Minus 30 seconds    : 1984-08-13T18:29:45+08:00[Asia/Singapore]
Plus 20 seconds     : 1984-08-13T18:30:35+08:00[Asia/Singapore]
Minus 20000 nanos   : 1984-08-13T18:30:14.999980+08:00[Asia/Singapore]
Plus 340000 nanos   : 1984-08-13T18:30:15.000340+08:00[Asia/Singapore]
30 days before      : 1984-07-14T18:30:15+08:00[Asia/Singapore]
3 weeks before      : 1984-07-23T18:30:15+08:00[Asia/Singapore]
6 months later      : 1985-02-13T18:30:15+08:00[Asia/Singapore]
2 years later       : 1986-08-13T18:30:15+08:00[Asia/Singapore]
8 hours before      : 1984-08-13T10:30:15+08:00[Asia/Singapore]
35 minutes before   : 1984-08-13T17:55:15+08:00[Asia/Singapore]
125 seconds later   : 1984-08-13T18:32:20+08:00[Asia/Singapore]
42357500 nanos later: 1984-08-13T18:30:15.042357500+08:00[Asia/Singapore]
5 years later       : 1989-08-13T18:30:15+08:00[Asia/Singapore]
60 days before      : 1984-06-14T18:30:15+08:00[Asia/Singapore]
160 minutes before  : 1984-08-13T15:50:15+08:00[Asia/Singapore]
2 hours later       : 1984-08-13T20:30:15+08:00[Asia/Singapore]

Comparing ZonedDateTimes

ZonedDateTime class is implementing interface ChronoZonedDateTime. Following methods can be use to compare two ZonedDateTimes:

LocalDateTimeCompareExample.java
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class LocalDateTimeCompareExample {

    public static void main(String[] args) {
        LocalDateTime localDT1 = LocalDateTime.parse("1979-12-09T09:50:25");
        LocalDateTime localDT2 = LocalDateTime.parse("1980-04-09T09:50:25");
        LocalDateTime localDT3 = LocalDateTime.parse("19791209095025", DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        
        System.out.println("LocalDateTime1 after LocalDateTime2    : " + localDT1.isAfter(localDT2));
        System.out.println("LocalDateTime1 before LocalDateTime2   : " + localDT1.isBefore(localDT2));
        System.out.println("LocalDateTime1 equal LocalDateTime3    : " + localDT1.isEqual(localDT3));
        System.out.println("LocalDateTime2 equal LocalDateTime3    : " + localDT2.isEqual(localDT3));

        System.out.println("LocalDateTime1 compareTo LocalDateTime2: " + localDT1.compareTo(localDT2));
        System.out.println("LocalDateTime2 compareTo LocalDateTime1: " + localDT2.compareTo(localDT1));
        System.out.println("LocalDateTime1 compareTo LocalDateTime3: " + localDT1.compareTo(localDT3));
        System.out.println("LocalDateTime3 compareTo LocalDateTime2: " + localDT3.compareTo(localDT2));
    }
}
                    

LocalDateTime1 after LocalDateTime2    : false
LocalDateTime1 before LocalDateTime2   : true
LocalDateTime1 equal LocalDateTime3    : true
LocalDateTime2 equal LocalDateTime3    : false
LocalDateTime1 compareTo LocalDateTime2: -1
LocalDateTime2 compareTo LocalDateTime1: 1
LocalDateTime1 compareTo LocalDateTime3: 0
LocalDateTime3 compareTo LocalDateTime2: -1

Supported Field and Unit of a ZonedDateTime

Use isSupported(...) to check if a particular field/unit is supported in a ZonedDateTime:

ZonedDateTimeIsSupportedExample.java
import java.time.ZonedDateTime;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;

public class ZonedDateTimeIsSupportedExample {

    public static void main(String[] args) {
        ZonedDateTime zonedDT = ZonedDateTime.now();

        System.out.println("*** ChronoField ***");
        for(ChronoField chronoField : ChronoField.values()){
            System.out.println(chronoField + " is supported:" + zonedDT.isSupported(chronoField));
        }

        System.out.println("\n*** ChronoUnit ***");
        for(ChronoUnit chronoUnit : ChronoUnit.values()){
            System.out.println(chronoUnit + " is supported:" + zonedDT.isSupported(chronoUnit));
        }
    }
}
                    

*** ChronoField ***
NanoOfSecond is supported:true
NanoOfDay is supported:true
MicroOfSecond is supported:true
MicroOfDay is supported:true
MilliOfSecond is supported:true
MilliOfDay is supported:true
SecondOfMinute is supported:true
SecondOfDay is supported:true
MinuteOfHour is supported:true
MinuteOfDay is supported:true
HourOfAmPm is supported:true
ClockHourOfAmPm is supported:true
HourOfDay is supported:true
ClockHourOfDay is supported:true
AmPmOfDay is supported:true
DayOfWeek is supported:true
AlignedDayOfWeekInMonth is supported:true
AlignedDayOfWeekInYear is supported:true
DayOfMonth is supported:true
DayOfYear is supported:true
EpochDay is supported:true
AlignedWeekOfMonth is supported:true
AlignedWeekOfYear is supported:true
MonthOfYear is supported:true
ProlepticMonth is supported:true
YearOfEra is supported:true
Year is supported:true
Era is supported:true
InstantSeconds is supported:true
OffsetSeconds is supported:true

*** ChronoUnit ***
Nanos is supported:true
Micros is supported:true
Millis is supported:true
Seconds is supported:true
Minutes is supported:true
Hours is supported:true
HalfDays is supported:true
Days is supported:true
Weeks is supported:true
Months is supported:true
Years is supported:true
Decades is supported:true
Centuries is supported:true
Millennia is supported:true
Eras is supported:true
Forever is supported:false