Java OffsetDateTime Tutorial with Examples

OffsetDateTime class represent a date-time with an offset from UTC/Greenwich in the ISO-8601 calendar system, such as 1980-04-09T10:15:30+07:00. This class is immutable and thread-safe.

OffsetDateTime, ZonedDateTime and Instant all store an instant on the time-line to nanosecond precision. Instant is the simplest, simply representing the instant. OffsetDateTime adds to the instant the offset from UTC/Greenwich, which allows the local date-time to be obtained. ZonedDateTime adds full time-zone rules.

It is intended that ZonedDateTime or Instant is used to model data in simpler applications. OffsetDateTime may be used when modeling date-time concepts in more detail, or when communicating to a database or in a network protocol.

Creating an OffsetDateTime

We can create an OffsetDateTime in several ways:

The time zone offsets are represented by the ZoneOffset class. You can create a ZoneOffset object using the ZoneId.of(...) method.

OffsetDateTimeInitExample.java
import java.time.Clock;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;

public class OffsetDateTimeInitExample {

    public static void main(String[] args) {
        OffsetDateTime offsetDT1 = OffsetDateTime.now();
        System.out.println("OffsetDateTime1: " + offsetDT1);

        OffsetDateTime offsetDT2 = OffsetDateTime.now(Clock.systemUTC());
        System.out.println("OffsetDateTime2: " + offsetDT2);
        
        OffsetDateTime offsetDT3 = OffsetDateTime.now(ZoneId.of("Asia/Jakarta"));
        System.out.println("OffsetDateTime3: " + offsetDT3);
        
        OffsetDateTime offsetDT4 = OffsetDateTime.of(1980, 4, 9, 20, 15, 45, 345875000, ZoneOffset.of("+07:00"));
        System.out.println("OffsetDateTime4: " + offsetDT4);
        
        OffsetDateTime offsetDT5 = OffsetDateTime.of(LocalDate.now(), LocalTime.of(15, 50, 25), ZoneOffset.of("+07:00"));
        System.out.println("OffsetDateTime5: " + offsetDT5);
        
        OffsetDateTime offsetDT6 = OffsetDateTime.of(LocalDateTime.now(), ZoneOffset.of("+07:00"));
        System.out.println("OffsetDateTime6: " + offsetDT6);
        
        OffsetDateTime offsetDT7 = OffsetDateTime.ofInstant(Instant.now(), ZoneId.systemDefault());
        System.out.println("OffsetDateTime7: " + offsetDT7);
        
        OffsetDateTime offsetDT8 = OffsetDateTime.parse("2019-08-31T15:20:30+08:00");
        System.out.println("OffsetDateTime8: " + offsetDT8);
        
        OffsetDateTime offsetDT9 = OffsetDateTime.parse("1980-04-09T08:20:45+07:00", DateTimeFormatter.ISO_OFFSET_DATE_TIME);
        System.out.println("OffsetDateTime9: " + offsetDT9);
    }
}
                    

OffsetDateTime1: 2019-08-31T23:49:05.629+08:00
OffsetDateTime2: 2019-08-31T15:49:05.630Z
OffsetDateTime3: 2019-08-31T22:49:05.630+07:00
OffsetDateTime4: 1980-04-09T20:15:45.345875+07:00
OffsetDateTime5: 2019-08-31T15:50:25+07:00
OffsetDateTime6: 2019-08-31T23:49:05.631+07:00
OffsetDateTime7: 2019-08-31T23:49:05.631+08:00
OffsetDateTime8: 2019-08-31T15:20:30+08:00
OffsetDateTime9: 1980-04-09T08:20:45+07:00

Getting Information from an OffsetDateTime

Following methods can be used to access Date and/or Time information from an OffsetDateTime:

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

