1. Introduction
When dealing with date/time in Java, DateTimeException is an exception you’ll probably encounter. In this article, you’ll learn how to fix this exception. You’ll also learn some best practices for avoiding the DateTimeException.
2. What Java Says about DateTimeException
According to the Javadoc, a DateTimeException indicates problems with creating, querying, and manipulating date-time objects. Most of the time, this exception will occur when you provide a value out of the supported range for the date and time fields.
3. How to Reproduce
3.1. Using the LocalDate Class
Let’s consider the following code which attempts to create a LocalDate with an invalid month value:
LocalDate wrongDate = LocalDate.of(2024,13,1); //DateTimeException
Running the above code snippet will print the following to the console:
Exception in thread "main" java.time.DateTimeException: Invalid value for MonthOfYear (valid values 1 - 12): 13
at java.base/java.time.temporal.ValueRange.checkValidValue(ValueRange.java:319)
at java.base/java.time.temporal.ChronoField.checkValidValue(ChronoField.java:718)
at java.base/java.time.LocalDate.of(LocalDate.java:271)
at Scratch.main(scratch.java:12)
To fix the exception, you should ensure the month value is within the range 1-12.
LocalDate validDate = LocalDate.of(2024,5,1); //No DateTimeException
3.2. Using the LocalTime Class
The code below is attempting to create a LocalTime with an invalid hour value:
LocalTime wrongTime = LocalTime.of(25,1);//DateTimeException
Running the above code snippet will print the following to the console:
Exception in thread "main" java.time.DateTimeException: Invalid value for HourOfDay (valid values 0 - 23): 25
at java.base/java.time.temporal.ValueRange.checkValidValue(ValueRange.java:319)
at java.base/java.time.temporal.ChronoField.checkValidValue(ChronoField.java:718)
at java.base/java.time.LocalTime.of(LocalTime.java:298)
at Scratch.main(scratch.java:13)
Provide a valid value to the hour field to fix this exception:
LocalTime validTime = LocalTime.of(18,1);//No DateTimeException
3.3. Using the Instant Class
The maximum supported value for an instant object is ‘1000000000-12-31T23:59:59.999999999Z’, which corresponds to 31556889864403199L
seconds and 999_999_999
nanoseconds. Any attempt to go beyond this value will lead to a DateTimeException.
Instant tooBigInstant = Instant.ofEpochSecond(31556889864403199L + 1);//DateTimeException
Output:
Exception in thread "main" java.time.DateTimeException: Instant exceeds minimum or maximum instant
at java.base/java.time.Instant.create(Instant.java:413)
at java.base/java.time.Instant.ofEpochSecond(Instant.java:306)
at Scratch.main(scratch.java:12)
To avoid this exception, ensure your instant object’s value is within the supported range. If you’re creating an Instant object with the ofSecond()
method, ensure the provided value is within the range Instant.MIN
and Instant.MAX
values.
Instant validInstant = Instant.ofEpochSecond(1715176763L);//No DateTimeException
3.4. Using the Period Class
Another situation in which a DateTimeException might be thrown is when using the Period#plus()
and Period.minus()
methods with an invalid TemporalAmount.
Period period = Period.ofYears(1);
TemporalAmount secondsAmount = Duration.of(5000, ChronoUnit.SECONDS);//Invalid TemporalAmount
Period addedPeriod = period.plus(secondsAmount);//DateTimeException
Output:
Exception in thread "main" java.time.DateTimeException: Unit must be Years, Months or Days, but was Seconds
at java.base/java.time.Period.from(Period.java:281)
at java.base/java.time.Period.plus(Period.java:629)
at Scratch.main(scratch.java:15)
The Period#plus()
and Period.minus()
methods expect a TemporalAmount with a ChronoUnit of type YEARS, MONTHS, or DAYS.
Period period = Period.ofYears(1);
Period monthsAmount = Period.ofMonths(1);// valid TemporalAmount
Period addedPeriod = period.plus(monthsAmount);//No DateTimeException
4. Best Practices to Avoid DateTimeException
4.1. Use Built-in Constants
If you are dealing with LocalDate for example, it is advisable to use the built-in Month
Enum:
LocalDate validDate = LocalDate.of(2024,Month.MAY,1); //No DateTimeException
4.2. Use Safe Methods for Date Arithmetic
Java provides safe methods for incrementing and decrementing date and time values: plusDays
, plusMonths
, plusYears
, minusDays
, minusMonths
, minusYears
, etc. These methods are designed to handle overflow and underflow properly.
You should use them whenever possible.
Period period = Period.ofYears(1);
Period addedPeriod = period.plusDays(1);//Prefer this over the generic period.plus()
4.3. Use Suitable Data Types
Always make sure you choose the proper data type according to your needs:
- Use LocalDate for date-only values: “2024-05-25”
- Use LocalTime for time-only values: “15:30”
- Use LocalDateTime for combined date and time values: “2024-05-25T15:30”
- Use ZonedDateTime or OffsetDateTime for date and time values with time zone or offset: “2024-05-25T15:30:15.962090600+02:00[Europe/Paris]”
5. Conclusion
In this brief tutorial, you learned about the DateTimeException and how to fix it.
You can find the complete code of this article here in GitHub