Подтвердить что ты не робот

В java.time, как результат вычисления месяца?

В API JSR-310 java.time в JDK 8, каковы правила для вычисления результата добавления месяца к дате. В частности, что произойдет, если вы добавите 1 месяц к дате, подобной 31 января?

LocalDate initial = LocalDate.of(2012, 1, 31);  // 31st January 2012
LocalDate result = initial.plusMonths(1);
// what is the result?
4b9b3361

Ответ 1

Короткий ответ:

В этом примере результат будет последним днем ​​февраля, 2012-02-29.

Пояснение:

Вопрос, "какая дата вы получаете, если вы добавляете месяц", - это вопрос, который может быть открыт для интерпретации. Чтобы избежать этого, API java.time имеет правило очистки. Результат будет иметь тот же день месяца, что и вход, если это не будет недопустимой датой, и в этом случае результатом будет последний день месяца.

Таким образом, 31 января плюс один месяц приведет к 31-му февраля, но поскольку это недопустимая дата, результатом является последняя действительная дата в феврале, которая составляет 28 или 29 февраля в зависимости от того, является ли это високосным годом

// normal case
2011-01-15 plus 1 month = 2011-02-15  // 15 Jan -> 15 Feb

// special rule choosing the last valid day-of-month
2011-01-31 plus 1 month = 2011-02-28  // 31 Jan -> 28 Feb (2011 is normal year)
2012-01-31 plus 1 month = 2012-02-29  // 31 Jan -> 29 Feb (2012 is leap year)

// same rule applies for months other than February
2013-03-31 plus 1 month = 2013-04-30  // 31 Mar -> 30 Apr (only 30 days in April)

То же правило применяется, если добавить один месяц или много месяцев и всегда основывается на результирующем месяце. то есть. сначала добавляется месяц (при необходимости корректируется год), и только тогда учитывается день недели. Это же правило применяется и при вычитании.

// multiple months works on the month of the result
2013-10-31 plus 4 months = 2014-02-28   // last day of February
2013-10-31 minus 4 months = 2013-06-30  // last day of June

Те же правила применяются и при добавлении/вычитании лет в/из даты - эти годы добавляются, и только тогда день месяца проверяется на достоверность в течение месяца.

// years use the same rule
2012-02-29 plus 1 year = 2013-02-28  // 29th February invalid so adjusted to 28th

Если вашей бизнес-логике требуется другое правило для добавления месяца, наилучшим подходом будет написать TemporalAdjuster или TemporalAmount, который упаковывает вашу специальную логику.