Search in sources :

Example 16 with TimeZoneTransition

use of android.icu.util.TimeZoneTransition in project j2objc by google.

the class TimeZoneRuleTest method TestSimpleTimeZoneCoverage.

/*
     * API coverage test for BasicTimeZone APIs in SimpleTimeZone
     */
@Test
public void TestSimpleTimeZoneCoverage() {
    long time1 = getUTCMillis(1990, Calendar.JUNE, 1);
    long time2 = getUTCMillis(2000, Calendar.JUNE, 1);
    TimeZoneTransition tzt1, tzt2;
    // BasicTimeZone API implementation in SimpleTimeZone
    SimpleTimeZone stz1 = new SimpleTimeZone(-5 * HOUR, "GMT-5");
    tzt1 = stz1.getNextTransition(time1, false);
    if (tzt1 != null) {
        errln("FAIL: No transition must be returned by getNextTranstion for SimpleTimeZone with no DST rule");
    }
    tzt1 = stz1.getPreviousTransition(time1, false);
    if (tzt1 != null) {
        errln("FAIL: No transition must be returned by getPreviousTransition  for SimpleTimeZone with no DST rule");
    }
    TimeZoneRule[] tzrules = stz1.getTimeZoneRules();
    if (tzrules.length != 1 || !(tzrules[0] instanceof InitialTimeZoneRule)) {
        errln("FAIL: Invalid results returned by SimpleTimeZone#getTimeZoneRules");
    }
    // Set DST rule
    // March 11
    stz1.setStartRule(Calendar.MARCH, 11, 2 * HOUR);
    // First Sunday in November
    stz1.setEndRule(Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2 * HOUR);
    tzt1 = stz1.getNextTransition(time1, false);
    if (tzt1 == null) {
        errln("FAIL: Non-null transition must be returned by getNextTranstion for SimpleTimeZone with a DST rule");
    } else {
        String str = tzt1.toString();
        if (str == null || str.length() == 0) {
            errln("FAIL: TimeZoneTransition#toString returns null or empty string");
        } else {
            logln(str);
        }
    }
    tzt1 = stz1.getPreviousTransition(time1, false);
    if (tzt1 == null) {
        errln("FAIL: Non-null transition must be returned by getPreviousTransition  for SimpleTimeZone with a DST rule");
    }
    tzrules = stz1.getTimeZoneRules();
    if (tzrules.length != 3 || !(tzrules[0] instanceof InitialTimeZoneRule) || !(tzrules[1] instanceof AnnualTimeZoneRule) || !(tzrules[2] instanceof AnnualTimeZoneRule)) {
        errln("FAIL: Invalid results returned by SimpleTimeZone#getTimeZoneRules for a SimpleTimeZone with DST");
    }
    // Set DST start year
    stz1.setStartYear(2007);
    tzt1 = stz1.getPreviousTransition(time1, false);
    if (tzt1 != null) {
        errln("FAIL: No transition must be returned before 1990");
    }
    // transition after 1990-06-01
    tzt1 = stz1.getNextTransition(time1, false);
    // transition after 2000-06-01
    tzt2 = stz1.getNextTransition(time2, false);
    if (tzt1 == null || tzt2 == null || !tzt1.equals(tzt2)) {
        errln("FAIL: Bad transition returned by SimpleTimeZone#getNextTransition");
    }
}
Also used : InitialTimeZoneRule(android.icu.util.InitialTimeZoneRule) TimeArrayTimeZoneRule(android.icu.util.TimeArrayTimeZoneRule) AnnualTimeZoneRule(android.icu.util.AnnualTimeZoneRule) TimeZoneRule(android.icu.util.TimeZoneRule) TimeZoneTransition(android.icu.util.TimeZoneTransition) InitialTimeZoneRule(android.icu.util.InitialTimeZoneRule) SimpleTimeZone(android.icu.util.SimpleTimeZone) AnnualTimeZoneRule(android.icu.util.AnnualTimeZoneRule) Test(org.junit.Test)

Example 17 with TimeZoneTransition

use of android.icu.util.TimeZoneTransition in project j2objc by google.

the class TimeZoneTest method isDaylightTimeAvailable.

