package net.time4j.tz.model; import net.time4j.Moment; import net.time4j.Month; import net.time4j.PlainDate; import net.time4j.PlainTime; import net.time4j.PlainTimestamp; import net.time4j.Weekday; import net.time4j.base.UnixTime; import net.time4j.tz.OffsetSign; import net.time4j.tz.TransitionHistory; import net.time4j.tz.ZonalOffset; import net.time4j.tz.ZonalTransition; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.nullValue; import static org.junit.Assert.assertThat; @RunWith(JUnit4.class) public class CompositeTransitionModelTest { private static final ZonalTransition FIRST = new ZonalTransition(0L, 1800, 7200, 3600); private static final ZonalTransition SECOND = new ZonalTransition(365 * 86400L, 7200, 3600, 0); private static final ZonalTransition THIRD = new ZonalTransition(830 * 86400L, 3600, 7200, 3600); private static final TransitionHistory MODEL = createModel(false); private static final TransitionHistory MODEL_EXT = createModel(true); private static final TransitionHistory MODEL_SINGLE = createSingleRuleModel(); private static final ZonalTransition FOURTH = new ZonalTransition( PlainDate.of(1972, 10, 1) .with(PlainDate.WEEKDAY_IN_MONTH.setToLast(Weekday.SUNDAY)) .atTime(1, 0) .atUTC() .getPosixTime(), 7200, 3600, 0 ); private static final ZonalTransition FIFTH = new ZonalTransition( PlainDate.of(1973, 3, 1) .with(PlainDate.WEEKDAY_IN_MONTH.setToLast(Weekday.SUNDAY)) .atTime(1, 0) .atUTC() .getPosixTime(), 3600, 7200, 3600 ); @Test public void getInitialOffset() { ZonalOffset expected = ZonalOffset.ofHoursMinutes(OffsetSign.AHEAD_OF_UTC, 0, 30); assertThat(MODEL.getInitialOffset(), is(expected)); assertThat(MODEL_EXT.getInitialOffset(), is(expected)); assertThat(MODEL_SINGLE.getInitialOffset(), is(expected)); } @Test public void getStartTransition1() { assertThat(MODEL.getStartTransition(new UT(-1)), nullValue()); assertThat(MODEL_EXT.getStartTransition(new UT(-1)), nullValue()); assertThat(MODEL_SINGLE.getStartTransition(new UT(-1)), nullValue()); } @Test public void getStartTransition2() { assertThat(MODEL.getStartTransition(new UT(0)), is(FIRST)); assertThat(MODEL_EXT.getStartTransition(new UT(0)), is(FIRST)); assertThat(MODEL_SINGLE.getStartTransition(new UT(0)), is(FIRST)); } @Test public void getStartTransition3() { assertThat( MODEL.getStartTransition(new UT(365 * 86400L - 1)), is(FIRST)); assertThat( MODEL_EXT.getStartTransition(new UT(365 * 86400L - 1)), is(FIRST)); assertThat( MODEL_SINGLE.getStartTransition(new UT(365 * 86400L - 1)), is(FIRST)); } @Test public void getStartTransition4() { assertThat( MODEL.getStartTransition(new UT(365 * 86400L)), is(SECOND)); assertThat( MODEL_EXT.getStartTransition(new UT(365 * 86400L)), is(SECOND)); assertThat( MODEL_SINGLE.getStartTransition(new UT(365 * 86400L)), is(SECOND)); } @Test public void getStartTransition5() { ZonalTransition expected = THIRD; ZonalTransition zt = MODEL.getStartTransition(new UT(FOURTH.getPosixTime() - 1)); ZonalTransition ztExt = MODEL_EXT.getStartTransition(new UT(FOURTH.getPosixTime() - 1)); ZonalTransition ztSingle = MODEL_SINGLE.getStartTransition(new UT(FOURTH.getPosixTime() - 1)); assertThat(zt, is(expected)); assertThat(ztExt, is(expected)); assertThat(ztSingle, is(expected)); } @Test public void getStartTransition6() { ZonalTransition expected = FOURTH; ZonalTransition zt = MODEL.getStartTransition(new UT(FOURTH.getPosixTime())); ZonalTransition ztExt = MODEL_EXT.getStartTransition(new UT(FOURTH.getPosixTime())); assertThat(zt, is(expected)); assertThat(ztExt, is(expected)); assertThat(zt == expected, is(false)); assertThat(ztExt == expected, is(false)); assertThat(zt == ztExt, is(false)); } @Test public void findPreviousTransition1() { ZonalTransition expected = THIRD; // from array ZonalTransition zt = MODEL.findPreviousTransition(new UT(FOURTH.getPosixTime())).get(); assertThat(zt, is(expected)); } @Test public void findPreviousTransition2() { ZonalTransition expected = FOURTH; // rule-based ZonalTransition zt = MODEL.findPreviousTransition(new UT(FOURTH.getPosixTime() + 1)).get(); assertThat(zt, is(expected)); } @Test public void findNextTransition1() { assertThat(MODEL.findNextTransition(new UT(-1)).get(), is(FIRST)); assertThat(MODEL_EXT.findNextTransition(new UT(-1)).get(), is(FIRST)); assertThat(MODEL_SINGLE.findNextTransition(new UT(-1)).get(), is(FIRST)); } @Test public void findNextTransition2() { assertThat(MODEL.findNextTransition(new UT(0)).get(), is(SECOND)); assertThat(MODEL_EXT.findNextTransition(new UT(0)).get(), is(SECOND)); assertThat(MODEL_SINGLE.findNextTransition(new UT(0)).get(), is(SECOND)); } @Test public void findNextTransition3() { assertThat( MODEL.findNextTransition(new UT(THIRD.getPosixTime() - 1)).get(), is(THIRD)); assertThat( MODEL_EXT.findNextTransition(new UT(THIRD.getPosixTime() - 1)).get(), is(THIRD)); assertThat( MODEL_SINGLE.findNextTransition(new UT(THIRD.getPosixTime() - 1)).get(), is(THIRD)); } @Test public void findNextTransition4() { assertThat( MODEL.findNextTransition(new UT(THIRD.getPosixTime())).get(), is(FOURTH)); assertThat( MODEL_EXT.findNextTransition(new UT(THIRD.getPosixTime())).get(), is(FOURTH)); Moment m = PlainTimestamp.of(1973, 3, 1, 1, 0) .with(PlainDate.WEEKDAY_IN_MONTH.setToLast(Weekday.SUNDAY)) .atUTC(); assertThat( MODEL_SINGLE.findNextTransition(new UT(THIRD.getPosixTime())).get(), is(new ZonalTransition(m.getPosixTime(), 7200, 7200, 3600))); } @Test public void findNextTransition5() { assertThat( MODEL.findNextTransition(new UT(FOURTH.getPosixTime() - 1)).get(), is(FOURTH)); assertThat( MODEL_EXT.findNextTransition(new UT(FOURTH.getPosixTime() - 1)).get(), is(FOURTH)); } @Test public void findNextTransition6() { assertThat( MODEL.findNextTransition(new UT(FOURTH.getPosixTime())).get(), is(FIFTH)); assertThat( MODEL_EXT.findNextTransition(new UT(FOURTH.getPosixTime())).get(), is(FIFTH)); } @Test public void getGapTransition1() { assertThat( MODEL.getConflictTransition( PlainDate.of(1970, 1, 1), PlainTime.of(0, 29, 59)), nullValue()); assertThat( MODEL_EXT.getConflictTransition( PlainDate.of(1970, 1, 1), PlainTime.of(0, 29, 59)), nullValue()); } @Test public void getGapTransition2() { assertThat( MODEL.getConflictTransition( PlainDate.of(1970, 1, 1), PlainTime.of(0, 30)), is(FIRST)); assertThat( MODEL_EXT.getConflictTransition( PlainDate.of(1970, 1, 1), PlainTime.of(0, 30)), is(FIRST)); } @Test public void getGapTransition3() { assertThat( MODEL.getConflictTransition( PlainDate.of(1970, 1, 1), PlainTime.of(1, 59, 59)), is(FIRST)); assertThat( MODEL_EXT.getConflictTransition( PlainDate.of(1970, 1, 1), PlainTime.of(1, 59, 59)), is(FIRST)); } @Test public void getGapTransition4() { assertThat( MODEL.getConflictTransition( PlainDate.of(1970, 1, 1), PlainTime.of(2, 0)), nullValue()); assertThat( MODEL_EXT.getConflictTransition( PlainDate.of(1970, 1, 1), PlainTime.of(2, 0)), nullValue()); } @Test public void getGapTransition5() { assertThat( MODEL.getConflictTransition( PlainDate.of(1973, 3, 1) .with(PlainDate.WEEKDAY_IN_MONTH.setToLast(Weekday.SUNDAY)), PlainTime.of(2, 0)), is(FIFTH)); assertThat( MODEL_EXT.getConflictTransition( PlainDate.of(1973, 3, 1) .with(PlainDate.WEEKDAY_IN_MONTH.setToLast(Weekday.SUNDAY)), PlainTime.of(2, 0)), is(FIFTH)); } @Test public void getOverlapTransition1() { assertThat( MODEL.getConflictTransition( PlainDate.of(1971, 1, 1), PlainTime.of(0, 59, 59)), nullValue()); assertThat( MODEL_EXT.getConflictTransition( PlainDate.of(1971, 1, 1), PlainTime.of(0, 59, 59)), nullValue()); } @Test public void getOverlapTransition2() { assertThat( MODEL.getConflictTransition( PlainDate.of(1971, 1, 1), PlainTime.of(1, 0)), is(SECOND)); assertThat( MODEL_EXT.getConflictTransition( PlainDate.of(1971, 1, 1), PlainTime.of(1, 0)), is(SECOND)); } @Test public void getOverlapTransition3() { assertThat( MODEL.getConflictTransition( PlainDate.of(1971, 1, 1), PlainTime.of(1, 59, 59)), is(SECOND)); assertThat( MODEL_EXT.getConflictTransition( PlainDate.of(1971, 1, 1), PlainTime.of(1, 59, 59)), is(SECOND)); } @Test public void getOverlapTransition4() { assertThat( MODEL.getConflictTransition( PlainDate.of(1971, 1, 1), PlainTime.of(2, 0)), nullValue()); assertThat( MODEL_EXT.getConflictTransition( PlainDate.of(1971, 1, 1), PlainTime.of(2, 0)), nullValue()); } @Test public void getOverlapTransition5() { assertThat( MODEL.getConflictTransition( PlainDate.of(1972, 10, 1) .with(PlainDate.WEEKDAY_IN_MONTH.setToLast(Weekday.SUNDAY)), PlainTime.of(2, 0)), is(FOURTH)); assertThat( MODEL_EXT.getConflictTransition( PlainDate.of(1972, 10, 1) .with(PlainDate.WEEKDAY_IN_MONTH.setToLast(Weekday.SUNDAY)), PlainTime.of(2, 0)), is(FOURTH)); } @Test public void getValidOffsetsOfGapTransition1() { assertThat( MODEL.getValidOffsets( PlainDate.of(1970, 1, 1), PlainTime.of(0, 29, 59)), is(TransitionModel.toList(1800))); assertThat( MODEL_EXT.getValidOffsets( PlainDate.of(1970, 1, 1), PlainTime.of(0, 29, 59)), is(TransitionModel.toList(1800))); } @Test public void getValidOffsetsOfGapTransition2() { List<ZonalOffset> offsets = Collections.emptyList(); assertThat( MODEL.getValidOffsets( PlainDate.of(1970, 1, 1), PlainTime.of(0, 30)), is(offsets)); assertThat( MODEL_EXT.getValidOffsets( PlainDate.of(1970, 1, 1), PlainTime.of(0, 30)), is(offsets)); } @Test public void getValidOffsetsOfGapTransition3() { List<ZonalOffset> offsets = Collections.emptyList(); assertThat( MODEL.getValidOffsets( PlainDate.of(1970, 1, 1), PlainTime.of(1, 59, 59)), is(offsets)); assertThat( MODEL_EXT.getValidOffsets( PlainDate.of(1970, 1, 1), PlainTime.of(1, 59, 59)), is(offsets)); } @Test public void getValidOffsetsOfGapTransition4() { assertThat( MODEL.getValidOffsets( PlainDate.of(1970, 1, 1), PlainTime.of(2, 0)), is(TransitionModel.toList(7200))); assertThat( MODEL_EXT.getValidOffsets( PlainDate.of(1970, 1, 1), PlainTime.of(2, 0)), is(TransitionModel.toList(7200))); } @Test public void getValidOffsetsOfOverlapTransition1() { assertThat( MODEL.getValidOffsets( PlainDate.of(1971, 1, 1), PlainTime.of(0, 59, 59)), is(TransitionModel.toList(7200))); assertThat( MODEL_EXT.getValidOffsets( PlainDate.of(1971, 1, 1), PlainTime.of(0, 59, 59)), is(TransitionModel.toList(7200))); } @Test public void getValidOffsetsOfOverlapTransition2() { assertThat( MODEL.getValidOffsets( PlainDate.of(1971, 1, 1), PlainTime.of(1, 0)), is(TransitionModel.toList(3600, 7200))); assertThat( MODEL_EXT.getValidOffsets( PlainDate.of(1971, 1, 1), PlainTime.of(1, 0)), is(TransitionModel.toList(3600, 7200))); } @Test public void getValidOffsetsOfOverlapTransition3() { assertThat( MODEL.getValidOffsets( PlainDate.of(1971, 1, 1), PlainTime.of(1, 59, 59)), is(TransitionModel.toList(3600, 7200))); assertThat( MODEL_EXT.getValidOffsets( PlainDate.of(1971, 1, 1), PlainTime.of(1, 59, 59)), is(TransitionModel.toList(3600, 7200))); } @Test public void getValidOffsetsOfOverlapTransition4() { assertThat( MODEL.getValidOffsets( PlainDate.of(1971, 1, 1), PlainTime.of(2, 0)), is(TransitionModel.toList(3600))); assertThat( MODEL_EXT.getValidOffsets( PlainDate.of(1971, 1, 1), PlainTime.of(2, 0)), is(TransitionModel.toList(3600))); } @Test public void getValidOffsetsBeforeStart() { assertThat( MODEL.getValidOffsets( PlainDate.of(1900, 1, 1), PlainTime.midnightAtStartOfDay()), is(TransitionModel.toList(1800))); assertThat( MODEL_EXT.getValidOffsets( PlainDate.of(1900, 1, 1), PlainTime.midnightAtStartOfDay()), is(TransitionModel.toList(1800))); } @Test public void getValidOffsetsAtStartOfYear2100() { assertThat( MODEL.getValidOffsets( PlainDate.of(2100, 1, 1), PlainTime.midnightAtStartOfDay()), is(TransitionModel.toList(3600))); assertThat( MODEL_EXT.getValidOffsets( PlainDate.of(2100, 1, 1), PlainTime.midnightAtStartOfDay()), is(TransitionModel.toList(3600))); } @Test public void getStdTransitions() throws IOException { List<ZonalTransition> expected = Arrays.asList(FIRST, SECOND, THIRD); List<ZonalTransition> expectedExt = Arrays.asList(FIRST, SECOND, THIRD, FOURTH, FIFTH); long t1 = THIRD.getPosixTime() + 1; long t2 = TransitionModel.getFutureMoment(1); long factor = (long) (365.2425 * 86400L); long minExpected = (t2 - t1) * 2 / factor + 2; // estimated assertThat( MODEL.getStdTransitions(), is(expected)); assertThat( MODEL_EXT.getStdTransitions().containsAll(expectedExt), is(true)); assertThat( (MODEL_EXT.getStdTransitions().size() >= minExpected), is(true)); } @Test public void getTransitions1() { assertThat( MODEL.getTransitions(new UT(0), new UT(FOURTH.getPosixTime())), is(Arrays.asList(FIRST, SECOND, THIRD))); assertThat( MODEL_EXT.getTransitions(new UT(0), new UT(FOURTH.getPosixTime())), is(Arrays.asList(FIRST, SECOND, THIRD))); } @Test public void getTransitions2() { assertThat( MODEL.getTransitions(new UT(0), new UT(FOURTH.getPosixTime() + 1)), is(Arrays.asList(FIRST, SECOND, THIRD, FOURTH))); assertThat( MODEL_EXT.getTransitions( new UT(0), new UT(FOURTH.getPosixTime() + 1)), is(Arrays.asList(FIRST, SECOND, THIRD, FOURTH))); } @Test public void isEmpty() { assertThat(MODEL.isEmpty(), is(false)); assertThat(MODEL_EXT.isEmpty(), is(false)); assertThat(MODEL_SINGLE.isEmpty(), is(false)); } @Test public void equals() { assertThat(MODEL.equals(MODEL_EXT), is(true)); } @Test public void identity() { assertThat(MODEL == MODEL_EXT, is(false)); } private static TransitionHistory createModel(boolean enlarged) { List<ZonalTransition> transitions = Arrays.asList(FIRST, THIRD, SECOND); DaylightSavingRule spring = GregorianTimezoneRule.ofLastWeekday( Month.MARCH, Weekday.SUNDAY, PlainTime.of(1), OffsetIndicator.UTC_TIME, 3600); DaylightSavingRule autumn = GregorianTimezoneRule.ofLastWeekday( Month.OCTOBER, Weekday.SUNDAY, PlainTime.of(1), OffsetIndicator.UTC_TIME, 0); List<DaylightSavingRule> rules = new ArrayList<>(); rules.add(autumn); rules.add(spring); if (enlarged) { return TransitionModel.of( ZonalOffset.ofTotalSeconds(FIRST.getPreviousOffset()), transitions, rules, true, true); } else { return new CompositeTransitionModel( 3, transitions, rules, true, true); } } private static TransitionHistory createSingleRuleModel() { List<ZonalTransition> transitions = Arrays.asList(FIRST, THIRD, SECOND); DaylightSavingRule rule = GregorianTimezoneRule.ofLastWeekday( Month.MARCH, Weekday.SUNDAY, PlainTime.of(1), OffsetIndicator.UTC_TIME, 3600); List<DaylightSavingRule> rules = new ArrayList<>(); rules.add(rule); return new CompositeTransitionModel( 1, transitions, rules, true, true); } // Hilfsklasse private static class UT implements UnixTime { private final long ut; UT(long ut) { super(); this.ut = ut; } @Override public long getPosixTime() { return this.ut; } @Override public int getNanosecond() { return 0; } } }