Метод parseUnresolved
для DatetimeFormatter
анализирует, не пытаясь понять проанализированные значения. Поэтому он принимает недопустимую дату и позволяет вам проверить проанализированные значения, прежде чем пытаться сделать из них LocalDate
.
public static LocalDate resolveInvalidDate(String nextFieldTypeDate) {
ParsePosition position = new ParsePosition(0);
TemporalAccessor parsed = DateTimeFormatter.ISO_LOCAL_DATE
.parseUnresolved(nextFieldTypeDate, position);
if (position.getIndex() < nextFieldTypeDate.length()) {
throw new IllegalArgumentException("Could not parse entire string");
}
YearMonth ym = YearMonth.from(parsed);
int lastDayOfMonth = ym.lengthOfMonth();
int parsedDayOfMOnth = parsed.get(ChronoField.DAY_OF_MONTH);
if (parsedDayOfMOnth > lastDayOfMonth) { // invalid, must be adjusted to lasst day of month
return ym.atEndOfMonth();
} else {
return ym.atDay(parsedDayOfMOnth);
}
}
Давайте попробуем эту версию вашего метода:
System.out.println(resolveInvalidDate("2018-02-31"));
System.out.println(resolveInvalidDate("2018-02-27"));
Вывод:
2018-02-28
2018-02-27
Таким образом, 31 февраля было недействительным и было перенесено на 28 февраля, который в 2018 году был последним днем этого месяца. 27 февраля действует и возвращается как есть.
Редактировать: Для связанной цели можно было бы подумать, что гораздо проще DateTimeFormatter.ISO_LOCAL_DATE.withResolverStyle(ResolverStyle.LENIENT).parse(nextFieldTypeDate, LocalDate::from)
. Это, однако, превращает 2018-02-31
в 2018-03-03
, что, как я понимаю, не то, что вы хотите.