To pytanie ma charakter filozoficzny i obejmuje kilka problemów, takich jak pomiary czasu i konwencje dotyczące formatu daty.
LocalDate
to implementacja standardu wymiany danych . Java Doc stwierdza jednoznacznie, że ta klasa nie reprezentuje czasu, ale zapewnia tylko standardowy zapis daty.
API zapewnia tylko proste operacje na samej notacji i wszystkie obliczenia wykonywane są przez przyrostowe zwiększenie Rok lub Miesiąc lub Dzień na dany dzień.
Innymi słowy, dzwoniąc pod numer LocalDate.plusYears()
, dodajesz lata koncepcyjne o długości 365 dni, a nie dokładną ilość czasu w ciągu roku.
To sprawia, że dzień najniższa jednostka czasu, którą można dodać do daty wyrażonej przez LocalDate
.
W rozumieniu ludzi, data nie jest momentem czasu, ale jest to okres.
Rozpoczyna się od 00h 00m 00s (...) i kończy się 23h 59m 59s (...).
LocalDate
jednak uniknąć problemów z pomiarem czasu i niejasności jednostek czasowych ludzkich (godzinnym, dni, miesięcy, a rok wszystko może mieć różne długości) i modele datę zapisu po prostu jako krotki :
(years, months within a year, days within a month)
obliczany od początku ery.
W tej interpretacji ma sens, że Dzień jest najmniejszą jednostką wpływającą na datę.
Jako przykład następujący:
LocalDate date = LocalDate.of(1996, 2, 29);
LocalDate plusSecond = date.plus(1, ChronoUnit.SECONDS);
zwrotów
java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Seconds
... co pokazuje, że przy użyciu LocalDate
i dodając liczbę sekund (lub mniejszych jednostek do prowadzenia precyzji), ty nie udało się przezwyciężyć ograniczeń wymienionych w pytaniu.
Patrząc na wdrożenie, po dodaniu lat znajduje się LocalDate.plusYears()
, nazywa się resolvePreviousValid()
. Metoda ta sprawdza na rok przestępny i modyfikuje pole dzień w następujący sposób:
day = Math.min(day, IsoChronology.INSTANCE.isLeapYear((long)year)?29:28);
Innymi słowy koryguje ją skutecznie odjęcie 1 dzień.
Można użyć numeru Year.length()
, który zwraca liczbę dni dla danego roku i zwróci dla lat przestępnych. Więc można zrobić:
LocalDate plusYear = date.plus(Year.of(date.getYear()).length(), ChronoUnit.DAYS);
Będziesz nadal działać w następujący osobliwości (wezwanie do Year.length()
zastąpione liczbą dziennie dla zwięzłość):
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");
zwrotów
1997-02-28
0y 11m 30d
następnie
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");
powraca
1997-03-29
1y 0m 0d
i wreszcie:
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");
Powroty:
1997-03-01
1y 0m 1d
Należy pamiętać, że przesunięcie terminu przez zamiast dni wzrosła okres od 11 miesięcy i 30 dni do 1 rok i 1 dzień (wzrost o 2 dni!).
Wydaje mi się, że Twój kod produkcyjny faktycznie nie dodaje 1 roku i nie liczy się z liczbą dodanych lat. Co tak naprawdę próbujesz osiągnąć? Podaj nam rzeczywiste dane wejściowe i oczekiwane wyniki. – dotvav
@dotvav: Podany przykład wydaje mi się całkiem jasny ... Nie widzę w tym nic złego. –
Jeśli naprawdę chcesz mieć roczną różnicę zamiast zera, po prostu odejmij numery roku nie biorąc pod uwagę miesiąca lub dnia w miesiącu. –