1. Introduction
Java 8 introduced, through JSR 310, a complete overhaul of the Date/Time API by providing new, more advanced classes for Date processing. OffsetDateTime is one such class that we will focus on in this article.
2. What is an OffsetDateTime?
OffsetDateTime is a class from the java.time
package. The class represents both a date and a time, in terms of date and time fields (year, month, day, hour, minute, second, nanosecond), plus the offset from UTC/Greenwich. For example, the value “2024-05-06T22:52:15.962090600+02:00” can be stored in an OffsetDateTime.
The ZonedDateTime is covered in a separate article.
The main particularity of OffsetDateTime is that it is immutable and thread-safe.
3. Creating an OffsetDateTime
There are two main ways of creating an OffsetDateTime in Java. The first way is by using the OffsetDateTime.now()
methods and the second way is with the OffsetDateTime.of()
methods.
3.1. Using OffsetDateTime.now()
Methods
You can create an OffsetDateTime object with the current date and time in this way:
OffsetDateTime now = OffsetDateTime.now();//2024-05-05T14:05:46.113681500+02:00
This will query the system clock in the default timezone.
Optionally, you can provide a custom Clock to the now()
method:
Clock clock = Clock.systemDefaultZone();
OffsetDateTime now = OffsetDateTime.now(clock);
It is a best practice to pass a Clock into any method that requires the current instant. This has the advantage of making your code more testable.
Furthermore, if you need to construct an offset date for a specific TimeZone, you can pass a ZoneId object to the now()
method:
ZoneId zoneId = ZoneId.of("America/Toronto");
OffsetDateTime now = OffsetDateTime.now(zoneId);//2024-05-05T08:05:46.113681500-04:00
3.2. Using OffsetDateTime.of()
Methods
You can also create an OffsetDateTime object by providing values for the year, month, day, hour, minute, second, nanosecond, and offset fields:
ZoneOffset offset = ZoneOffset.of("+2");
OffsetDateTime offsetDateTime = OffsetDateTime.of(2024,5,1,13,30,10,5,offset);//2024-05-01T13:30:10.000000005+02:00
Alternatively, you can send a LocalDate
, a LocalTime
, and a ZoneOffset
objects to the OffsetDateTime.of()
method:
LocalDate date = LocalDate.of(2024,5,1);
LocalTime time = LocalTime.of(13,30,10,5);
ZoneOffset offset = ZoneOffset.of("+2");
OffsetDateTime offsetDateTime = OffsetDateTime.of(date,time,offset);//2024-05-01T13:30:10.000000005+02:00
Lastly, the OffsetDateTime.of()
can take a LocalDateTime
and a ZoneOffset
objects:
LocalDateTime dateTime = LocalDateTime.of(2024,5,1,13,30,10,5);
ZoneOffset offset = ZoneOffset.of("+2");
OffsetDateTime offsetDateTime = OffsetDateTime.of(dateTime,offset);//2024-05-01T13:30:10.000000005+02:00
All these factory methods will throw a DateTimeException if the value of any field is out of range, or if the day-of-month is invalid for the month-year.
4. Formatting an OffsetDateTime
By default, the OffsetDateTime is formatted using the ISO-8601 date format. You can use a different format by passing a DateTimeFormatter object to the format()
method:
ZoneOffset offset = ZoneOffset.of("+2");
OffsetDateTime offsetDateTime = OffsetDateTime.of(2024,5,1,13,30,10,5,offset);//2024-05-01T13:30:10.000000005+02:00
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy hh:mm a XXX");
String formattedOffsetDateTime = offsetDateTime.format(formatter);// 01/05/2024 01:30 PM +02:00
Refer to the Official DateTimeFormatter Javadoc for the different formatting options.
5. Parsing from String to OffsetDateTime
Assuming that you have a zoned datetime in ISO-8601 date format and want to build an OffsetDateTime out of it, you can use the parse()
method in this way:
String myOffsetDateTime = "2024-05-01T13:30:10.000000005+02:00";// ISO-8601 date format
OffsetDateTime offsetDateTime = OffsetDateTime.parse(myOffsetDateTime);// 2024-05-01T13:30:10.000000005+02:00
Moreover, if the zoned datetime is in a different format, you can pass a custom DateTimeFormatter to the parse()
method:
String myOffsetDateTime = "01/05/2024 01:30 PM +02:00";//Custom format
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy hh:mm a XXX");
OffsetDateTime offsetDateTime = OffsetDateTime.parse(myOffsetDateTime, formatter);// 2024-05-01T13:30+02:00
Java will throw a DateTimeParseException if it is not able to parse the String with the given datetime format.
6. Operating on an OffsetDateTime
6.1. Comparing two OffsetDateTime objects
You can use isAfter()
, isBefore()
, and isEqual
methods to compare two OffsetDateTime objects:
ZoneOffset offset = ZoneOffset.of("+2");
OffsetDateTime firstOffsetDateTime = OffsetDateTime.of(2024,5,1,13,30,0,0,offset);
OffsetDateTime secondOffsetDateTime = OffsetDateTime.of(2024,5,1,13,27,0,0,offset);
OffsetDateTime thirdOffsetDateTime = OffsetDateTime.of(2024,5,1,13,33,0,0,offset);
OffsetDateTime fourthOffsetDateTime = OffsetDateTime.of(2024,5,1,13,30,0,0,offset);
boolean test1 = firstOffsetDateTime.isAfter(secondOffsetDateTime);//true
boolean test2 = firstOffsetDateTime.isBefore(thirdOffsetDateTime);//true
boolean test3 = firstOffsetDateTime.isEqual(fourthOffsetDateTime);//true
Since the OffsetDateTime class implements the Comparable<E>
interface, you may also use the compareTo()
method:
ZoneOffset offset = ZoneOffset.of("+2");
OffsetDateTime firstOffsetDateTime = OffsetDateTime.of(2024,5,1,13,30,0,0,offset);
OffsetDateTime secondOffsetDateTime = OffsetDateTime.of(2024,5,1,13,27,0,0,offset);
OffsetDateTime thirdOffsetDateTime = OffsetDateTime.of(2024,5,1,13,33,0,0,offset);
int test1 = firstOffsetDateTime.compareTo(secondOffsetDateTime);//A positive number
int test2 = firstOffsetDateTime.compareTo(thirdOffsetDateTime);//A negative number
Lastly, you should know that the OffsetDateTime class also overrides the equals()
method and provides a convenient way to check the equality of two dates:
ZoneOffset offset = ZoneOffset.of("+2");
OffsetDateTime firstOffsetDateTime = OffsetDateTime.of(2024,5,1,13,30,0,0,offset);
OffsetDateTime secondOffsetDateTime = OffsetDateTime.of(2024,5,1,13,27,0,0,offset);
OffsetDateTime thirdOffsetDateTime = OffsetDateTime.of(2024,5,1,13,30,0,0,offset);
boolean test1 = firstOffsetDateTime.equals(secondOffsetDateTime);// false
boolean test2 = firstOffsetDateTime.equals(thirdOffsetDateTime);// true
6.2. Temporal Arithmetic with OffsetDateTime objects
The OffsetDateTime class provides plusXXX()
and minusXXX()
methods to increment and decrement the object field values. Since the OffsetDateTime is immutable, all these methods return a copy of the original object with the given fields updated.
ZoneOffset offset = ZoneOffset.of("+2");
OffsetDateTime offsetDateTime = OffsetDateTime.of(2024,5,1,13,30,0,0,offset);// 2024-05-01T13:30+02:00
OffsetDateTime nextYear = offsetDateTime.plusYears(1);//2025-05-01T13:30+02:00
OffsetDateTime previousYear = offsetDateTime.minusYears(1);//2023-05-01T13:30+02:00
OffsetDateTime nextMonth = offsetDateTime.plusMonths(1);//2024-06-01T13:30+02:00
OffsetDateTime previousMonth = offsetDateTime.minusMonths(1);//2024-04-01T13:30+02:00
OffsetDateTime nextDay = offsetDateTime.plusDays(1);//2024-05-02T13:30+02:00
OffsetDateTime previousDay = offsetDateTime.minusDays(1);//2024-04-30T13:30+02:00
OffsetDateTime nextHour = offsetDateTime.plusHours(1);//2024-05-01T14:30+02:00
OffsetDateTime previousHour = offsetDateTime.minusHours(1);//2024-05-01T12:30+02:00
OffsetDateTime nextMinute = offsetDateTime.plusMinutes(1);//2024-05-01T13:31+02:00
OffsetDateTime previousMinute = offsetDateTime.minusMinutes(1);//2024-05-01T13:29+02:00
7. Conclusion
In this tutorial, you learned about the OffsetDateTime class in Java.
8. References
1) OCP Oracle Certified Professional Java SE 17 by Khalil A. Mughal and Vasily A. Strelnikov
2) Oracle Java Documentation