Этот вопрос имеет философский характер и охватывает несколько проблем, таких как измерения времени и условные обозначения формата даты.
API-интерфейс обеспечивает только простые операции на самой системе, а все вычисления выполняются приращение или Года Месяц или дня данной даты.
Другими словами, при звонке LocalDate.plusYears()
вы добавляете концептуальные годы по 365 дней каждый, а не точное количество времени в течение года.
Это День самая низкая единица времени, которую можно добавить к дате, выраженной LocalDate
.
В человеческом понимании, Дата не является моментом во времени, но это период.
Начало работы 00h 00m 00s (...) и заканчивается 23h 59m 59s (...).
LocalDate
однако позволяет избежать проблемы измерения времени и неопределенности единиц времени человека (часа, дня, месяца, и года все может иметь разную длину) и дату модели обозначение просто как кортеж :
(years, months within a year, days within a month)
рассчитывается с начала эпохи.
В этой интерпретации имеет смысл, что День - наименьшая единица, влияющая на дату.
В качестве примера следующее:
LocalDate date = LocalDate.of(1996, 2, 29);
LocalDate plusSecond = date.plus(1, ChronoUnit.SECONDS);
возвращается
java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Seconds
..., который показывает, что использование LocalDate
и добавление количества секунд (или более мелких единиц для привода точности), вам не смог преодолеть ограничение, указанное в вашем вопросе.
Глядя на реализацию, вы обнаружите, что LocalDate.plusYears()
после добавления лет, звонки resolvePreviousValid()
. Затем этот метод проверяет високосный год и изменяет день поле следующим образом:
day = Math.min(day, IsoChronology.INSTANCE.isLeapYear((long)year)?29:28);
Другими словами, он исправляет его эффективно вычитая 1 день.
Вы можете использовать Year.length()
, который возвращает количество дней для данного года и вернет для високоснов. Таким образом, вы можете сделать:
LocalDate plusYear = date.plus(Year.of(date.getYear()).length(), ChronoUnit.DAYS);
Вы все равно будете работать в следующие странности (вызов Year.length()
заменены подсчетами дня для краткости):
LocalDate date = LocalDate.of(1996, 2, 29);
LocalDate plusYear = date.plus(365, ChronoUnit.DAYS);
System.out.println(plusYear);
Period between = Period.between(date, plusYear);
System.out.println(between.getYears() + "y " +
between.getMonths() + "m " +
between.getDays() + "d");
возвращается
1997-02-28
0y 11m 30d
затем
LocalDate date = LocalDate.of(1996, 3, 29);
LocalDate plusYear = date.plus(365, ChronoUnit.DAYS);
System.out.println(plusYear);
Period between = Period.between(date, plusYear);
System.out.println(between.getYears() + "y " +
between.getMonths() + "m " +
between.getDays() + "d");
возвращает
1997-03-29
1y 0m 0d
и, наконец:
LocalDate date = LocalDate.of(1996, 2, 29);
LocalDate plusYear = date.plus(366, ChronoUnit.DAYS);
System.out.println(plusYear);
Period between = Period.between(date, plusYear);
System.out.println(between.getYears() + "y " +
between.getMonths() + "m " +
between.getDays() + "d");
возвращает:
1997-03-01
1y 0m 1d
Пожалуйста, обратите внимание, что перемещение даты по вместо дней увеличился период с 11 месяцев и 30 дней до 1 год и 1 день (2 день больше!).
Я считаю, что ваш производственный код на самом деле не добавляет 1 год и пытается подсчитать, сколько лет он только что добавил. Чего вы на самом деле пытаетесь достичь? Дайте нам фактический ввод и ожидаемый результат. – dotvav
@dotvav: Приведенный пример кажется мне совершенно понятным ... Я не вижу в этом ничего плохого. –
Если вы действительно хотите разницу в один год вместо нуля, то просто вычтите цифры года, не принимая во внимание любые месяцы или дни месяца. –