OffsetDateTimeInfoExample.java
import java.time.OffsetDateTime;
import java.time.temporal.ChronoField;

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

        System.out.println("DAY_OF_MONTH     : " + offsetDT.get(ChronoField.DAY_OF_MONTH));        
        System.out.println("MONTH_OF_YEAR    : " + offsetDT.get(ChronoField.MONTH_OF_YEAR));
        System.out.println("YEAR             : " + offsetDT.get(ChronoField.YEAR));
        
        System.out.println("HOUR_OF_DAY      : " + offsetDT.get(ChronoField.HOUR_OF_DAY));        
        System.out.println("MINUTE_OF_HOUR   : " + offsetDT.get(ChronoField.MINUTE_OF_HOUR));
        System.out.println("SECOND_OF_MINUTE : " + offsetDT.get(ChronoField.SECOND_OF_MINUTE));
        
        System.out.println("MINUTE_OF_DAY    : " + offsetDT.getLong(ChronoField.MINUTE_OF_DAY));
        System.out.println("SECOND_OF_DAY    : " + offsetDT.getLong(ChronoField.SECOND_OF_DAY));
        
        System.out.println("Offset           : " + offsetDT.getOffset()); 
        
        System.out.println("toEpochSecond()  : " + offsetDT.toEpochSecond());
        System.out.println("toInstant()      : " + offsetDT.toInstant());
        System.out.println("toLocalDate()    : " + offsetDT.toLocalDate());
        System.out.println("toLocalDateTime(): " + offsetDT.toLocalDateTime());
        System.out.println("toLocalTime()    : " + offsetDT.toLocalTime());
        System.out.println("toZonedDateTime(): " + offsetDT.toZonedDateTime());
    }
}
                    

OffsetDateTime   : 2019-09-01T01:32:00.896+08:00
DayOfMonth       : 1
MonthValue       : 9
Year             : 2019
Hour             : 1
Minute           : 32
Second           : 0
Nano             : 896000000
DayOfWeek        : SUNDAY
Month            : SEPTEMBER
DayOfYear        : 244
DAY_OF_MONTH     : 1
MONTH_OF_YEAR    : 9
YEAR             : 2019
HOUR_OF_DAY      : 1
MINUTE_OF_HOUR   : 32
SECOND_OF_MINUTE : 0
MINUTE_OF_DAY    : 92
SECOND_OF_DAY    : 5520
Offset           : +08:00
toEpochSecond()  : 1567272720
toInstant()      : 2019-08-31T17:32:00.896Z
toLocalDate()    : 2019-09-01
toLocalDateTime(): 2019-09-01T01:32:00.896
toLocalTime()    : 01:32:00.896
toZonedDateTime(): 2019-09-01T01:32:00.896+08:00

Add/Subtract Operations on OffsetDateTime

Following methods used for add/subtract operation in an OffsetDateTime:

OffsetDateTimeAddSubstractExample.java
import java.time.Duration;
import java.time.OffsetDateTime;
import java.time.Period;
import java.time.temporal.ChronoUnit;

