package net.time4j;
import java.text.ParseException;
import java.util.Arrays;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import static net.time4j.CalendarUnit.DAYS;
import static net.time4j.CalendarUnit.MONTHS;
import static net.time4j.CalendarUnit.YEARS;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
@RunWith(Parameterized.class)
public class DurationArithmeticTest {
@Parameters(name= "{index}: [start={0}-{1}-{2}/end={3}-{4}-{5}] => {6}")
public static Iterable<Object[]> data() {
return Arrays.asList(
new Object[][] {
{2012, 2, 29, 2016, 2, 29, "P4Y"},
{2012, 2, 29, 2016, 2, 29, "P3Y12M"},
{2012, 2, 29, 2015, 2, 28, "P2Y11M30D"},
{2015, 2, 28, 2016, 2, 28, "P12M"},
{2012, 6, 30, 2014, 7, 31, "P2Y1M1D"},
{2012, 5, 31, 2012, 7, 1, "P1M1D"},
{2014, 7, 31, 2012, 6, 30, "-P2Y1M1D"},
{2012, 6, 28, 2014, 7, 31, "P2Y1M3D"},
{2012, 6, 28, 2014, 7, 30, "P2Y1M2D"},
{2012, 2, 29, 2015, 2, 28, "P2Y11M30D"},
{2011, 2, 27, 2016, 3, 1, "P5Y3D"},
{2011, 1, 1, 2011, 12, 31, "P11M30D"},
{2012, 1, 1, 2012, 12, 31, "P11M30D"},
{2011, 1, 1, 2011, 1, 1, "P0D"},
{2012, 6, 4, 2012, 5, 31, "-P4D"},
{2010, 4, 29, 2011, 5, 31, "P1Y1M2D"},
{2004, 2, 29, 2008, 2, 28, "P3Y11M30D"},
{2003, 2, 27, 2008, 2, 28, "P5Y1D"},
{2003, 2, 27, 2008, 2, 27, "P5Y"},
{2003, 2, 27, 2008, 2, 26, "P4Y11M30D"},
{-999999999, 1, 1, 999999999, 12, 31, "P1999999998Y11M30D"},
{999999999, 12, 31, -999999999, 1, 1, "-P1999999998Y11M30D"}
}
);
}
private PlainDate start;
private PlainDate end;
private Duration<CalendarUnit> duration;
public DurationArithmeticTest(
int startYear,
int startMonth,
int startDay,
int endYear,
int endMonth,
int endDay,
String period
) throws ParseException {
super();
this.start = PlainDate.of(startYear, startMonth, startDay);
this.end = PlainDate.of(endYear, endMonth, endDay);
this.duration = Duration.parseCalendarPeriod(period);
}
@Test
public void plusDuration() {
assertThat(
this.start.plus(this.duration),
is(this.end));
}
@Test
public void minusDuration() {
assertThat(
this.start.minus(this.duration.inverse()),
is(this.end));
}
@Test
public void between() {
assertThat(
this.start.until(this.end, Duration.inYearsMonthsDays()),
is(this.duration.with(Duration.STD_CALENDAR_PERIOD)));
}
@Test
public void assertMonthsDaysInvariant_T1_Plus_T1UntilT2_Eq_T2() {
Duration<CalendarUnit> period =
this.start.until(this.end, Duration.in(MONTHS, DAYS));
assertThat(this.start.plus(period), is(this.end));
}
@Test
public void assertMonthsDaysInvariant_T1UntilT2_Eq_T2UntilT1Inv() {
Duration<CalendarUnit> p1 =
this.start.until(this.end, Duration.in(MONTHS, DAYS));
Duration<CalendarUnit> p2 =
this.end.until(this.start, Duration.in(MONTHS, DAYS));
assertThat(p1, is(p2.inverse()));
}
@Test
public void assertMonthsDaysWeakInvariant_T2_Minus_T1UntilT2_Eq_T1() {
if (this.start.getDayOfMonth() <= 28) {
Duration<CalendarUnit> period =
this.start.until(this.end, Duration.in(MONTHS, DAYS));
assertThat(this.end.minus(period), is(this.start));
}
}
@Test
public void assertYearsMonthsDaysInvariant_T1_Plus_T1UntilT2_Eq_T2() {
Duration<CalendarUnit> period =
this.start.until(this.end, Duration.in(YEARS, MONTHS, DAYS));
assertThat(this.start.plus(period), is(this.end));
}
@Test
public void assertYearsMonthsDaysInvariant_T1UntilT2_Eq_T2UntilT1Inv() {
Duration<CalendarUnit> p1 =
this.start.until(this.end, Duration.in(YEARS, MONTHS, DAYS));
Duration<CalendarUnit> p2 =
this.end.until(this.start, Duration.in(YEARS, MONTHS, DAYS));
assertThat(p1, is(p2.inverse()));
}
@Test
public void assertYearsMonthsDaysWeakInvariant_T2_Minus_T1UntilT2_Eq_T1() {
if (this.start.getDayOfMonth() <= 28) {
Duration<CalendarUnit> period =
this.start.until(this.end, Duration.in(YEARS, MONTHS, DAYS));
assertThat(this.end.minus(period), is(this.start));
}
}
}