1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
38393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius* Copyright (C) 2007-2013, International Business Machines Corporation and
427f654740f2a26ad62a5c155af9199af9e69b889claireho* others. All Rights Reserved.
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#include "utypeinfo.h"  // for 'typeid' to work
927f654740f2a26ad62a5c155af9199af9e69b889claireho
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h"
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/rbtz.h"
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/gregocal.h"
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uvector.h"
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "gregoimp.h"
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cmemory.h"
198393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#include "umutex.h"
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_BEGIN
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * A struct representing a time zone transition
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct Transition {
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UDate time;
28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TimeZoneRule* from;
29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TimeZoneRule* to;
30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool compareRules(UVector* rules1, UVector* rules2) {
33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (rules1 == NULL && rules2 == NULL) {
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if (rules1 == NULL || rules2 == NULL) {
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t size = rules1->size();
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (size != rules2->size()) {
40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t i = 0; i < size; i++) {
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        TimeZoneRule *r1 = (TimeZoneRule*)rules1->elementAt(i);
44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        TimeZoneRule *r2 = (TimeZoneRule*)rules2->elementAt(i);
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (*r1 != *r2) {
46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return FALSE;
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(RuleBasedTimeZone)
53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::RuleBasedTimeZone(const UnicodeString& id, InitialTimeZoneRule* initialRule)
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru: BasicTimeZone(id), fInitialRule(initialRule), fHistoricRules(NULL), fFinalRules(NULL),
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  fHistoricTransitions(NULL), fUpToDate(FALSE) {
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::RuleBasedTimeZone(const RuleBasedTimeZone& source)
60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru: BasicTimeZone(source), fInitialRule(source.fInitialRule->clone()),
61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  fHistoricTransitions(NULL), fUpToDate(FALSE) {
62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fHistoricRules = copyRules(source.fHistoricRules);
63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFinalRules = copyRules(source.fFinalRules);
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (source.fUpToDate) {
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UErrorCode status = U_ZERO_ERROR;
66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        complete(status);
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::~RuleBasedTimeZone() {
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    deleteTransitions();
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    deleteRules();
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone&
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::operator=(const RuleBasedTimeZone& right) {
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (*this != right) {
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        BasicTimeZone::operator=(right);
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        deleteRules();
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fInitialRule = right.fInitialRule->clone();
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fHistoricRules = copyRules(right.fHistoricRules);
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fFinalRules = copyRules(right.fFinalRules);
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        deleteTransitions();
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fUpToDate = FALSE;
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::operator==(const TimeZone& that) const {
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (this == &that) {
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
9427f654740f2a26ad62a5c155af9199af9e69b889claireho    if (typeid(*this) != typeid(that)
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        || BasicTimeZone::operator==(that) == FALSE) {
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RuleBasedTimeZone *rbtz = (RuleBasedTimeZone*)&that;
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (*fInitialRule != *(rbtz->fInitialRule)) {
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (compareRules(fHistoricRules, rbtz->fHistoricRules)
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        && compareRules(fFinalRules, rbtz->fFinalRules)) {
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::operator!=(const TimeZone& that) const {
111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return !operator==(that);
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::addTransitionRule(TimeZoneRule* rule, UErrorCode& status) {
116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
11927f654740f2a26ad62a5c155af9199af9e69b889claireho    AnnualTimeZoneRule* atzrule = dynamic_cast<AnnualTimeZoneRule*>(rule);
12027f654740f2a26ad62a5c155af9199af9e69b889claireho    if (atzrule != NULL && atzrule->getEndYear() == AnnualTimeZoneRule::MAX_YEAR) {
121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // A final rule
122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (fFinalRules == NULL) {
123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fFinalRules = new UVector(status);
124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (U_FAILURE(status)) {
125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return;
126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else if (fFinalRules->size() >= 2) {
128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Cannot handle more than two final rules
129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            status = U_INVALID_STATE_ERROR;
130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fFinalRules->addElement((void*)rule, status);
133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Non-final rule
135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (fHistoricRules == NULL) {
136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fHistoricRules = new UVector(status);
137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (U_FAILURE(status)) {
138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return;
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fHistoricRules->addElement((void*)rule, status);
142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Mark dirty, so transitions are recalculated at next complete() call
144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fUpToDate = FALSE;
145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1478393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusstatic UMutex gLock = U_MUTEX_INITIALIZER;
1488393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
1498393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusvoid
1508393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusRuleBasedTimeZone::completeConst(UErrorCode& status) const {
1518393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    if (U_FAILURE(status)) {
1528393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        return;
1538393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
15459d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_lock(&gLock);
15559d709d503bab6e2b61931737e662dd293b40578ccornelius    if (!fUpToDate) {
15659d709d503bab6e2b61931737e662dd293b40578ccornelius        RuleBasedTimeZone *ncThis = const_cast<RuleBasedTimeZone*>(this);
15759d709d503bab6e2b61931737e662dd293b40578ccornelius        ncThis->complete(status);
1588393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
15959d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_unlock(&gLock);
1608393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius}
1618393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::complete(UErrorCode& status) {
164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fUpToDate) {
168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Make sure either no final rules or a pair of AnnualTimeZoneRules
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // are available.
172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fFinalRules != NULL && fFinalRules->size() != 2) {
173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        status = U_INVALID_STATE_ERROR;
174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool *done = NULL;
178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Create a TimezoneTransition and add to the list
179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fHistoricRules != NULL || fFinalRules != NULL) {
180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        TimeZoneRule *curRule = fInitialRule;
181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UDate lastTransitionTime = MIN_MILLIS;
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Build the transition array which represents historical time zone
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // transitions.
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (fHistoricRules != NULL && fHistoricRules->size() > 0) {
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t i;
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t historicCount = fHistoricRules->size();
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            done = (UBool*)uprv_malloc(sizeof(UBool) * historicCount);
189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (done == NULL) {
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                status = U_MEMORY_ALLOCATION_ERROR;
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                goto cleanup;
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for (i = 0; i < historicCount; i++) {
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                done[i] = FALSE;
195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while (TRUE) {
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                int32_t curStdOffset = curRule->getRawOffset();
198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                int32_t curDstSavings = curRule->getDSTSavings();
199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UDate nextTransitionTime = MAX_MILLIS;
200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                TimeZoneRule *nextRule = NULL;
201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                TimeZoneRule *r = NULL;
202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UBool avail;
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UDate tt;
204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UnicodeString curName, name;
205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                curRule->getName(curName);
206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                for (i = 0; i < historicCount; i++) {
208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (done[i]) {
209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        continue;
210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    r = (TimeZoneRule*)fHistoricRules->elementAt(i);
212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    avail = r->getNextStart(lastTransitionTime, curStdOffset, curDstSavings, false, tt);
213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (!avail) {
214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        // No more transitions from this rule - skip this rule next time
215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        done[i] = TRUE;
216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    } else {
217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        r->getName(name);
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        if (*r == *curRule ||
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            (name == curName && r->getRawOffset() == curRule->getRawOffset()
220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            && r->getDSTSavings() == curRule->getDSTSavings())) {
221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            continue;
222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        if (tt < nextTransitionTime) {
224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            nextTransitionTime = tt;
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            nextRule = r;
226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (nextRule ==  NULL) {
231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // Check if all historic rules are done
232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    UBool bDoneAll = TRUE;
233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    for (int32_t j = 0; j < historicCount; j++) {
234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        if (!done[j]) {
235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            bDoneAll = FALSE;
236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            break;
237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (bDoneAll) {
240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (fFinalRules != NULL) {
245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // Check if one of final rules has earlier transition date
246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    for (i = 0; i < 2 /* fFinalRules->size() */; i++) {
247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        TimeZoneRule *fr = (TimeZoneRule*)fFinalRules->elementAt(i);
248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        if (*fr == *curRule) {
249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            continue;
250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        r = (TimeZoneRule*)fFinalRules->elementAt(i);
252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        avail = r->getNextStart(lastTransitionTime, curStdOffset, curDstSavings, false, tt);
253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        if (avail) {
254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            if (tt < nextTransitionTime) {
255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                nextTransitionTime = tt;
256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                nextRule = r;
257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            }
258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (nextRule == NULL) {
263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // Nothing more
264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (fHistoricTransitions == NULL) {
268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    fHistoricTransitions = new UVector(status);
269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (U_FAILURE(status)) {
270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        goto cleanup;
271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                Transition *trst = (Transition*)uprv_malloc(sizeof(Transition));
274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (trst == NULL) {
275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    status = U_MEMORY_ALLOCATION_ERROR;
276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    goto cleanup;
277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                trst->time = nextTransitionTime;
279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                trst->from = curRule;
280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                trst->to = nextRule;
281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fHistoricTransitions->addElement(trst, status);
282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (U_FAILURE(status)) {
283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    goto cleanup;
284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                lastTransitionTime = nextTransitionTime;
286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                curRule = nextRule;
287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (fFinalRules != NULL) {
290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (fHistoricTransitions == NULL) {
291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fHistoricTransitions = new UVector(status);
292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (U_FAILURE(status)) {
293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    goto cleanup;
294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Append the first transition for each
297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            TimeZoneRule *rule0 = (TimeZoneRule*)fFinalRules->elementAt(0);
298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            TimeZoneRule *rule1 = (TimeZoneRule*)fFinalRules->elementAt(1);
299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UDate tt0, tt1;
300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UBool avail0 = rule0->getNextStart(lastTransitionTime, curRule->getRawOffset(), curRule->getDSTSavings(), false, tt0);
301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UBool avail1 = rule1->getNextStart(lastTransitionTime, curRule->getRawOffset(), curRule->getDSTSavings(), false, tt1);
302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (!avail0 || !avail1) {
303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Should not happen, because both rules are permanent
304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                status = U_INVALID_STATE_ERROR;
305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                goto cleanup;
306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            Transition *final0 = (Transition*)uprv_malloc(sizeof(Transition));
308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (final0 == NULL) {
309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                status = U_MEMORY_ALLOCATION_ERROR;
310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                goto cleanup;
311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            Transition *final1 = (Transition*)uprv_malloc(sizeof(Transition));
313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (final1 == NULL) {
31485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                uprv_free(final0);
315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                status = U_MEMORY_ALLOCATION_ERROR;
316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                goto cleanup;
317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (tt0 < tt1) {
319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                final0->time = tt0;
320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                final0->from = curRule;
321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                final0->to = rule0;
322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                rule1->getNextStart(tt0, rule0->getRawOffset(), rule0->getDSTSavings(), false, final1->time);
323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                final1->from = rule0;
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                final1->to = rule1;
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                final0->time = tt1;
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                final0->from = curRule;
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                final0->to = rule1;
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                rule0->getNextStart(tt1, rule1->getRawOffset(), rule1->getDSTSavings(), false, final1->time);
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                final1->from = rule1;
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                final1->to = rule0;
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fHistoricTransitions->addElement(final0, status);
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (U_FAILURE(status)) {
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                goto cleanup;
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fHistoricTransitions->addElement(final1, status);
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (U_FAILURE(status)) {
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                goto cleanup;
340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fUpToDate = TRUE;
344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (done != NULL) {
345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_free(done);
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return;
348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querucleanup:
350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    deleteTransitions();
351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (done != NULL) {
352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_free(done);
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fUpToDate = FALSE;
355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone*
358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::clone(void) const {
359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return new RuleBasedTimeZone(*this);
360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::getOffset(uint8_t era, int32_t year, int32_t month, int32_t day,
364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             uint8_t dayOfWeek, int32_t millis, UErrorCode& status) const {
365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (month < UCAL_JANUARY || month > UCAL_DECEMBER) {
369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        status = U_ILLEGAL_ARGUMENT_ERROR;
370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return getOffset(era, year, month, day, dayOfWeek, millis,
373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         Grego::monthLength(year, month), status);
374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::getOffset(uint8_t era, int32_t year, int32_t month, int32_t day,
379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             uint8_t /*dayOfWeek*/, int32_t millis,
380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t /*monthLength*/, UErrorCode& status) const {
381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // dayOfWeek and monthLength are unused
382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (era == GregorianCalendar::BC) {
386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Convert to extended year
387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        year = 1 - year;
388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t rawOffset, dstOffset;
390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UDate time = (UDate)Grego::fieldsToDay(year, month, day) * U_MILLIS_PER_DAY + millis;
391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    getOffsetInternal(time, TRUE, kDaylight, kStandard, rawOffset, dstOffset, status);
392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (rawOffset + dstOffset);
396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::getOffset(UDate date, UBool local, int32_t& rawOffset,
400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t& dstOffset, UErrorCode& status) const {
401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    getOffsetInternal(date, local, kFormer, kLatter, rawOffset, dstOffset, status);
402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt,
4068393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                      int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) const {
407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    getOffsetInternal(date, TRUE, nonExistingTimeOpt, duplicatedTimeOpt, rawOffset, dstOffset, status);
408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * The internal getOffset implementation
413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::getOffsetInternal(UDate date, UBool local,
416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt,
417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     int32_t& rawOffset, int32_t& dstOffset,
418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     UErrorCode& status) const {
419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    rawOffset = 0;
420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    dstOffset = 0;
421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (!fUpToDate) {
426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Transitions are not yet resolved.  We cannot do it here
427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // because this method is const.  Thus, do nothing and return
428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // error status.
429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        status = U_INVALID_STATE_ERROR;
430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const TimeZoneRule *rule = NULL;
433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fHistoricTransitions == NULL) {
434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        rule = fInitialRule;
435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UDate tstart = getTransitionTime((Transition*)fHistoricTransitions->elementAt(0),
437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            local, NonExistingTimeOpt, DuplicatedTimeOpt);
438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (date < tstart) {
439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            rule = fInitialRule;
440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t idx = fHistoricTransitions->size() - 1;
442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UDate tend = getTransitionTime((Transition*)fHistoricTransitions->elementAt(idx),
443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                local, NonExistingTimeOpt, DuplicatedTimeOpt);
444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (date > tend) {
445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (fFinalRules != NULL) {
446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    rule = findRuleInFinal(date, local, NonExistingTimeOpt, DuplicatedTimeOpt);
447103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                }
448103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                if (rule == NULL) {
449103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                    // no final rules or the given time is before the first transition
450103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                    // specified by the final rules -> use the last rule
451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    rule = ((Transition*)fHistoricTransitions->elementAt(idx))->to;
452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Find a historical transition
455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                while (idx >= 0) {
456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (date >= getTransitionTime((Transition*)fHistoricTransitions->elementAt(idx),
457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        local, NonExistingTimeOpt, DuplicatedTimeOpt)) {
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    idx--;
461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                rule = ((Transition*)fHistoricTransitions->elementAt(idx))->to;
463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (rule != NULL) {
467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        rawOffset = rule->getRawOffset();
468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        dstOffset = rule->getDSTSavings();
469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::setRawOffset(int32_t /*offsetMillis*/) {
474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // We don't support this operation at this moment.
475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Nothing to do!
476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::getRawOffset(void) const {
480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Note: This implementation returns standard GMT offset
481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // as of current time.
482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t raw, dst;
484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    getOffset(uprv_getUTCtime() * U_MILLIS_PER_SECOND,
485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        FALSE, raw, dst, status);
486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return raw;
487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::useDaylightTime(void) const {
491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Note: This implementation returns true when
492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // daylight saving time is used as of now or
493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // after the next transition.
494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UDate now = uprv_getUTCtime() * U_MILLIS_PER_SECOND;
496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t raw, dst;
497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    getOffset(now, FALSE, raw, dst, status);
498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (dst != 0) {
499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // If DST is not used now, check if DST is used after the next transition
502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UDate time;
503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TimeZoneRule *from, *to;
504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool avail = findNext(now, FALSE, time, from, to);
505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (avail && to->getDSTSavings() != 0) {
506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::inDaylightTime(UDate date, UErrorCode& status) const {
513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t raw, dst;
517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    getOffset(date, FALSE, raw, dst, status);
518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (dst != 0) {
519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::hasSameRules(const TimeZone& other) const {
526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (this == &other) {
527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
52927f654740f2a26ad62a5c155af9199af9e69b889claireho    if (typeid(*this) != typeid(other)) {
530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const RuleBasedTimeZone& that = (const RuleBasedTimeZone&)other;
533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (*fInitialRule != *(that.fInitialRule)) {
534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (compareRules(fHistoricRules, that.fHistoricRules)
537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        && compareRules(fFinalRules, that.fFinalRules)) {
538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
5448393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusRuleBasedTimeZone::getNextTransition(UDate base, UBool inclusive, TimeZoneTransition& result) const {
545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
5468393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    completeConst(status);
547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UDate transitionTime;
551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TimeZoneRule *fromRule, *toRule;
552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool found = findNext(base, inclusive, transitionTime, fromRule, toRule);
553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (found) {
554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result.setTime(transitionTime);
555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result.setFrom((const TimeZoneRule&)*fromRule);
556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result.setTo((const TimeZoneRule&)*toRule);
557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
5638393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusRuleBasedTimeZone::getPreviousTransition(UDate base, UBool inclusive, TimeZoneTransition& result) const {
564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
5658393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    completeConst(status);
566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UDate transitionTime;
570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TimeZoneRule *fromRule, *toRule;
571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool found = findPrev(base, inclusive, transitionTime, fromRule, toRule);
572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (found) {
573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result.setTime(transitionTime);
574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result.setFrom((const TimeZoneRule&)*fromRule);
575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result.setTo((const TimeZoneRule&)*toRule);
576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
5828393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusRuleBasedTimeZone::countTransitionRules(UErrorCode& /*status*/) const {
583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t count = 0;
584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fHistoricRules != NULL) {
585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        count += fHistoricRules->size();
586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fFinalRules != NULL) {
588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        count += fFinalRules->size();
589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return count;
591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::getTimeZoneRules(const InitialTimeZoneRule*& initial,
595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                    const TimeZoneRule* trsrules[],
596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                    int32_t& trscount,
5978393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                    UErrorCode& status) const {
598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Initial rule
602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    initial = fInitialRule;
603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Transition rules
605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t cnt = 0;
606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t idx;
607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fHistoricRules != NULL && cnt < trscount) {
608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t historicCount = fHistoricRules->size();
609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        idx = 0;
610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while (cnt < trscount && idx < historicCount) {
611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            trsrules[cnt++] = (const TimeZoneRule*)fHistoricRules->elementAt(idx++);
612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fFinalRules != NULL && cnt < trscount) {
615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t finalCount = fFinalRules->size();
616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        idx = 0;
617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while (cnt < trscount && idx < finalCount) {
618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            trsrules[cnt++] = (const TimeZoneRule*)fFinalRules->elementAt(idx++);
619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Set the result length
622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    trscount = cnt;
623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::deleteRules(void) {
627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete fInitialRule;
628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fInitialRule = NULL;
629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fHistoricRules != NULL) {
630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while (!fHistoricRules->isEmpty()) {
631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delete (TimeZoneRule*)(fHistoricRules->orphanElementAt(0));
632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete fHistoricRules;
634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fHistoricRules = NULL;
635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fFinalRules != NULL) {
637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while (!fFinalRules->isEmpty()) {
638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delete (AnnualTimeZoneRule*)(fFinalRules->orphanElementAt(0));
639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete fFinalRules;
641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fFinalRules = NULL;
642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::deleteTransitions(void) {
647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fHistoricTransitions != NULL) {
648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while (!fHistoricTransitions->isEmpty()) {
649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            Transition *trs = (Transition*)fHistoricTransitions->orphanElementAt(0);
650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_free(trs);
651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete fHistoricTransitions;
653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fHistoricTransitions = NULL;
655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUVector*
658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::copyRules(UVector* source) {
659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (source == NULL) {
660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode ec = U_ZERO_ERROR;
663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t size = source->size();
664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UVector *rules = new UVector(size, ec);
665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(ec)) {
666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t i;
669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (i = 0; i < size; i++) {
670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        rules->addElement(((TimeZoneRule*)source->elementAt(i))->clone(), ec);
671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(ec)) {
672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(ec)) {
676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // In case of error, clean up
677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (i = 0; i < rules->size(); i++) {
678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            TimeZoneRule *rule = (TimeZoneRule*)rules->orphanElementAt(i);
679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delete rule;
680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete rules;
682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return rules;
685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZoneRule*
688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::findRuleInFinal(UDate date, UBool local,
689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt) const {
690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fFinalRules == NULL) {
691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    AnnualTimeZoneRule* fr0 = (AnnualTimeZoneRule*)fFinalRules->elementAt(0);
695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    AnnualTimeZoneRule* fr1 = (AnnualTimeZoneRule*)fFinalRules->elementAt(1);
696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fr0 == NULL || fr1 == NULL) {
697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UDate start0, start1;
701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UDate base;
702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t localDelta;
703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    base = date;
705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (local) {
706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        localDelta = getLocalDelta(fr1->getRawOffset(), fr1->getDSTSavings(),
707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   fr0->getRawOffset(), fr0->getDSTSavings(),
708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   NonExistingTimeOpt, DuplicatedTimeOpt);
709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        base -= localDelta;
710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool avail0 = fr0->getPreviousStart(base, fr1->getRawOffset(), fr1->getDSTSavings(), TRUE, start0);
712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    base = date;
714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (local) {
715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        localDelta = getLocalDelta(fr0->getRawOffset(), fr0->getDSTSavings(),
716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   fr1->getRawOffset(), fr1->getDSTSavings(),
717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   NonExistingTimeOpt, DuplicatedTimeOpt);
718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        base -= localDelta;
719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool avail1 = fr1->getPreviousStart(base, fr0->getRawOffset(), fr0->getDSTSavings(), TRUE, start1);
721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
722103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (!avail0 || !avail1) {
723103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if (avail0) {
724103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            return fr0;
725103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        } else if (avail1) {
726103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            return fr1;
727103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
728103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        // Both rules take effect after the given time
729103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        return NULL;
730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
731103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
732103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return (start0 > start1) ? fr0 : fr1;
733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::findNext(UDate base, UBool inclusive, UDate& transitionTime,
737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            TimeZoneRule*& fromRule, TimeZoneRule*& toRule) const {
738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fHistoricTransitions == NULL) {
739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool isFinal = FALSE;
742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool found = FALSE;
743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Transition result;
744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Transition *tzt = (Transition*)fHistoricTransitions->elementAt(0);
745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UDate tt = tzt->time;
746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (tt > base || (inclusive && tt == base)) {
747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result = *tzt;
748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        found = TRUE;
749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t idx = fHistoricTransitions->size() - 1;
751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        tzt = (Transition*)fHistoricTransitions->elementAt(idx);
752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        tt = tzt->time;
753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (inclusive && tt == base) {
754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            result = *tzt;
755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            found = TRUE;
756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else if (tt <= base) {
757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (fFinalRules != NULL) {
758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Find a transion time with finalRules
759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                TimeZoneRule *r0 = (TimeZoneRule*)fFinalRules->elementAt(0);
760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                TimeZoneRule *r1 = (TimeZoneRule*)fFinalRules->elementAt(1);
761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UDate start0, start1;
762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UBool avail0 = r0->getNextStart(base, r1->getRawOffset(), r1->getDSTSavings(), inclusive, start0);
763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UBool avail1 = r1->getNextStart(base, r0->getRawOffset(), r0->getDSTSavings(), inclusive, start1);
764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                //  avail0/avail1 should be always TRUE
765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (!avail0 && !avail1) {
766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return FALSE;
767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (!avail1 || start0 < start1) {
769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    result.time = start0;
770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    result.from = r1;
771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    result.to = r0;
772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else {
773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    result.time = start1;
774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    result.from = r0;
775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    result.to = r1;
776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                isFinal = TRUE;
778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                found = TRUE;
779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Find a transition within the historic transitions
782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            idx--;
783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            Transition *prev = tzt;
784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while (idx > 0) {
785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                tzt = (Transition*)fHistoricTransitions->elementAt(idx);
786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                tt = tzt->time;
787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (tt < base || (!inclusive && tt == base)) {
788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                idx--;
791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                prev = tzt;
792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            result.time = prev->time;
794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            result.from = prev->from;
795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            result.to = prev->to;
796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            found = TRUE;
797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (found) {
800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // For now, this implementation ignore transitions with only zone name changes.
801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (result.from->getRawOffset() == result.to->getRawOffset()
802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            && result.from->getDSTSavings() == result.to->getDSTSavings()) {
803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (isFinal) {
804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return FALSE;
805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // No offset changes.  Try next one if not final
807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return findNext(result.time, FALSE /* always exclusive */,
808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    transitionTime, fromRule, toRule);
809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        transitionTime = result.time;
812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fromRule = result.from;
813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        toRule = result.to;
814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::findPrev(UDate base, UBool inclusive, UDate& transitionTime,
821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            TimeZoneRule*& fromRule, TimeZoneRule*& toRule) const {
822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fHistoricTransitions == NULL) {
823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool found = FALSE;
826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Transition result;
827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Transition *tzt = (Transition*)fHistoricTransitions->elementAt(0);
828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UDate tt = tzt->time;
829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (inclusive && tt == base) {
830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result = *tzt;
831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        found = TRUE;
832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if (tt < base) {
833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t idx = fHistoricTransitions->size() - 1;
834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        tzt = (Transition*)fHistoricTransitions->elementAt(idx);
835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        tt = tzt->time;
836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (inclusive && tt == base) {
837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            result = *tzt;
838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            found = TRUE;
839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else if (tt < base) {
840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (fFinalRules != NULL) {
841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Find a transion time with finalRules
842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                TimeZoneRule *r0 = (TimeZoneRule*)fFinalRules->elementAt(0);
843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                TimeZoneRule *r1 = (TimeZoneRule*)fFinalRules->elementAt(1);
844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UDate start0, start1;
845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UBool avail0 = r0->getPreviousStart(base, r1->getRawOffset(), r1->getDSTSavings(), inclusive, start0);
846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UBool avail1 = r1->getPreviousStart(base, r0->getRawOffset(), r0->getDSTSavings(), inclusive, start1);
847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                //  avail0/avail1 should be always TRUE
848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (!avail0 && !avail1) {
849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return FALSE;
850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (!avail1 || start0 > start1) {
852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    result.time = start0;
853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    result.from = r1;
854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    result.to = r0;
855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else {
856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    result.time = start1;
857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    result.from = r0;
858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    result.to = r1;
859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                result = *tzt;
862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            found = TRUE;
864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Find a transition within the historic transitions
866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            idx--;
867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while (idx >= 0) {
868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                tzt = (Transition*)fHistoricTransitions->elementAt(idx);
869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                tt = tzt->time;
870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (tt < base || (inclusive && tt == base)) {
871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                idx--;
874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            result = *tzt;
876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            found = TRUE;
877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (found) {
880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // For now, this implementation ignore transitions with only zone name changes.
881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (result.from->getRawOffset() == result.to->getRawOffset()
882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            && result.from->getDSTSavings() == result.to->getDSTSavings()) {
883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // No offset changes.  Try next one if not final
884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return findPrev(result.time, FALSE /* always exclusive */,
885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                transitionTime, fromRule, toRule);
886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        transitionTime = result.time;
888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fromRule = result.from;
889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        toRule = result.to;
890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUDate
896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::getTransitionTime(Transition* transition, UBool local,
897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt) const {
898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UDate time = transition->time;
899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (local) {
900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        time += getLocalDelta(transition->from->getRawOffset(), transition->from->getDSTSavings(),
901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                              transition->to->getRawOffset(), transition->to->getDSTSavings(),
902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                              NonExistingTimeOpt, DuplicatedTimeOpt);
903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return time;
905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::getLocalDelta(int32_t rawBefore, int32_t dstBefore, int32_t rawAfter, int32_t dstAfter,
909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt) const {
910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t delta = 0;
911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t offsetBefore = rawBefore + dstBefore;
913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t offsetAfter = rawAfter + dstAfter;
914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool dstToStd = (dstBefore != 0) && (dstAfter == 0);
916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool stdToDst = (dstBefore == 0) && (dstAfter != 0);
917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (offsetAfter - offsetBefore >= 0) {
919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Positive transition, which makes a non-existing local time range
920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (((NonExistingTimeOpt & kStdDstMask) == kStandard && dstToStd)
921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                || ((NonExistingTimeOpt & kStdDstMask) == kDaylight && stdToDst)) {
922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delta = offsetBefore;
923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else if (((NonExistingTimeOpt & kStdDstMask) == kStandard && stdToDst)
924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                || ((NonExistingTimeOpt & kStdDstMask) == kDaylight && dstToStd)) {
925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delta = offsetAfter;
926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else if ((NonExistingTimeOpt & kFormerLatterMask) == kLatter) {
927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delta = offsetBefore;
928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Interprets the time with rule before the transition,
930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // default for non-existing time range
931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delta = offsetAfter;
932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Negative transition, which makes a duplicated local time range
935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (((DuplicatedTimeOpt & kStdDstMask) == kStandard && dstToStd)
936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                || ((DuplicatedTimeOpt & kStdDstMask) == kDaylight && stdToDst)) {
937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delta = offsetAfter;
938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else if (((DuplicatedTimeOpt & kStdDstMask) == kStandard && stdToDst)
939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                || ((DuplicatedTimeOpt & kStdDstMask) == kDaylight && dstToStd)) {
940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delta = offsetBefore;
941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else if ((DuplicatedTimeOpt & kFormerLatterMask) == kFormer) {
942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delta = offsetBefore;
943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Interprets the time with rule after the transition,
945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // default for duplicated local time range
946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delta = offsetAfter;
947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return delta;
950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_END
953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */
955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//eof
957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
958