private static boolean isDaylightTimeAvailable(TimeZone tz, long start) {
    if (tz.inDaylightTime(new Date(start))) {
        return true;
    }
    long date;
    if (tz instanceof BasicTimeZone) {
        BasicTimeZone btz = (BasicTimeZone) tz;
        // check future transitions, up to 100
        date = start;
        for (int i = 0; i < 100; i++) {
            TimeZoneTransition tzt = btz.getNextTransition(date, false);
            if (tzt == null) {
                // no more transitions
                break;
            }
            if (tzt.getTo().getDSTSavings() != 0) {
                return true;
            }
            date = tzt.getTime();
        }
    } else {
        // check future times by incrementing 30 days, up to 200 times (about 16 years)
        final long inc = 30L * 24 * 60 * 60 * 1000;
        int[] offsets = new int[2];
        date = start + inc;
        for (int i = 0; i < 200; i++, date += inc) {
            tz.getOffset(date, false, offsets);
            if (offsets[1] != 0) {
                return true;
            }
        }
    }
    return false;
}
Also used : BasicTimeZone(android.icu.util.BasicTimeZone) TimeZoneTransition(android.icu.util.TimeZoneTransition) Date(java.util.Date)

Example 18 with TimeZoneTransition

use of android.icu.util.TimeZoneTransition in project j2objc by google.

the class IcuZoneRulesProviderTest method testTransitionsNearInstants.

/**
 * Verifies that ICU and java.time return the same transitions before and after a pre-selected
 * set of instants in time.
 */
@Test
public void testTransitionsNearInstants() {
    // An arbitrary set of instants at which to test the offsets in both implementations.
    Instant[] instants = new Instant[] { LocalDateTime.of(1900, Month.DECEMBER, 24, 12, 0).toInstant(ZoneOffset.UTC), LocalDateTime.of(1970, Month.JANUARY, 1, 2, 3).toInstant(ZoneOffset.UTC), LocalDateTime.of(1980, Month.FEBRUARY, 4, 5, 6).toInstant(ZoneOffset.UTC), LocalDateTime.of(1990, Month.MARCH, 7, 8, 9).toInstant(ZoneOffset.UTC), LocalDateTime.of(2000, Month.APRIL, 10, 11, 12).toInstant(ZoneOffset.UTC), LocalDateTime.of(2016, Month.MAY, 13, 14, 15).toInstant(ZoneOffset.UTC), LocalDateTime.of(2020, Month.JUNE, 16, 17, 18).toInstant(ZoneOffset.UTC), LocalDateTime.of(2100, Month.JULY, 19, 20, 21).toInstant(ZoneOffset.UTC), // updates don't break on the then-current date.
    Instant.now() };
    // Coincidentally this test verifies that all zones can be converted to ZoneRules and
    // don't violate any of the assumptions of IcuZoneRulesProvider.
    ZoneRules rules = ZoneRulesProvider.getRules(zoneId, false);
    BasicTimeZone timeZone = (BasicTimeZone) TimeZone.getTimeZone(zoneId);
    int[] icuOffsets = new int[2];
    for (Instant instant : instants) {
        ZoneOffset offset = rules.getOffset(instant);
        Duration daylightSavings = rules.getDaylightSavings(instant);
        timeZone.getOffset(instant.toEpochMilli(), false, icuOffsets);
        assertEquals("total offset for " + zoneId + " at " + instant, icuOffsets[1] + icuOffsets[0], offset.getTotalSeconds() * 1000);
        assertEquals("dst offset for " + zoneId + " at " + instant, icuOffsets[1], daylightSavings.toMillis());
        ZoneOffsetTransition jtTrans;
        TimeZoneTransition icuTrans;
        jtTrans = rules.nextTransition(instant);
        icuTrans = timeZone.getNextTransition(instant.toEpochMilli(), false);
        while (isIcuOnlyTransition(icuTrans)) {
            icuTrans = timeZone.getNextTransition(icuTrans.getTime(), false);
        }
        assertEquivalent(icuTrans, jtTrans);
        jtTrans = rules.previousTransition(instant);
        icuTrans = timeZone.getPreviousTransition(instant.toEpochMilli(), false);
        // Find previous "real" transition.
        while (isIcuOnlyTransition(icuTrans)) {
            icuTrans = timeZone.getPreviousTransition(icuTrans.getTime(), false);
        }
        assertEquivalent(icuTrans, jtTrans);
    }
}
Also used : BasicTimeZone(android.icu.util.BasicTimeZone) TimeZoneTransition(android.icu.util.TimeZoneTransition) Instant(java.time.Instant) ZoneRules(java.time.zone.ZoneRules) Duration(java.time.Duration) ZoneOffsetTransition(java.time.zone.ZoneOffsetTransition) ZoneOffset(java.time.ZoneOffset) Test(org.junit.Test)

Example 19 with TimeZoneTransition

use of android.icu.util.TimeZoneTransition in project j2objc by google.

the class IcuZoneRulesProviderTest method testAllTransitions.

