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.tz.GapResolver;
import net.time4j.tz.OverlapResolver;
import net.time4j.tz.Timezone;
import net.time4j.tz.TransitionStrategy;
import net.time4j.tz.ZonalOffset;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
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.junit.Assert.assertThat;
@RunWith(JUnit4.class)
public class TransitionResolverTest {
@Test
public void gap_PUSH_FORWARD() {
TransitionStrategy strategy =
GapResolver.PUSH_FORWARD.and(OverlapResolver.LATER_OFFSET);
Timezone tz =
Timezone
.of("RulesOfEU", createModelOfEuropeanUnion())
.with(strategy);
PlainDate date = PlainDate.of(2015, 3, 29);
PlainTime time = PlainTime.of(2, 30);
PlainTimestamp tsp = PlainTimestamp.of(date, time);
ZonalOffset offset = ZonalOffset.parse("UTC+02:00");
Moment expected =
PlainTimestamp.of(date, PlainTime.of(3, 30)).at(offset);
assertThat(tsp.in(tz), is(expected));
assertThat(strategy.getOffset(date, time, tz), is(offset));
}
@Test
public void gap_NEXT_VALID_TIME() {
TransitionStrategy strategy =
GapResolver.NEXT_VALID_TIME.and(OverlapResolver.LATER_OFFSET);
Timezone tz =
Timezone
.of("RulesOfEU", createModelOfEuropeanUnion())
.with(strategy);
PlainDate date = PlainDate.of(2015, 3, 29);
PlainTime time = PlainTime.of(2, 30);
PlainTimestamp tsp = PlainTimestamp.of(date, time);
ZonalOffset offset = ZonalOffset.parse("UTC+02:00");
Moment expected =
PlainTimestamp.of(date, PlainTime.of(3, 0)).at(offset);
assertThat(tsp.in(tz), is(expected));
assertThat(strategy.getOffset(date, time, tz), is(offset));
}
@Test(expected=IllegalArgumentException.class)
public void gap_resolve_ABORT() {
TransitionStrategy strategy =
GapResolver.ABORT.and(OverlapResolver.LATER_OFFSET);
Timezone tz =
Timezone
.of("RulesOfEU", createModelOfEuropeanUnion())
.with(strategy);
PlainDate date = PlainDate.of(2015, 3, 29);
PlainTime time = PlainTime.of(2, 30);
PlainTimestamp tsp = PlainTimestamp.of(date, time);
tsp.in(tz);
}
@Test(expected=IllegalArgumentException.class)
public void gap_getOffset_ABORT() {
TransitionStrategy strategy =
GapResolver.ABORT.and(OverlapResolver.LATER_OFFSET);
Timezone tz =
Timezone
.of("RulesOfEU", createModelOfEuropeanUnion())
.with(strategy);
PlainDate date = PlainDate.of(2015, 3, 29);
PlainTime time = PlainTime.of(2, 30);
strategy.getOffset(date, time, tz);
}
@Test
public void overlap_LATER_OFFSET() {
TransitionStrategy strategy =
GapResolver.PUSH_FORWARD.and(OverlapResolver.LATER_OFFSET);
Timezone tz =
Timezone
.of("RulesOfEU", createModelOfEuropeanUnion())
.with(strategy);
PlainDate date = PlainDate.of(2015, 10, 25);
PlainTime time = PlainTime.of(2, 30);
PlainTimestamp tsp = PlainTimestamp.of(date, time);
ZonalOffset offset = ZonalOffset.parse("UTC+01:00");
Moment expected =
PlainTimestamp.of(date, PlainTime.of(2, 30)).at(offset);
assertThat(tsp.in(tz), is(expected));
assertThat(strategy.getOffset(date, time, tz), is(offset));
}
@Test
public void overlap_EARLIER_OFFSET() {
TransitionStrategy strategy =
GapResolver.PUSH_FORWARD.and(OverlapResolver.EARLIER_OFFSET);
Timezone tz =
Timezone
.of("RulesOfEU", createModelOfEuropeanUnion())
.with(strategy);
PlainDate date = PlainDate.of(2015, 10, 25);
PlainTime time = PlainTime.of(2, 30);
PlainTimestamp tsp = PlainTimestamp.of(date, time);
ZonalOffset offset = ZonalOffset.parse("UTC+02:00");
Moment expected =
PlainTimestamp.of(date, PlainTime.of(2, 30)).at(offset);
assertThat(tsp.in(tz), is(expected));
assertThat(strategy.getOffset(date, time, tz), is(offset));
}
@Test
public void serialize_PUSH_FORWARD_and_LATER_OFFSET()
throws IOException, ClassNotFoundException {
Object strategy =
GapResolver.PUSH_FORWARD.and(OverlapResolver.LATER_OFFSET);
assertThat(roundtrip(strategy), is(strategy));
}
@Test
public void serialize_PUSH_FORWARD_and_EARLIER_OFFSET()
throws IOException, ClassNotFoundException {
Object strategy =
GapResolver.PUSH_FORWARD.and(OverlapResolver.EARLIER_OFFSET);
assertThat(roundtrip(strategy), is(strategy));
}
@Test
public void serialize_NEXT_VALID_TIME_and_LATER_OFFSET()
throws IOException, ClassNotFoundException {
Object strategy =
GapResolver.NEXT_VALID_TIME.and(OverlapResolver.LATER_OFFSET);
assertThat(roundtrip(strategy), is(strategy));
}
@Test
public void serialize_NEXT_VALID_TIME_and_EARLIER_OFFSET()
throws IOException, ClassNotFoundException {
Object strategy =
GapResolver.NEXT_VALID_TIME.and(OverlapResolver.EARLIER_OFFSET);
assertThat(roundtrip(strategy), is(strategy));
}
@Test
public void serialize_ABORT_and_LATER_OFFSET()
throws IOException, ClassNotFoundException {
Object strategy =
GapResolver.ABORT.and(OverlapResolver.LATER_OFFSET);
assertThat(roundtrip(strategy), is(strategy));
}
@Test
public void serialize_ABORT_and_EARLIER_OFFSET()
throws IOException, ClassNotFoundException {
Object strategy =
GapResolver.ABORT.and(OverlapResolver.EARLIER_OFFSET);
assertThat(roundtrip(strategy), is(strategy));
}
private static Object roundtrip(Object obj)
throws IOException, ClassNotFoundException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
byte[] data = baos.toByteArray();
oos.close();
ByteArrayInputStream bais = new ByteArrayInputStream(data);
ObjectInputStream ois = new ObjectInputStream(bais);
Object ser = ois.readObject();
ois.close();
return ser;
}
private static RuleBasedTransitionModel createModelOfEuropeanUnion() {
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<DaylightSavingRule>();
rules.add(autumn);
rules.add(spring);
return new RuleBasedTransitionModel(
ZonalOffset.ofTotalSeconds(3600),
rules);
}
}