public class OffsetDateTimeAddSubstractExample {

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

OffsetDateTime      : 1983-07-12T06:30:15+07:00
10 days before      : 1983-07-02T06:30:15+07:00
15 days later       : 1983-07-27T06:30:15+07:00
Minus 4 months      : 1983-03-12T06:30:15+07:00
Plus 5 months       : 1983-12-12T06:30:15+07:00
Minus 20 weeks      : 1983-02-22T06:30:15+07:00
Plus 30 weeks       : 1984-02-07T06:30:15+07:00
Minus 12 years      : 1971-07-12T06:30:15+07:00
Plus 4 years        : 1987-07-12T06:30:15+07:00
12 hours before     : 1983-07-11T18:30:15+07:00
6 hours later       : 1983-07-12T12:30:15+07:00
Minus 40 minutes    : 1983-07-12T05:50:15+07:00
Plus 15 minutes     : 1983-07-12T06:45:15+07:00
Minus 30 seconds    : 1983-07-12T06:29:45+07:00
Plus 20 seconds     : 1983-07-12T06:30:35+07:00
Minus 20000 nanos   : 1983-07-12T06:30:14.999980+07:00
Plus 340000 nanos   : 1983-07-12T06:30:15.000340+07:00
30 days before      : 1983-06-12T06:30:15+07:00
3 weeks before      : 1983-06-21T06:30:15+07:00
6 months later      : 1984-01-12T06:30:15+07:00
2 years later       : 1985-07-12T06:30:15+07:00
8 hours before      : 1983-07-11T22:30:15+07:00
35 minutes before   : 1983-07-12T05:55:15+07:00
125 seconds later   : 1983-07-12T06:32:20+07:00
42357500 nanos later: 1983-07-12T06:30:15.042357500+07:00
60 days before      : 1983-05-13T06:30:15+07:00
160 minutes before  : 1983-07-12T03:50:15+07:00
2 hours later       : 1983-07-12T08:30:15+07:00
5 years before      : 1978-07-12T06:30:15+07:00
8 months later      : 1984-03-12T06:30:15+07:00

Comparing OffsetDateTimes

Following methods can be use to compare two OffsetDateTimes:

OffsetDateTimeCompareExample.java
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;

public class OffsetDateTimeCompareExample {

    public static void main(String[] args) {
        OffsetDateTime offsetDT1 = OffsetDateTime.parse("1979-12-09T09:50:25+07:00");
        OffsetDateTime offsetDT2 = OffsetDateTime.parse("1980-04-09T09:50:25+08:00");
        
        LocalDateTime localDT = LocalDateTime.parse("19791209095025", DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        OffsetDateTime offsetDT3 = OffsetDateTime.of(localDT, ZoneOffset.of("+07:00"));
        
        System.out.println("OffsetDateTime1 after OffsetDateTime2    : " + offsetDT1.isAfter(offsetDT2));
        System.out.println("OffsetDateTime1 before OffsetDateTime2   : " + offsetDT1.isBefore(offsetDT2));
        System.out.println("OffsetDateTime1 equal OffsetDateTime3    : " + offsetDT1.isEqual(offsetDT3));
        System.out.println("OffsetDateTime2 equal OffsetDateTime3    : " + offsetDT2.isEqual(offsetDT3));

        System.out.println("OffsetDateTime1 compareTo OffsetDateTime2: " + offsetDT1.compareTo(offsetDT2));
        System.out.println("OffsetDateTime2 compareTo OffsetDateTime1: " + offsetDT2.compareTo(offsetDT1));
        System.out.println("OffsetDateTime1 compareTo OffsetDateTime3: " + offsetDT1.compareTo(offsetDT3));
        System.out.println("OffsetDateTime3 compareTo OffsetDateTime2: " + offsetDT3.compareTo(offsetDT2));
    }
}
                    

OffsetDateTime1 after OffsetDateTime2    : false
OffsetDateTime1 before OffsetDateTime2   : true
OffsetDateTime1 equal OffsetDateTime3    : true
OffsetDateTime2 equal OffsetDateTime3    : false
OffsetDateTime1 compareTo OffsetDateTime2: -1
OffsetDateTime2 compareTo OffsetDateTime1: 1
OffsetDateTime1 compareTo OffsetDateTime3: 0
OffsetDateTime3 compareTo OffsetDateTime2: -1

Supported Field and Unit of an OffsetDateTime

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

OffsetDateTimeIsSupportedExample.java
import java.time.OffsetDateTime;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;

public class OffsetDateTimeIsSupportedExample {

    public static void main(String[] args) {
        OffsetDateTime offsetDT = OffsetDateTime.now();

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

        System.out.println("\n*** ChronoUnit ***");
        for(ChronoUnit chronoUnit : ChronoUnit.values()){
            System.out.println(chronoUnit + " is supported:" + offsetDT.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