/**
 * Verifies that ICU and java.time rules return the same transitions between 1900 and 2100.
 */
@Test
public void testAllTransitions() {
    final Instant start = LocalDateTime.of(1900, Month.JANUARY, 1, 12, 0).toInstant(ZoneOffset.UTC);
    // Many timezones have ongoing DST changes, so they would generate transitions endlessly.
    // Pick a far-future end date to stop comparing in that case.
    final Instant end = LocalDateTime.of(2100, Month.DECEMBER, 31, 12, 0).toInstant(ZoneOffset.UTC);
    ZoneRules rules = ZoneRulesProvider.getRules(zoneId, false);
    BasicTimeZone timeZone = (BasicTimeZone) TimeZone.getTimeZone(zoneId);
    Instant instant = start;
    while (instant.isBefore(end)) {
        ZoneOffsetTransition jtTrans;
        TimeZoneTransition icuTrans;
        jtTrans = rules.nextTransition(instant);
        icuTrans = timeZone.getNextTransition(instant.toEpochMilli(), false);
        while (isIcuOnlyTransition(icuTrans)) {
            icuTrans = timeZone.getNextTransition(icuTrans.getTime(), false);
        }
        assertEquivalent(icuTrans, jtTrans);
        if (jtTrans == null) {
            break;
        }
        instant = jtTrans.getInstant();
    }
}
Also used : BasicTimeZone(android.icu.util.BasicTimeZone) TimeZoneTransition(android.icu.util.TimeZoneTransition) Instant(java.time.Instant) ZoneRules(java.time.zone.ZoneRules) ZoneOffsetTransition(java.time.zone.ZoneOffsetTransition) Test(org.junit.Test)

Example 20 with TimeZoneTransition

use of android.icu.util.TimeZoneTransition in project j2objc by google.

the class IcuZoneRulesProvider method generateZoneRules.

/*
     * This implementation is only tested with BasicTimeZone objects and depends on
     * implementation details of that class:
     *
     * 0. TimeZone.getFrozenTimeZone() always returns a BasicTimeZone object.
     * 1. The first rule is always an InitialTimeZoneRule (guaranteed by spec).
     * 2. AnnualTimeZoneRules are only used as "final rules".
     * 3. The final rules are either 0 or 2 AnnualTimeZoneRules
     * 4. The final rules have endYear set to MAX_YEAR.
     * 5. Each transition generated by the rules changes either the raw offset, the total offset
     *    or both.
     * 6. There is a non-immense number of transitions for any rule before the final rules apply
     *    (enforced via the arbitrary limit defined in MAX_TRANSITIONS).
     *
     * Assumptions #5 and #6 are not strictly required for this code to work, but hold for the
     * the data and code at the time of implementation. If they were broken they would indicate
     * an incomplete understanding of how ICU TimeZoneRules are used which would probably mean that
     * this code needs to be updated.
     *
     * These assumptions are verified using the verify() method where appropriate.
     */
