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.SystemClock; import net.time4j.Weekday; import net.time4j.tz.OffsetSign; import net.time4j.tz.ZonalOffset; import net.time4j.tz.ZonalTransition; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.concurrent.TimeUnit; 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 RulesLikeBerlin1947Test { private static final ZonalOffset CET = ZonalOffset.ofHours(OffsetSign.AHEAD_OF_UTC, 1); private static final ZonalOffset CEST = ZonalOffset.ofHours(OffsetSign.AHEAD_OF_UTC, 2); private static final ZonalOffset CEMT = ZonalOffset.ofHours(OffsetSign.AHEAD_OF_UTC, 3); private static final RuleBasedTransitionModel MODEL = createModel(); private static final ZonalTransition SPRING_1947 = new ZonalTransition( PlainTimestamp.of(1947, 4, 6, 3, 0) .at(CET) .getPosixTime(), 3600, 2 * 3600, 3600); private static final ZonalTransition SUMMER_START_1947 = new ZonalTransition( PlainTimestamp.of(1947, 5, 11, 2, 0) .at(CET) .getPosixTime(), 2 * 3600, 3 * 3600, 7200); private static final ZonalTransition SUMMER_END_1947 = new ZonalTransition( PlainTimestamp.of(1947, 6, 29, 3, 0) .at(CEMT) .getPosixTime(), 3 * 3600, 2 * 3600, 3600); private static final ZonalTransition AUTUMN_1947 = new ZonalTransition( PlainDate.of(1947, Month.OCTOBER, 1) .with(PlainDate.WEEKDAY_IN_MONTH.setToFirst(Weekday.SUNDAY)) .atTime(2, 0) .at(CET) .getPosixTime(), 2 * 3600, 3600, 0); @Test public void getInitialOffset() { assertThat( MODEL.getInitialOffset(), is(CET)); } @Test public void getStdTransitions() { ZonalTransition spring1970 = new ZonalTransition( PlainTimestamp.of(1970, 4, 6, 3, 0) .at(CET) .getPosixTime(), 3600, 2 * 3600, 3600); int year = SystemClock.inZonalView(CET).today().getYear(); ZonalTransition autumnCurrentYear = new ZonalTransition( PlainDate.of(year, Month.OCTOBER, 1) .with(PlainDate.WEEKDAY_IN_MONTH.setToFirst(Weekday.SUNDAY)) .atTime(2, 0) .at(CET) .getPosixTime(), 2 * 3600, 3600, 0); List<ZonalTransition> stdTransitions = MODEL.getStdTransitions(); assertThat( stdTransitions.contains(spring1970), is(true)); assertThat( stdTransitions.contains(autumnCurrentYear), is(true)); } @Test public void getTransitions() { Moment start = PlainTimestamp.of(1947, 1, 1, 0, 0, 0).at(CET); Moment end = PlainTimestamp.of(1947, 12, 31, 24, 0, 0).at(CET); List<ZonalTransition> transitions = MODEL.getTransitions(start, end); List<ZonalTransition> expected = Arrays.asList( SPRING_1947, SUMMER_START_1947, SUMMER_END_1947, AUTUMN_1947); assertThat(transitions, is(expected)); } @Test public void isEmpty() { assertThat(MODEL.isEmpty(), is(false)); } @Test public void getValidOffsetsBeforeSummerStartTransition() { assertThat( MODEL.getValidOffsets( PlainDate.of(1947, 5, 11), PlainTime.of(2, 59) ), is(Collections.singletonList(CEST))); } @Test public void getValidOffsetsAtSummerStartTransition() { List<ZonalOffset> expected = Collections.emptyList(); assertThat( MODEL.getValidOffsets( PlainDate.of(1947, 5, 11), PlainTime.of(3, 0) ), is(expected)); assertThat( MODEL.getValidOffsets( PlainDate.of(1947, 5, 11), PlainTime.of(3, 59) ), is(expected)); } @Test public void getValidOffsetsAfterSummerStartTransition() { assertThat( MODEL.getValidOffsets( PlainDate.of(1947, 5, 11), PlainTime.of(4, 0) ), is(Collections.singletonList(CEMT))); } @Test public void getValidOffsetsBeforeSummerEndTransition() { assertThat( MODEL.getValidOffsets( PlainDate.of(1947, 6, 29), PlainTime.of(1, 59) ), is(Collections.singletonList(CEMT))); } @Test public void getValidOffsetsAtSummerEndTransition() { List<ZonalOffset> expected = Arrays.asList(CEST, CEMT); assertThat( MODEL.getValidOffsets( PlainDate.of(1947, 6, 29), PlainTime.of(2, 0) ), is(expected)); assertThat( MODEL.getValidOffsets( PlainDate.of(1947, 6, 29), PlainTime.of(2, 59) ), is(expected)); } @Test public void getValidOffsetsAfterSummerEndTransition() { assertThat( MODEL.getValidOffsets( PlainDate.of(1947, 6, 29), PlainTime.of(3, 0) ), is(Collections.singletonList(CEST))); } @Test public void getConflictBeforeSummerStartTransition() { assertThat( MODEL.getConflictTransition( PlainDate.of(1947, 5, 11), PlainTime.of(2, 59) ), nullValue()); } @Test public void getConflictAtSummerStartTransition() { assertThat( MODEL.getConflictTransition( PlainDate.of(1947, 5, 11), PlainTime.of(3, 0) ), is(SUMMER_START_1947)); assertThat( MODEL.getConflictTransition( PlainDate.of(1947, 5, 11), PlainTime.of(3, 59) ), is(SUMMER_START_1947)); } @Test public void getConflictAfterSummerStartTransition() { assertThat( MODEL.getConflictTransition( PlainDate.of(1947, 5, 11), PlainTime.of(4, 0) ), nullValue()); } @Test public void getConflictBeforeSummerEndTransition() { assertThat( MODEL.getConflictTransition( PlainDate.of(1947, 6, 29), PlainTime.of(1, 59) ), nullValue()); } @Test public void getConflictAtSummerEndTransition() { assertThat( MODEL.getConflictTransition( PlainDate.of(1947, 6, 29), PlainTime.of(2, 0) ), is(SUMMER_END_1947)); assertThat( MODEL.getConflictTransition( PlainDate.of(1947, 6, 29), PlainTime.of(2, 59) ), is(SUMMER_END_1947)); } @Test public void getConflictAfterSummerEndTransition() { assertThat( MODEL.getConflictTransition( PlainDate.of(1947, 6, 29), PlainTime.of(3, 0) ), nullValue()); } @Test public void getStartTransition1() { Moment utc = PlainDate.of(1947, 5, 11) .atTime(2, 0) .at(CET) .minus(1, TimeUnit.SECONDS); assertThat( MODEL.getStartTransition(utc), is(SPRING_1947)); } @Test public void getStartTransition2() { Moment utc = PlainDate.of(1947, 5, 11).atTime(2, 0).at(CET); assertThat( MODEL.getStartTransition(utc), is(SUMMER_START_1947)); } @Test public void getStartTransition3() { Moment utc = PlainDate.of(1947, 6, 29) .atTime(3, 0) .at(CEMT) .minus(1, TimeUnit.SECONDS); assertThat( MODEL.getStartTransition(utc), is(SUMMER_START_1947)); } @Test public void getStartTransition4() { Moment utc = PlainDate.of(1947, 6, 29).atTime(3, 0).at(CEMT); assertThat( MODEL.getStartTransition(utc), is(SUMMER_END_1947)); } @Test public void findNextTransition1() { Moment utc = PlainDate.of(1947, 5, 11) .atTime(2, 0) .at(CET) .minus(1, TimeUnit.SECONDS); assertThat( MODEL.findNextTransition(utc).get(), is(SUMMER_START_1947)); } @Test public void findNextTransition2() { Moment utc = PlainDate.of(1947, 5, 11).atTime(2, 0).at(CET); assertThat( MODEL.findNextTransition(utc).get(), is(SUMMER_END_1947)); } @Test public void findNextTransition3() { Moment utc = PlainDate.of(1947, 6, 29) .atTime(3, 0) .at(CEMT) .minus(1, TimeUnit.SECONDS); assertThat( MODEL.findNextTransition(utc).get(), is(SUMMER_END_1947)); } @Test public void findNextTransition4() { Moment utc = PlainDate.of(1947, 6, 29).atTime(3, 0).at(CEMT); assertThat( MODEL.findNextTransition(utc).get(), is(AUTUMN_1947)); } private static RuleBasedTransitionModel createModel() { DaylightSavingRule spring = GregorianTimezoneRule.ofFixedDay( Month.APRIL, 6, PlainTime.of(3), OffsetIndicator.STANDARD_TIME, 3600); DaylightSavingRule startHighSummer = GregorianTimezoneRule.ofFixedDay( Month.MAY, 11, PlainTime.of(2), OffsetIndicator.STANDARD_TIME, 7200); DaylightSavingRule endHighSummer = GregorianTimezoneRule.ofFixedDay( Month.JUNE, 29, PlainTime.of(3), OffsetIndicator.WALL_TIME, 3600); DaylightSavingRule autumn = GregorianTimezoneRule.ofWeekdayAfterDate( Month.OCTOBER, 1, Weekday.SUNDAY, PlainTime.of(2), OffsetIndicator.STANDARD_TIME, 0); List<DaylightSavingRule> rules = new ArrayList<>(); rules.add(spring); rules.add(startHighSummer); rules.add(endHighSummer); rules.add(autumn); return new RuleBasedTransitionModel(CET, rules); } }