Ausgabe
Ich versuche herauszufinden, wie viele Monate zwischen 2 Daten liegen. Mein Code ist jetzt ungefähr so aus
ChronoUnit.MONTHS.between(d1, d2)
Das Problem ist, dass das Ergebnis lang ist. Wenn sich die Daten beispielsweise nur in ein paar Tagen unterscheiden, sollte ich ein Ergebnis von etwa 0,34 anstelle von 0 erhalten.
Außerdem brauche ich meinen Code, um den Kalender zu berücksichtigen, ich kann nicht davon ausgehen, dass jeder Monat 31 Tage hat.
Diff between 1999-05-12 and 1999-08-24
Assuming all months have 31 days for simplicity
result = (19/31 + 31/31 + 31/31 + 24/31) = 2.793
According to the calendar we replace the 31s with the correct number of days for that specific year and month
Lösung
Hier ist meine Lösung:
public static double monthsBetween(LocalDate start, LocalDate end) {
if (start.isAfter(end)) throw new IllegalArgumentException("Start must be before end!");
var lastDayOfStartMonth = start.with(TemporalAdjusters.lastDayOfMonth());
var firstDayOfEndMonth = end.with(TemporalAdjusters.firstDayOfMonth());
var startMonthLength = (double)start.lengthOfMonth();
var endMonthLength = (double)end.lengthOfMonth();
if (lastDayOfStartMonth.isAfter(firstDayOfEndMonth)) { // same month
return ChronoUnit.DAYS.between(start, end) / startMonthLength;
}
long months = ChronoUnit.MONTHS.between(lastDayOfStartMonth, firstDayOfEndMonth);
double startFraction = ChronoUnit.DAYS.between(start, lastDayOfStartMonth.plusDays(1)) / startMonthLength;
double endFraction = ChronoUnit.DAYS.between(firstDayOfEndMonth, end) / endMonthLength;
return months + startFraction + endFraction;
}
Die Idee ist, dass Sie den letzten Tag des start
Monats von ( lastDayOfStartMonth
) und den ersten Tag des end
Monats von ( firstDayOfEndMonth
) mithilfe zeitlicher Anpassungen finden. Diese beiden Daten sind sehr wichtig. Die gesuchte Zahl ist die Summe aus:
- die Bruchzahl eines Monats zwischen
start
undlastDayOfStartMonth
- die ganze Anzahl der Monate zwischen
lastDayOfStartMonth
undfirstDayOfEndMonth
. - die Bruchzahl eines Monats zwischen
firstDayOfEndMonth
undend
.
Dann gibt es den Randfall, dass beide Daten im selben Monat liegen, was einfach zu handhaben ist.
Durch die Verwendung dieser Definition bleibt die schöne Eigenschaft erhalten, dass die Anzahl der Monate zwischen dem ersten Tag von zwei beliebigen Monaten immer eine ganze Zahl ist.
Beachten Sie, dass Sie in der ersten Berechnung einen Tag zu addieren müssen lastDayOfStartMonth
, da ChronoUnit.between
die Obergrenze als exklusiv behandelt wird, aber wir wollen sie hier eigentlich als einen Tag zählen.
Beantwortet von – Kehrmaschine
Antwort geprüft von – Marie Seifert (FixError Admin)