static ZoneRules generateZoneRules(String zoneId) {
    TimeZone timeZone = TimeZone.getFrozenTimeZone(zoneId);
    // Assumption #0
    verify(timeZone instanceof BasicTimeZone, zoneId, "Unexpected time zone class " + timeZone.getClass());
    BasicTimeZone tz = (BasicTimeZone) timeZone;
    TimeZoneRule[] rules = tz.getTimeZoneRules();
    // Assumption #1
    InitialTimeZoneRule initial = (InitialTimeZoneRule) rules[0];
    ZoneOffset baseStandardOffset = millisToOffset(initial.getRawOffset());
    ZoneOffset baseWallOffset = millisToOffset((initial.getRawOffset() + initial.getDSTSavings()));
    List<ZoneOffsetTransition> standardOffsetTransitionList = new ArrayList<>();
    List<ZoneOffsetTransition> transitionList = new ArrayList<>();
    List<ZoneOffsetTransitionRule> lastRules = new ArrayList<>();
    int preLastDstSavings = 0;
    AnnualTimeZoneRule last1 = null;
    AnnualTimeZoneRule last2 = null;
    TimeZoneTransition transition = tz.getNextTransition(Long.MIN_VALUE, false);
    int transitionCount = 1;
    // "last rules" in java.time) the "break transitionLoop" will be used to exit the loop.
    transitionLoop: while (transition != null) {
        TimeZoneRule from = transition.getFrom();
        TimeZoneRule to = transition.getTo();
        boolean hadEffect = false;
        if (from.getRawOffset() != to.getRawOffset()) {
            standardOffsetTransitionList.add(new ZoneOffsetTransition(TimeUnit.MILLISECONDS.toSeconds(transition.getTime()), millisToOffset(from.getRawOffset()), millisToOffset(to.getRawOffset())));
            hadEffect = true;
        }
        int fromTotalOffset = from.getRawOffset() + from.getDSTSavings();
        int toTotalOffset = to.getRawOffset() + to.getDSTSavings();
        if (fromTotalOffset != toTotalOffset) {
            transitionList.add(new ZoneOffsetTransition(TimeUnit.MILLISECONDS.toSeconds(transition.getTime()), millisToOffset(fromTotalOffset), millisToOffset(toTotalOffset)));
            hadEffect = true;
        }
        // Assumption #5
        verify(hadEffect, zoneId, "Transition changed neither total nor raw offset.");
        if (to instanceof AnnualTimeZoneRule) {
            // The presence of an AnnualTimeZoneRule is taken as an indication of a final rule.
            if (last1 == null) {
                preLastDstSavings = from.getDSTSavings();
                last1 = (AnnualTimeZoneRule) to;
                // Assumption #4
                verify(last1.getEndYear() == AnnualTimeZoneRule.MAX_YEAR, zoneId, "AnnualTimeZoneRule is not permanent.");
            } else {
                last2 = (AnnualTimeZoneRule) to;
                // Assumption #4
                verify(last2.getEndYear() == AnnualTimeZoneRule.MAX_YEAR, zoneId, "AnnualTimeZoneRule is not permanent.");
                // Assumption #3
                transition = tz.getNextTransition(transition.getTime(), false);
                verify(transition.getTo() == last1, zoneId, "Unexpected rule after 2 AnnualTimeZoneRules.");
                break transitionLoop;
            }
        } else {
            // Assumption #2
            verify(last1 == null, zoneId, "Unexpected rule after AnnualTimeZoneRule.");
        }
        verify(transitionCount <= MAX_TRANSITIONS, zoneId, "More than " + MAX_TRANSITIONS + " transitions.");
        transition = tz.getNextTransition(transition.getTime(), false);
        transitionCount++;
    }
    if (last1 != null) {
        // Assumption #3
        verify(last2 != null, zoneId, "Only one AnnualTimeZoneRule.");
        lastRules.add(toZoneOffsetTransitionRule(last1, preLastDstSavings));
        lastRules.add(toZoneOffsetTransitionRule(last2, last1.getDSTSavings()));
    }
    return ZoneRules.of(baseStandardOffset, baseWallOffset, standardOffsetTransitionList, transitionList, lastRules);
}
Also used : InitialTimeZoneRule(android.icu.util.InitialTimeZoneRule) AnnualTimeZoneRule(android.icu.util.AnnualTimeZoneRule) ArrayList(java.util.ArrayList) ZoneOffset(java.time.ZoneOffset) InitialTimeZoneRule(android.icu.util.InitialTimeZoneRule) AnnualTimeZoneRule(android.icu.util.AnnualTimeZoneRule) TimeZoneRule(android.icu.util.TimeZoneRule) TimeZone(android.icu.util.TimeZone) BasicTimeZone(android.icu.util.BasicTimeZone) BasicTimeZone(android.icu.util.BasicTimeZone) TimeZoneTransition(android.icu.util.TimeZoneTransition)

Aggregations

TimeZoneTransition (android.icu.util.TimeZoneTransition)22 BasicTimeZone (android.icu.util.BasicTimeZone)17 Test (org.junit.Test)8 TimeZone (android.icu.util.TimeZone)6 AnnualTimeZoneRule (android.icu.util.AnnualTimeZoneRule)5 InitialTimeZoneRule (android.icu.util.InitialTimeZoneRule)5 TimeZoneRule (android.icu.util.TimeZoneRule)5 Date (java.util.Date)5 Calendar (android.icu.util.Calendar)4 SimpleTimeZone (android.icu.util.SimpleTimeZone)4 TimeArrayTimeZoneRule (android.icu.util.TimeArrayTimeZoneRule)4 VTimeZone (android.icu.util.VTimeZone)3 ByteArrayInputStream (java.io.ByteArrayInputStream)2 ByteArrayOutputStream (java.io.ByteArrayOutputStream)2 IOException (java.io.IOException)2 InputStreamReader (java.io.InputStreamReader)2 OutputStreamWriter (java.io.OutputStreamWriter)2 Instant (java.time.Instant)2 ZoneOffset (java.time.ZoneOffset)2 ZoneOffsetTransition (java.time.zone.ZoneOffsetTransition)2