[Fix] Properly handle month periods in PeriodHelper
This commit is contained in:
parent
4f52c1852f
commit
76011f6940
|
@ -9,6 +9,13 @@ import li.strolch.utils.dbc.DBC;
|
||||||
|
|
||||||
public class PeriodHelper {
|
public class PeriodHelper {
|
||||||
|
|
||||||
|
public static double monthsIn(PeriodDuration periodDuration) {
|
||||||
|
long hours = periodDuration.getDuration().toHours();
|
||||||
|
Period period = periodDuration.getPeriod();
|
||||||
|
long months = period.toTotalMonths();
|
||||||
|
return (months + (period.getDays() / 30.0) + (hours / 24.0 / 30.0));
|
||||||
|
}
|
||||||
|
|
||||||
public static double daysIn(PeriodDuration periodDuration) {
|
public static double daysIn(PeriodDuration periodDuration) {
|
||||||
return (daysIn(periodDuration.getPeriod()) + (periodDuration.getDuration().toHours() / 24.0));
|
return (daysIn(periodDuration.getPeriod()) + (periodDuration.getDuration().toHours() / 24.0));
|
||||||
}
|
}
|
||||||
|
@ -17,6 +24,10 @@ public class PeriodHelper {
|
||||||
return (period.getYears() * 365.0) + (period.getMonths() * 30.0) + period.getDays();
|
return (period.getYears() * 365.0) + (period.getMonths() * 30.0) + period.getDays();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static double monthsIn(Period period) {
|
||||||
|
return (period.getYears() * 12.0) + (period.getMonths());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This special function allows us to shift a date by a multiple of the given {@link PeriodDuration} so that is
|
* This special function allows us to shift a date by a multiple of the given {@link PeriodDuration} so that is
|
||||||
* before the given to date. It does multiple tries to get as close as possible, due to the inexactness of 30 days
|
* before the given to date. It does multiple tries to get as close as possible, due to the inexactness of 30 days
|
||||||
|
@ -35,7 +46,20 @@ public class PeriodHelper {
|
||||||
PeriodDuration periodDuration) {
|
PeriodDuration periodDuration) {
|
||||||
DBC.PRE.assertTrue("date must be before to!", date.isBefore(to));
|
DBC.PRE.assertTrue("date must be before to!", date.isBefore(to));
|
||||||
DBC.PRE.assertFalse("period duration may not be null!", periodDuration.isZero());
|
DBC.PRE.assertFalse("period duration may not be null!", periodDuration.isZero());
|
||||||
|
|
||||||
|
// see if we need to shift by months
|
||||||
|
long monthsInPeriod = (long) monthsIn(periodDuration);
|
||||||
|
if (monthsInPeriod > 0) {
|
||||||
|
Period between = between(date.toLocalDate(), to.toLocalDate());
|
||||||
|
double monthsInBetween = monthsIn(between);
|
||||||
|
long shifts = (long) (monthsInBetween / monthsInPeriod);
|
||||||
|
if (shifts > 0) {
|
||||||
|
date = date.plusMonths(shifts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Period between = between(date.toLocalDate(), to.toLocalDate());
|
Period between = between(date.toLocalDate(), to.toLocalDate());
|
||||||
|
|
||||||
double daysInBetween = daysIn(between);
|
double daysInBetween = daysIn(between);
|
||||||
double daysInPeriod = daysIn(periodDuration);
|
double daysInPeriod = daysIn(periodDuration);
|
||||||
long shifts = (long) (daysInBetween / daysInPeriod);
|
long shifts = (long) (daysInBetween / daysInPeriod);
|
||||||
|
|
|
@ -7,7 +7,6 @@ import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.time.temporal.ChronoUnit;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -68,6 +67,26 @@ public class PeriodHelperTest {
|
||||||
assertEquals(30, daysIn(PeriodDuration.parse("P1M")), 0.0);
|
assertEquals(30, daysIn(PeriodDuration.parse("P1M")), 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldCalcMonths1() {
|
||||||
|
assertEquals(1, monthsIn(PeriodDuration.parse("P1M")), 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldCalcMonths2() {
|
||||||
|
assertEquals(1, monthsIn(PeriodDuration.parse("P30D")), 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldCalcMonths3() {
|
||||||
|
assertEquals(2, monthsIn(PeriodDuration.parse("P60D")), 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldCalcMonths4() {
|
||||||
|
assertEquals(12, monthsIn(PeriodDuration.parse("P1Y")), 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldCalcShiftDays1() {
|
public void shouldCalcShiftDays1() {
|
||||||
ZonedDateTime past = ZonedDateTime.now().minusDays(35);
|
ZonedDateTime past = ZonedDateTime.now().minusDays(35);
|
||||||
|
@ -83,7 +102,7 @@ public class PeriodHelperTest {
|
||||||
public void shouldCalcShiftDays2() {
|
public void shouldCalcShiftDays2() {
|
||||||
ZonedDateTime past = ZonedDateTime
|
ZonedDateTime past = ZonedDateTime
|
||||||
.parse("2007-12-03T10:15:30+01:00", DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(systemDefault()));
|
.parse("2007-12-03T10:15:30+01:00", DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(systemDefault()));
|
||||||
ZonedDateTime now = ZonedDateTime.now().truncatedTo(ChronoUnit.DAYS);
|
ZonedDateTime now = ZonedDateTime.now();
|
||||||
PeriodDuration periodDuration = PeriodDuration.parse("P1M");
|
PeriodDuration periodDuration = PeriodDuration.parse("P1M");
|
||||||
ZonedDateTime shiftedDate = shiftByMultipleOfPeriod(past, now, periodDuration);
|
ZonedDateTime shiftedDate = shiftByMultipleOfPeriod(past, now, periodDuration);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue