You are currently viewing How to Fix DateTimeException In Java

How to Fix DateTimeException In Java

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

Noel Kamphoa

Experienced software engineer with expertise in Telecom, Payroll, and Banking. Now Senior Software Engineer at Societe Generale Paris.