Search in sources :

Example 21 with BasicTimeZone

use of android.icu.util.BasicTimeZone 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 22 with BasicTimeZone

use of android.icu.util.BasicTimeZone 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 23 with BasicTimeZone

use of android.icu.util.BasicTimeZone 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

BasicTimeZone (android.icu.util.BasicTimeZone)23 TimeZoneTransition (android.icu.util.TimeZoneTransition)15 Test (org.junit.Test)14 TimeZone (android.icu.util.TimeZone)11 SimpleTimeZone (android.icu.util.SimpleTimeZone)8 VTimeZone (android.icu.util.VTimeZone)8 Date (java.util.Date)8 AnnualTimeZoneRule (android.icu.util.AnnualTimeZoneRule)6 InitialTimeZoneRule (android.icu.util.InitialTimeZoneRule)6 RuleBasedTimeZone (android.icu.util.RuleBasedTimeZone)6 Calendar (android.icu.util.Calendar)4 TimeZoneRule (android.icu.util.TimeZoneRule)4 DateTimeRule (android.icu.util.DateTimeRule)3 TimeArrayTimeZoneRule (android.icu.util.TimeArrayTimeZoneRule)3 SimpleDateFormat (android.icu.text.SimpleDateFormat)2 ULocale (android.icu.util.ULocale)2 ByteArrayInputStream (java.io.ByteArrayInputStream)2 ByteArrayOutputStream (java.io.ByteArrayOutputStream)2 IOException (java.io.IOException)2 InputStreamReader (java.io.InputStreamReader)2