Java JodaTime - 29.02.2024 - Value 29 for dayOfMonth must be in the range [1,28] - leap year

434 Views Asked by At

I use this code in my application:

final DateTime selectedDate = new DateTime().withMonthOfYear(month).withDayOfMonth(day).withYear(year);

where month = 2, day = 29, year = 2024

and I get this exception:

Value 29 for dayOfMonth must be in the range [1,28]

but 2024 is a leap year. Does anyone have a solution about this?

1

There are 1 best solutions below

0
Dawood ibn Kareem On

Whereas the final value of your expression appears to be a valid date, you've evaluated it in an order which requires an invalid date to be evaluated along the way.

You wrote

final DateTime selectedDate = 
    new DateTime().withMonthOfYear(month).withDayOfMonth(day).withYear(year);

which is evaluated from left to right. It's therefore equivalent to

DateTime result1 = new DateTime().withMonthOfYear(month);
DateTime result2 = result1.withDayOfMonth(day);
final DateTime selectedDate = result2.withYear(year);

Now, suppose I run this today (20 March 2023) with month = 2, day = 29, year = 2024 as you specified. Then I have

DateTime result1 = 20 February 2023 // all good so far
DateTime result2 = 29 February 2023 // whoops!

and this is the point where your exception is thrown. We never got as far as setting the year to 2024.

Rearranging your code so that withYear gets called first would fix this, because all the intermediate results would be valid dates.

final DateTime selectedDate = 
    new DateTime().withYear(year).withMonthOfYear(month).withDayOfMonth(day);

A better idea is Ole's idea

final DateTime selectedDate = new DateTime().withDate(year, month, day);

which sets all three fields in a single call, so you don't need to be concerned about intermediate results.

But the best idea of all would be for you to use the classes in the java.time package, instead of Joda. Joda has been obsolete for almost 10 years now.

import java.time.LocalDate;

// ...

final LocalDate selectedDate = LocalDate.of(year, month, day);