16f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
26f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*******************************************************************************
36f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* Copyright (C) 2007-2013, International Business Machines Corporation and
46f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* others. All Rights Reserved.
56f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*******************************************************************************
66f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
76f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
86f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/utypes.h"
96f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if !UCONFIG_NO_FORMATTING
116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/basictz.h"
136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "gregoimp.h"
146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "uvector.h"
156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "cmemory.h"
166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_NAMESPACE_BEGIN
186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define MILLIS_PER_YEAR (365*24*60*60*1000.0)
206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgBasicTimeZone::BasicTimeZone()
226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org: TimeZone() {
236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgBasicTimeZone::BasicTimeZone(const UnicodeString &id)
266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org: TimeZone(id) {
276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgBasicTimeZone::BasicTimeZone(const BasicTimeZone& source)
306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org: TimeZone(source) {
316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgBasicTimeZone::~BasicTimeZone() {
346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUBool
376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgBasicTimeZone::hasEquivalentTransitions(const BasicTimeZone& tz, UDate start, UDate end,
386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                        UBool ignoreDstAmount, UErrorCode& status) const {
396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE(status)) {
406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return FALSE;
416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (hasSameRules(tz)) {
436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return TRUE;
446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Check the offsets at the start time
466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t raw1, raw2, dst1, dst2;
476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    getOffset(start, FALSE, raw1, dst1, status);
486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE(status)) {
496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return FALSE;
506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    tz.getOffset(start, FALSE, raw2, dst2, status);
526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE(status)) {
536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return FALSE;
546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (ignoreDstAmount) {
566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if ((raw1 + dst1 != raw2 + dst2)
576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            || (dst1 != 0 && dst2 == 0)
586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            || (dst1 == 0 && dst2 != 0)) {
596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return FALSE;
606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (raw1 != raw2 || dst1 != dst2) {
636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return FALSE;
646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Check transitions in the range
676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UDate time = start;
686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    TimeZoneTransition tr1, tr2;
696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while (TRUE) {
706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UBool avail1 = getNextTransition(time, FALSE, tr1);
716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UBool avail2 = tz.getNextTransition(time, FALSE, tr2);
726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (ignoreDstAmount) {
746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Skip a transition which only differ the amount of DST savings
756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            while (TRUE) {
766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (avail1
776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        && tr1.getTime() <= end
786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        && (tr1.getFrom()->getRawOffset() + tr1.getFrom()->getDSTSavings()
796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                == tr1.getTo()->getRawOffset() + tr1.getTo()->getDSTSavings())
806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        && (tr1.getFrom()->getDSTSavings() != 0 && tr1.getTo()->getDSTSavings() != 0)) {
816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    getNextTransition(tr1.getTime(), FALSE, tr1);
826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    break;
846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            while (TRUE) {
876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (avail2
886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        && tr2.getTime() <= end
896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        && (tr2.getFrom()->getRawOffset() + tr2.getFrom()->getDSTSavings()
906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                == tr2.getTo()->getRawOffset() + tr2.getTo()->getDSTSavings())
916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        && (tr2.getFrom()->getDSTSavings() != 0 && tr2.getTo()->getDSTSavings() != 0)) {
926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    tz.getNextTransition(tr2.getTime(), FALSE, tr2);
936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    break;
956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UBool inRange1 = (avail1 && tr1.getTime() <= end);
1006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UBool inRange2 = (avail2 && tr2.getTime() <= end);
1016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (!inRange1 && !inRange2) {
1026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // No more transition in the range
1036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
1046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (!inRange1 || !inRange2) {
1066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return FALSE;
1076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (tr1.getTime() != tr2.getTime()) {
1096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return FALSE;
1106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (ignoreDstAmount) {
1126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (tr1.getTo()->getRawOffset() + tr1.getTo()->getDSTSavings()
1136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        != tr2.getTo()->getRawOffset() + tr2.getTo()->getDSTSavings()
1146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    || (tr1.getTo()->getDSTSavings() != 0 &&  tr2.getTo()->getDSTSavings() == 0)
1156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    || (tr1.getTo()->getDSTSavings() == 0 &&  tr2.getTo()->getDSTSavings() != 0)) {
1166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return FALSE;
1176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
1186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
1196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (tr1.getTo()->getRawOffset() != tr2.getTo()->getRawOffset() ||
1206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                tr1.getTo()->getDSTSavings() != tr2.getTo()->getDSTSavings()) {
1216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return FALSE;
1226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
1236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        time = tr1.getTime();
1256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return TRUE;
1276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
1306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgBasicTimeZone::getSimpleRulesNear(UDate date, InitialTimeZoneRule*& initial,
1316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        AnnualTimeZoneRule*& std, AnnualTimeZoneRule*& dst, UErrorCode& status) const {
1326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    initial = NULL;
1336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    std = NULL;
1346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    dst = NULL;
1356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE(status)) {
1366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
1376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t initialRaw, initialDst;
1396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UnicodeString initialName;
1406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    AnnualTimeZoneRule *ar1 = NULL;
1426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    AnnualTimeZoneRule *ar2 = NULL;
1436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UnicodeString name;
1446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UBool avail;
1466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    TimeZoneTransition tr;
1476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Get the next transition
1486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    avail = getNextTransition(date, FALSE, tr);
1496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (avail) {
1506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        tr.getFrom()->getName(initialName);
1516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        initialRaw = tr.getFrom()->getRawOffset();
1526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        initialDst = tr.getFrom()->getDSTSavings();
1536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // Check if the next transition is either DST->STD or STD->DST and
1556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // within roughly 1 year from the specified date
1566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UDate nextTransitionTime = tr.getTime();
1576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (((tr.getFrom()->getDSTSavings() == 0 && tr.getTo()->getDSTSavings() != 0)
1586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org              || (tr.getFrom()->getDSTSavings() != 0 && tr.getTo()->getDSTSavings() == 0))
1596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            && (date + MILLIS_PER_YEAR > nextTransitionTime)) {
1606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t year, month, dom, dow, doy, mid;
1626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            UDate d;
1636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Get local wall time for the next transition time
1656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            Grego::timeToFields(nextTransitionTime + initialRaw + initialDst,
1666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                year, month, dom, dow, doy, mid);
1676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t weekInMonth = Grego::dayOfWeekInMonth(year, month, dom);
1686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Create DOW rule
1696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            DateTimeRule *dtr = new DateTimeRule(month, weekInMonth, dow, mid, DateTimeRule::WALL_TIME);
1706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            tr.getTo()->getName(name);
1716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Note:  SimpleTimeZone does not support raw offset change.
1736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // So we always use raw offset of the given time for the rule,
1746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // even raw offset is changed.  This will result that the result
1756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // zone to return wrong offset after the transition.
1766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // When we encounter such case, we do not inspect next next
1776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // transition for another rule.
1786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ar1 = new AnnualTimeZoneRule(name, initialRaw, tr.getTo()->getDSTSavings(),
1796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                dtr, year, AnnualTimeZoneRule::MAX_YEAR);
1806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (tr.getTo()->getRawOffset() == initialRaw) {
1826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                // Get the next next transition
1836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                avail = getNextTransition(nextTransitionTime, FALSE, tr);
1846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (avail) {
1856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    // Check if the next next transition is either DST->STD or STD->DST
1866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    // and within roughly 1 year from the next transition
1876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if (((tr.getFrom()->getDSTSavings() == 0 && tr.getTo()->getDSTSavings() != 0)
1886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                          || (tr.getFrom()->getDSTSavings() != 0 && tr.getTo()->getDSTSavings() == 0))
1896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         && nextTransitionTime + MILLIS_PER_YEAR > tr.getTime()) {
1906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        // Get local wall time for the next transition time
1926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        Grego::timeToFields(tr.getTime() + tr.getFrom()->getRawOffset() + tr.getFrom()->getDSTSavings(),
1936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            year, month, dom, dow, doy, mid);
1946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        weekInMonth = Grego::dayOfWeekInMonth(year, month, dom);
1956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        // Generate another DOW rule
1966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        dtr = new DateTimeRule(month, weekInMonth, dow, mid, DateTimeRule::WALL_TIME);
1976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        tr.getTo()->getName(name);
1986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        ar2 = new AnnualTimeZoneRule(name, tr.getTo()->getRawOffset(), tr.getTo()->getDSTSavings(),
1996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            dtr, year - 1, AnnualTimeZoneRule::MAX_YEAR);
2006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        // Make sure this rule can be applied to the specified date
2026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        avail = ar2->getPreviousStart(date, tr.getFrom()->getRawOffset(), tr.getFrom()->getDSTSavings(), TRUE, d);
2036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        if (!avail || d > date
2046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                || initialRaw != tr.getTo()->getRawOffset()
2056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                || initialDst != tr.getTo()->getDSTSavings()) {
2066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            // We cannot use this rule as the second transition rule
2076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            delete ar2;
2086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            ar2 = NULL;
2096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        }
2106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
2116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
2126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
2136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (ar2 == NULL) {
2146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                // Try previous transition
2156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                avail = getPreviousTransition(date, TRUE, tr);
2166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (avail) {
2176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    // Check if the previous transition is either DST->STD or STD->DST.
2186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    // The actual transition time does not matter here.
2196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if ((tr.getFrom()->getDSTSavings() == 0 && tr.getTo()->getDSTSavings() != 0)
2206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        || (tr.getFrom()->getDSTSavings() != 0 && tr.getTo()->getDSTSavings() == 0)) {
2216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        // Generate another DOW rule
2236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        Grego::timeToFields(tr.getTime() + tr.getFrom()->getRawOffset() + tr.getFrom()->getDSTSavings(),
2246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            year, month, dom, dow, doy, mid);
2256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        weekInMonth = Grego::dayOfWeekInMonth(year, month, dom);
2266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        dtr = new DateTimeRule(month, weekInMonth, dow, mid, DateTimeRule::WALL_TIME);
2276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        tr.getTo()->getName(name);
2286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        // second rule raw/dst offsets should match raw/dst offsets
2306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        // at the given time
2316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        ar2 = new AnnualTimeZoneRule(name, initialRaw, initialDst,
2326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            dtr, ar1->getStartYear() - 1, AnnualTimeZoneRule::MAX_YEAR);
2336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        // Check if this rule start after the first rule after the specified date
2356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        avail = ar2->getNextStart(date, tr.getFrom()->getRawOffset(), tr.getFrom()->getDSTSavings(), FALSE, d);
2366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        if (!avail || d <= nextTransitionTime) {
2376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            // We cannot use this rule as the second transition rule
2386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            delete ar2;
2396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            ar2 = NULL;
2406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        }
2416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
2426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
2436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
2446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (ar2 == NULL) {
2456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                // Cannot find a good pair of AnnualTimeZoneRule
2466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                delete ar1;
2476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ar1 = NULL;
2486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
2496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                // The initial rule should represent the rule before the previous transition
2506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ar1->getName(initialName);
2516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                initialRaw = ar1->getRawOffset();
2526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                initialDst = ar1->getDSTSavings();
2536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
2546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    else {
2576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // Try the previous one
2586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        avail = getPreviousTransition(date, TRUE, tr);
2596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (avail) {
2606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            tr.getTo()->getName(initialName);
2616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            initialRaw = tr.getTo()->getRawOffset();
2626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            initialDst = tr.getTo()->getDSTSavings();
2636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
2646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // No transitions in the past.  Just use the current offsets
2656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            getOffset(date, FALSE, initialRaw, initialDst, status);
2666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (U_FAILURE(status)) {
2676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return;
2686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
2696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Set the initial rule
2726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    initial = new InitialTimeZoneRule(initialName, initialRaw, initialDst);
2736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Set the standard and daylight saving rules
2756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (ar1 != NULL && ar2 != NULL) {
2766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (ar1->getDSTSavings() != 0) {
2776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            dst = ar1;
2786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            std = ar2;
2796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
2806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            std = ar1;
2816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            dst = ar2;
2826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
2876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgBasicTimeZone::getTimeZoneRulesAfter(UDate start, InitialTimeZoneRule*& initial,
2886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     UVector*& transitionRules, UErrorCode& status) const {
2896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE(status)) {
2906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
2916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const InitialTimeZoneRule *orgini;
2946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const TimeZoneRule **orgtrs = NULL;
2956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    TimeZoneTransition tzt;
2966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UBool avail;
2976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UVector *orgRules = NULL;
2986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t ruleCount;
2996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    TimeZoneRule *r = NULL;
3006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UBool *done = NULL;
3016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    InitialTimeZoneRule *res_initial = NULL;
3026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UVector *filteredRules = NULL;
3036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UnicodeString name;
3046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t i;
3056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UDate time, t;
3066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UDate *newTimes = NULL;
3076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UDate firstStart;
3086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UBool bFinalStd = FALSE, bFinalDst = FALSE;
3096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Original transition rules
3116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ruleCount = countTransitionRules(status);
3126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE(status)) {
3136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
3146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    orgRules = new UVector(ruleCount, status);
3166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE(status)) {
3176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
3186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    orgtrs = (const TimeZoneRule**)uprv_malloc(sizeof(TimeZoneRule*)*ruleCount);
3206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (orgtrs == NULL) {
3216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        status = U_MEMORY_ALLOCATION_ERROR;
3226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        goto error;
3236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    getTimeZoneRules(orgini, orgtrs, ruleCount, status);
3256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE(status)) {
3266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        goto error;
3276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for (i = 0; i < ruleCount; i++) {
3296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        orgRules->addElement(orgtrs[i]->clone(), status);
3306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (U_FAILURE(status)) {
3316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            goto error;
3326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uprv_free(orgtrs);
3356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    orgtrs = NULL;
3366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    avail = getPreviousTransition(start, TRUE, tzt);
3386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (!avail) {
3396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // No need to filter out rules only applicable to time before the start
3406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        initial = orgini->clone();
3416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        transitionRules = orgRules;
3426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
3436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    done = (UBool*)uprv_malloc(sizeof(UBool)*ruleCount);
3466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (done == NULL) {
3476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        status = U_MEMORY_ALLOCATION_ERROR;
3486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        goto error;
3496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    filteredRules = new UVector(status);
3516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE(status)) {
3526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        goto error;
3536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Create initial rule
3566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    tzt.getTo()->getName(name);
3576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    res_initial = new InitialTimeZoneRule(name, tzt.getTo()->getRawOffset(),
3586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        tzt.getTo()->getDSTSavings());
3596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Mark rules which does not need to be processed
3616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for (i = 0; i < ruleCount; i++) {
3626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        r = (TimeZoneRule*)orgRules->elementAt(i);
3636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        avail = r->getNextStart(start, res_initial->getRawOffset(), res_initial->getDSTSavings(), FALSE, time);
3646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        done[i] = !avail;
3656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    time = start;
3686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while (!bFinalStd || !bFinalDst) {
3696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        avail = getNextTransition(time, FALSE, tzt);
3706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (!avail) {
3716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
3726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UDate updatedTime = tzt.getTime();
3746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (updatedTime == time) {
3756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Can get here if rules for start & end of daylight time have exactly
3766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // the same time.
3776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // TODO:  fix getNextTransition() to prevent it?
3786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            status = U_INVALID_STATE_ERROR;
3796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            goto error;
3806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        time = updatedTime;
3826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const TimeZoneRule *toRule = tzt.getTo();
3846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for (i = 0; i < ruleCount; i++) {
3856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            r = (TimeZoneRule*)orgRules->elementAt(i);
3866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (*r == *toRule) {
3876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                break;
3886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
3896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (i >= ruleCount) {
3916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // This case should never happen
3926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            status = U_INVALID_STATE_ERROR;
3936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            goto error;
3946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (done[i]) {
3966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            continue;
3976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const TimeArrayTimeZoneRule *tar = dynamic_cast<const TimeArrayTimeZoneRule *>(toRule);
3996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const AnnualTimeZoneRule *ar;
4006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (tar != NULL) {
4016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Get the previous raw offset and DST savings before the very first start time
4026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            TimeZoneTransition tzt0;
4036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            t = start;
4046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            while (TRUE) {
4056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                avail = getNextTransition(t, FALSE, tzt0);
4066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (!avail) {
4076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    break;
4086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
4096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (*(tzt0.getTo()) == *tar) {
4106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    break;
4116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
4126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                t = tzt0.getTime();
4136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
4146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (avail) {
4156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                // Check if the entire start times to be added
4166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                tar->getFirstStart(tzt.getFrom()->getRawOffset(), tzt.getFrom()->getDSTSavings(), firstStart);
4176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (firstStart > start) {
4186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    // Just add the rule as is
4196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    filteredRules->addElement(tar->clone(), status);
4206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if (U_FAILURE(status)) {
4216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        goto error;
4226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
4236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
4246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    // Colllect transitions after the start time
4256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    int32_t startTimes;
4266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    DateTimeRule::TimeRuleType timeType;
4276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    int32_t idx;
4286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    startTimes = tar->countStartTimes();
4306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    timeType = tar->getTimeType();
4316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    for (idx = 0; idx < startTimes; idx++) {
4326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        tar->getStartTimeAt(idx, t);
4336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        if (timeType == DateTimeRule::STANDARD_TIME) {
4346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            t -= tzt.getFrom()->getRawOffset();
4356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        }
4366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        if (timeType == DateTimeRule::WALL_TIME) {
4376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            t -= tzt.getFrom()->getDSTSavings();
4386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        }
4396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        if (t > start) {
4406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            break;
4416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        }
4426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
4436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    int32_t asize = startTimes - idx;
4446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if (asize > 0) {
4456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        newTimes = (UDate*)uprv_malloc(sizeof(UDate) * asize);
4466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        if (newTimes == NULL) {
4476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            status = U_MEMORY_ALLOCATION_ERROR;
4486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            goto error;
4496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        }
4506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        for (int32_t newidx = 0; newidx < asize; newidx++) {
4516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            tar->getStartTimeAt(idx + newidx, newTimes[newidx]);
4526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            if (U_FAILURE(status)) {
4536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                uprv_free(newTimes);
4546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                newTimes = NULL;
4556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                goto error;
4566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            }
4576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        }
4586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        tar->getName(name);
4596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        TimeArrayTimeZoneRule *newTar = new TimeArrayTimeZoneRule(name,
4606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            tar->getRawOffset(), tar->getDSTSavings(), newTimes, asize, timeType);
4616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        uprv_free(newTimes);
4626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        filteredRules->addElement(newTar, status);
4636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        if (U_FAILURE(status)) {
4646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            goto error;
4656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        }
4666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
4676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
4686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
4696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if ((ar = dynamic_cast<const AnnualTimeZoneRule *>(toRule)) != NULL) {
4706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ar->getFirstStart(tzt.getFrom()->getRawOffset(), tzt.getFrom()->getDSTSavings(), firstStart);
4716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (firstStart == tzt.getTime()) {
4726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                // Just add the rule as is
4736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                filteredRules->addElement(ar->clone(), status);
4746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (U_FAILURE(status)) {
4756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    goto error;
4766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
4776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
4786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                // Calculate the transition year
4796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                int32_t year, month, dom, dow, doy, mid;
4806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                Grego::timeToFields(tzt.getTime(), year, month, dom, dow, doy, mid);
4816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                // Re-create the rule
4826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ar->getName(name);
4836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                AnnualTimeZoneRule *newAr = new AnnualTimeZoneRule(name, ar->getRawOffset(), ar->getDSTSavings(),
4846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    *(ar->getRule()), year, ar->getEndYear());
4856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                filteredRules->addElement(newAr, status);
4866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (U_FAILURE(status)) {
4876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    goto error;
4886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
4896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
4906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // check if this is a final rule
4916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (ar->getEndYear() == AnnualTimeZoneRule::MAX_YEAR) {
4926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                // After bot final standard and dst rules are processed,
4936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                // exit this while loop.
4946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (ar->getDSTSavings() == 0) {
4956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    bFinalStd = TRUE;
4966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
4976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    bFinalDst = TRUE;
4986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
4996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
5006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        done[i] = TRUE;
5026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Set the results
5056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (orgRules != NULL) {
5066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while (!orgRules->isEmpty()) {
5076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            r = (TimeZoneRule*)orgRules->orphanElementAt(0);
5086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            delete r;
5096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        delete orgRules;
5116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (done != NULL) {
5136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_free(done);
5146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    initial = res_initial;
5176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    transitionRules = filteredRules;
5186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return;
5196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgerror:
5216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (orgtrs != NULL) {
5226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_free(orgtrs);
5236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (orgRules != NULL) {
5256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while (!orgRules->isEmpty()) {
5266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            r = (TimeZoneRule*)orgRules->orphanElementAt(0);
5276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            delete r;
5286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        delete orgRules;
5306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (done != NULL) {
5326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (filteredRules != NULL) {
5336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            while (!filteredRules->isEmpty()) {
5346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                r = (TimeZoneRule*)filteredRules->orphanElementAt(0);
5356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                delete r;
5366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
5376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            delete filteredRules;
5386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        delete res_initial;
5406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_free(done);
5416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    initial = NULL;
5446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    transitionRules = NULL;
5456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
5466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
5486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgBasicTimeZone::getOffsetFromLocal(UDate /*date*/, int32_t /*nonExistingTimeOpt*/, int32_t /*duplicatedTimeOpt*/,
5496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            int32_t& /*rawOffset*/, int32_t& /*dstOffset*/, UErrorCode& status) const {
5506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE(status)) {
5516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
5526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    status = U_UNSUPPORTED_ERROR;
5546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
5556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_NAMESPACE_END
5576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif /* #if !UCONFIG_NO_FORMATTING */
5596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//eof
561