TL; DR: Использование payDate = payDate.plusDays(payDay - payDate.getDayOfMonth());
Поведение Calendar
, которое вы описываете, задокументировано в javado c:
Лентность
Calendar
имеет два режима для интерпретации полей календаря: снисходительный и без снисходительны . Когда Calendar
находится в мягком режиме, он принимает более широкий диапазон значений календарного поля, чем он производит. Когда Calendar
пересчитывает значения полей календаря для возврата на get()
, все поля календаря нормализуются. Например, снисходительный GregorianCalendar
интерпретирует MONTH == JANUARY
, DAY_OF_MONTH == 32
как 1 февраля.
Когда Calendar
находится в не снисходительном режиме, он генерирует исключение, если в его календаре есть несоответствия поля. Например, GregorianCalendar
всегда выдает DAY_OF_MONTH
значения между 1 и продолжительностью месяца. Не снисходительный GregorianCalendar
выдает исключение при вычислении его значений поля времени или календаря, если было установлено какое-либо значение поля вне диапазона.
Чтобы показать эффект этого, попробуйте установить дата от Calendar
до 70 января 2020 года:
Calendar cal = Calendar.getInstance();
cal.clear();
cal.set(2020, Calendar.JANUARY, 70);
System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime()));
Вывод
2020-03-10
Вы бы получили тот же результат, если бы сделали:
cal.set(2020, Calendar.JANUARY, 1);
cal.add(Calendar.DAY_OF_MONTH, 69);
LocalDate
всегда не снижен , поэтому вы не можете установить значение дня месяца равным из-диапазона. Однако вы можете получить тот же результат, что и Calendar
, изменив операцию «добавить» вместо «установить».
Итак, если у вас есть конкретная дата, например, указанная дата 2020-01-29
в вопросе, и вы хотите "установить" значение дня месяца равным 70 или 0, с тем же снисходительным переполнением logi c, как Calendar
, сделайте это:
LocalDate date = LocalDate.parse("2020-01-29");
date = date.plusDays(70 - date.getDayOfMonth());
System.out.println(date);
LocalDate date = LocalDate.parse("2020-01-29");
date = date.plusDays(0 - date.getDayOfMonth());
System.out.println(date);
Выход
2020-03-10
2019-12-31
Как видите, date.plusDays(dayToSet - date.getDayOfMonth())
даст вам желаемый результат.