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 } 1548393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UBool updated; 1558393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UMTX_CHECK(&gLock, fUpToDate, updated); 1568393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (!updated) { 1578393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius umtx_lock(&gLock); 1588393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (!fUpToDate) { 1598393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius RuleBasedTimeZone *ncThis = const_cast<RuleBasedTimeZone*>(this); 1608393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius ncThis->complete(status); 1618393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 1628393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius umtx_unlock(&gLock); 1638393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 1648393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius} 1658393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::complete(UErrorCode& status) { 168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fUpToDate) { 172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Make sure either no final rules or a pair of AnnualTimeZoneRules 175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // are available. 176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fFinalRules != NULL && fFinalRules->size() != 2) { 177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_STATE_ERROR; 178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool *done = NULL; 182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Create a TimezoneTransition and add to the list 183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fHistoricRules != NULL || fFinalRules != NULL) { 184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru TimeZoneRule *curRule = fInitialRule; 185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate lastTransitionTime = MIN_MILLIS; 186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Build the transition array which represents historical time zone 188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // transitions. 189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fHistoricRules != NULL && fHistoricRules->size() > 0) { 190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t i; 191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t historicCount = fHistoricRules->size(); 192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru done = (UBool*)uprv_malloc(sizeof(UBool) * historicCount); 193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (done == NULL) { 194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_MEMORY_ALLOCATION_ERROR; 195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto cleanup; 196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (i = 0; i < historicCount; i++) { 198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru done[i] = FALSE; 199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (TRUE) { 201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t curStdOffset = curRule->getRawOffset(); 202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t curDstSavings = curRule->getDSTSavings(); 203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate nextTransitionTime = MAX_MILLIS; 204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru TimeZoneRule *nextRule = NULL; 205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru TimeZoneRule *r = NULL; 206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool avail; 207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate tt; 208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UnicodeString curName, name; 209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru curRule->getName(curName); 210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (i = 0; i < historicCount; i++) { 212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (done[i]) { 213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru continue; 214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru r = (TimeZoneRule*)fHistoricRules->elementAt(i); 216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru avail = r->getNextStart(lastTransitionTime, curStdOffset, curDstSavings, false, tt); 217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!avail) { 218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // No more transitions from this rule - skip this rule next time 219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru done[i] = TRUE; 220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru r->getName(name); 222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (*r == *curRule || 223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru (name == curName && r->getRawOffset() == curRule->getRawOffset() 224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru && r->getDSTSavings() == curRule->getDSTSavings())) { 225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru continue; 226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (tt < nextTransitionTime) { 228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru nextTransitionTime = tt; 229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru nextRule = r; 230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (nextRule == NULL) { 235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Check if all historic rules are done 236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool bDoneAll = TRUE; 237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (int32_t j = 0; j < historicCount; j++) { 238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!done[j]) { 239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bDoneAll = FALSE; 240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (bDoneAll) { 244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fFinalRules != NULL) { 249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Check if one of final rules has earlier transition date 250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (i = 0; i < 2 /* fFinalRules->size() */; i++) { 251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru TimeZoneRule *fr = (TimeZoneRule*)fFinalRules->elementAt(i); 252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (*fr == *curRule) { 253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru continue; 254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru r = (TimeZoneRule*)fFinalRules->elementAt(i); 256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru avail = r->getNextStart(lastTransitionTime, curStdOffset, curDstSavings, false, tt); 257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (avail) { 258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (tt < nextTransitionTime) { 259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru nextTransitionTime = tt; 260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru nextRule = r; 261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (nextRule == NULL) { 267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Nothing more 268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fHistoricTransitions == NULL) { 272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fHistoricTransitions = new UVector(status); 273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto cleanup; 275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Transition *trst = (Transition*)uprv_malloc(sizeof(Transition)); 278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (trst == NULL) { 279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_MEMORY_ALLOCATION_ERROR; 280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto cleanup; 281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru trst->time = nextTransitionTime; 283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru trst->from = curRule; 284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru trst->to = nextRule; 285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fHistoricTransitions->addElement(trst, status); 286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto cleanup; 288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru lastTransitionTime = nextTransitionTime; 290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru curRule = nextRule; 291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fFinalRules != NULL) { 294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fHistoricTransitions == NULL) { 295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fHistoricTransitions = new UVector(status); 296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto cleanup; 298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Append the first transition for each 301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru TimeZoneRule *rule0 = (TimeZoneRule*)fFinalRules->elementAt(0); 302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru TimeZoneRule *rule1 = (TimeZoneRule*)fFinalRules->elementAt(1); 303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate tt0, tt1; 304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool avail0 = rule0->getNextStart(lastTransitionTime, curRule->getRawOffset(), curRule->getDSTSavings(), false, tt0); 305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool avail1 = rule1->getNextStart(lastTransitionTime, curRule->getRawOffset(), curRule->getDSTSavings(), false, tt1); 306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!avail0 || !avail1) { 307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Should not happen, because both rules are permanent 308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_STATE_ERROR; 309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto cleanup; 310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Transition *final0 = (Transition*)uprv_malloc(sizeof(Transition)); 312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (final0 == NULL) { 313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_MEMORY_ALLOCATION_ERROR; 314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto cleanup; 315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Transition *final1 = (Transition*)uprv_malloc(sizeof(Transition)); 317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (final1 == NULL) { 31885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho uprv_free(final0); 319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_MEMORY_ALLOCATION_ERROR; 320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto cleanup; 321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (tt0 < tt1) { 323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru final0->time = tt0; 324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru final0->from = curRule; 325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru final0->to = rule0; 326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru rule1->getNextStart(tt0, rule0->getRawOffset(), rule0->getDSTSavings(), false, final1->time); 327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru final1->from = rule0; 328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru final1->to = rule1; 329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru final0->time = tt1; 331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru final0->from = curRule; 332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru final0->to = rule1; 333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru rule0->getNextStart(tt1, rule1->getRawOffset(), rule1->getDSTSavings(), false, final1->time); 334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru final1->from = rule1; 335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru final1->to = rule0; 336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fHistoricTransitions->addElement(final0, status); 338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto cleanup; 340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fHistoricTransitions->addElement(final1, status); 342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto cleanup; 344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fUpToDate = TRUE; 348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (done != NULL) { 349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(done); 350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querucleanup: 354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru deleteTransitions(); 355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (done != NULL) { 356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(done); 357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fUpToDate = FALSE; 359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone* 362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::clone(void) const { 363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return new RuleBasedTimeZone(*this); 364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t 367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::getOffset(uint8_t era, int32_t year, int32_t month, int32_t day, 368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uint8_t dayOfWeek, int32_t millis, UErrorCode& status) const { 369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (month < UCAL_JANUARY || month > UCAL_DECEMBER) { 373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_ILLEGAL_ARGUMENT_ERROR; 374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return getOffset(era, year, month, day, dayOfWeek, millis, 377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Grego::monthLength(year, month), status); 378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t 382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::getOffset(uint8_t era, int32_t year, int32_t month, int32_t day, 383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uint8_t /*dayOfWeek*/, int32_t millis, 384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t /*monthLength*/, UErrorCode& status) const { 385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // dayOfWeek and monthLength are unused 386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (era == GregorianCalendar::BC) { 390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Convert to extended year 391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru year = 1 - year; 392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t rawOffset, dstOffset; 394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate time = (UDate)Grego::fieldsToDay(year, month, day) * U_MILLIS_PER_DAY + millis; 395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru getOffsetInternal(time, TRUE, kDaylight, kStandard, rawOffset, dstOffset, status); 396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return (rawOffset + dstOffset); 400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::getOffset(UDate date, UBool local, int32_t& rawOffset, 404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t& dstOffset, UErrorCode& status) const { 405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru getOffsetInternal(date, local, kFormer, kLatter, rawOffset, dstOffset, status); 406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt, 4108393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) const { 411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru getOffsetInternal(date, TRUE, nonExistingTimeOpt, duplicatedTimeOpt, rawOffset, dstOffset, status); 412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* 416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * The internal getOffset implementation 417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::getOffsetInternal(UDate date, UBool local, 420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt, 421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t& rawOffset, int32_t& dstOffset, 422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode& status) const { 423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru rawOffset = 0; 424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dstOffset = 0; 425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!fUpToDate) { 430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Transitions are not yet resolved. We cannot do it here 431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // because this method is const. Thus, do nothing and return 432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // error status. 433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_STATE_ERROR; 434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const TimeZoneRule *rule = NULL; 437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fHistoricTransitions == NULL) { 438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru rule = fInitialRule; 439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate tstart = getTransitionTime((Transition*)fHistoricTransitions->elementAt(0), 441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru local, NonExistingTimeOpt, DuplicatedTimeOpt); 442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (date < tstart) { 443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru rule = fInitialRule; 444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t idx = fHistoricTransitions->size() - 1; 446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate tend = getTransitionTime((Transition*)fHistoricTransitions->elementAt(idx), 447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru local, NonExistingTimeOpt, DuplicatedTimeOpt); 448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (date > tend) { 449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fFinalRules != NULL) { 450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru rule = findRuleInFinal(date, local, NonExistingTimeOpt, DuplicatedTimeOpt); 451103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 452103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (rule == NULL) { 453103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // no final rules or the given time is before the first transition 454103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // specified by the final rules -> use the last rule 455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru rule = ((Transition*)fHistoricTransitions->elementAt(idx))->to; 456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Find a historical transition 459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (idx >= 0) { 460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (date >= getTransitionTime((Transition*)fHistoricTransitions->elementAt(idx), 461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru local, NonExistingTimeOpt, DuplicatedTimeOpt)) { 462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru idx--; 465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru rule = ((Transition*)fHistoricTransitions->elementAt(idx))->to; 467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (rule != NULL) { 471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru rawOffset = rule->getRawOffset(); 472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dstOffset = rule->getDSTSavings(); 473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::setRawOffset(int32_t /*offsetMillis*/) { 478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We don't support this operation at this moment. 479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Nothing to do! 480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t 483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::getRawOffset(void) const { 484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Note: This implementation returns standard GMT offset 485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // as of current time. 486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode status = U_ZERO_ERROR; 487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t raw, dst; 488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru getOffset(uprv_getUTCtime() * U_MILLIS_PER_SECOND, 489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru FALSE, raw, dst, status); 490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return raw; 491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool 494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::useDaylightTime(void) const { 495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Note: This implementation returns true when 496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // daylight saving time is used as of now or 497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // after the next transition. 498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode status = U_ZERO_ERROR; 499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate now = uprv_getUTCtime() * U_MILLIS_PER_SECOND; 500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t raw, dst; 501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru getOffset(now, FALSE, raw, dst, status); 502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (dst != 0) { 503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return TRUE; 504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If DST is not used now, check if DST is used after the next transition 506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate time; 507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru TimeZoneRule *from, *to; 508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool avail = findNext(now, FALSE, time, from, to); 509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (avail && to->getDSTSavings() != 0) { 510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return TRUE; 511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool 516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::inDaylightTime(UDate date, UErrorCode& status) const { 517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t raw, dst; 521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru getOffset(date, FALSE, raw, dst, status); 522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (dst != 0) { 523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return TRUE; 524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool 529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::hasSameRules(const TimeZone& other) const { 530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (this == &other) { 531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return TRUE; 532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 53327f654740f2a26ad62a5c155af9199af9e69b889claireho if (typeid(*this) != typeid(other)) { 534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const RuleBasedTimeZone& that = (const RuleBasedTimeZone&)other; 537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (*fInitialRule != *(that.fInitialRule)) { 538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (compareRules(fHistoricRules, that.fHistoricRules) 541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru && compareRules(fFinalRules, that.fFinalRules)) { 542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return TRUE; 543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool 5488393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusRuleBasedTimeZone::getNextTransition(UDate base, UBool inclusive, TimeZoneTransition& result) const { 549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode status = U_ZERO_ERROR; 5508393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius completeConst(status); 551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate transitionTime; 555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru TimeZoneRule *fromRule, *toRule; 556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool found = findNext(base, inclusive, transitionTime, fromRule, toRule); 557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (found) { 558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result.setTime(transitionTime); 559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result.setFrom((const TimeZoneRule&)*fromRule); 560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result.setTo((const TimeZoneRule&)*toRule); 561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return TRUE; 562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool 5678393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusRuleBasedTimeZone::getPreviousTransition(UDate base, UBool inclusive, TimeZoneTransition& result) const { 568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode status = U_ZERO_ERROR; 5698393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius completeConst(status); 570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate transitionTime; 574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru TimeZoneRule *fromRule, *toRule; 575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool found = findPrev(base, inclusive, transitionTime, fromRule, toRule); 576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (found) { 577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result.setTime(transitionTime); 578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result.setFrom((const TimeZoneRule&)*fromRule); 579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result.setTo((const TimeZoneRule&)*toRule); 580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return TRUE; 581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t 5868393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusRuleBasedTimeZone::countTransitionRules(UErrorCode& /*status*/) const { 587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t count = 0; 588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fHistoricRules != NULL) { 589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru count += fHistoricRules->size(); 590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fFinalRules != NULL) { 592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru count += fFinalRules->size(); 593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return count; 595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::getTimeZoneRules(const InitialTimeZoneRule*& initial, 599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const TimeZoneRule* trsrules[], 600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t& trscount, 6018393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UErrorCode& status) const { 602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Initial rule 606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru initial = fInitialRule; 607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Transition rules 609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t cnt = 0; 610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t idx; 611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fHistoricRules != NULL && cnt < trscount) { 612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t historicCount = fHistoricRules->size(); 613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru idx = 0; 614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (cnt < trscount && idx < historicCount) { 615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru trsrules[cnt++] = (const TimeZoneRule*)fHistoricRules->elementAt(idx++); 616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fFinalRules != NULL && cnt < trscount) { 619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t finalCount = fFinalRules->size(); 620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru idx = 0; 621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (cnt < trscount && idx < finalCount) { 622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru trsrules[cnt++] = (const TimeZoneRule*)fFinalRules->elementAt(idx++); 623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Set the result length 626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru trscount = cnt; 627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::deleteRules(void) { 631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete fInitialRule; 632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fInitialRule = NULL; 633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fHistoricRules != NULL) { 634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (!fHistoricRules->isEmpty()) { 635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete (TimeZoneRule*)(fHistoricRules->orphanElementAt(0)); 636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete fHistoricRules; 638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fHistoricRules = NULL; 639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fFinalRules != NULL) { 641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (!fFinalRules->isEmpty()) { 642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete (AnnualTimeZoneRule*)(fFinalRules->orphanElementAt(0)); 643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete fFinalRules; 645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fFinalRules = NULL; 646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::deleteTransitions(void) { 651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fHistoricTransitions != NULL) { 652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (!fHistoricTransitions->isEmpty()) { 653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Transition *trs = (Transition*)fHistoricTransitions->orphanElementAt(0); 654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(trs); 655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete fHistoricTransitions; 657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fHistoricTransitions = NULL; 659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUVector* 662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::copyRules(UVector* source) { 663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (source == NULL) { 664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode ec = U_ZERO_ERROR; 667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t size = source->size(); 668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UVector *rules = new UVector(size, ec); 669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(ec)) { 670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t i; 673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (i = 0; i < size; i++) { 674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru rules->addElement(((TimeZoneRule*)source->elementAt(i))->clone(), ec); 675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(ec)) { 676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(ec)) { 680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // In case of error, clean up 681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (i = 0; i < rules->size(); i++) { 682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru TimeZoneRule *rule = (TimeZoneRule*)rules->orphanElementAt(i); 683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete rule; 684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete rules; 686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return rules; 689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZoneRule* 692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::findRuleInFinal(UDate date, UBool local, 693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt) const { 694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fFinalRules == NULL) { 695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru AnnualTimeZoneRule* fr0 = (AnnualTimeZoneRule*)fFinalRules->elementAt(0); 699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru AnnualTimeZoneRule* fr1 = (AnnualTimeZoneRule*)fFinalRules->elementAt(1); 700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fr0 == NULL || fr1 == NULL) { 701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate start0, start1; 705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate base; 706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t localDelta; 707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru base = date; 709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (local) { 710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru localDelta = getLocalDelta(fr1->getRawOffset(), fr1->getDSTSavings(), 711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fr0->getRawOffset(), fr0->getDSTSavings(), 712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NonExistingTimeOpt, DuplicatedTimeOpt); 713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru base -= localDelta; 714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool avail0 = fr0->getPreviousStart(base, fr1->getRawOffset(), fr1->getDSTSavings(), TRUE, start0); 716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru base = date; 718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (local) { 719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru localDelta = getLocalDelta(fr0->getRawOffset(), fr0->getDSTSavings(), 720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fr1->getRawOffset(), fr1->getDSTSavings(), 721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NonExistingTimeOpt, DuplicatedTimeOpt); 722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru base -= localDelta; 723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool avail1 = fr1->getPreviousStart(base, fr0->getRawOffset(), fr0->getDSTSavings(), TRUE, start1); 725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 726103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (!avail0 || !avail1) { 727103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (avail0) { 728103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return fr0; 729103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else if (avail1) { 730103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return fr1; 731103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 732103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // Both rules take effect after the given time 733103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return NULL; 734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 735103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 736103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return (start0 > start1) ? fr0 : fr1; 737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool 740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::findNext(UDate base, UBool inclusive, UDate& transitionTime, 741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru TimeZoneRule*& fromRule, TimeZoneRule*& toRule) const { 742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fHistoricTransitions == NULL) { 743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool isFinal = FALSE; 746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool found = FALSE; 747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Transition result; 748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Transition *tzt = (Transition*)fHistoricTransitions->elementAt(0); 749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate tt = tzt->time; 750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (tt > base || (inclusive && tt == base)) { 751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result = *tzt; 752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru found = TRUE; 753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t idx = fHistoricTransitions->size() - 1; 755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru tzt = (Transition*)fHistoricTransitions->elementAt(idx); 756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru tt = tzt->time; 757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (inclusive && tt == base) { 758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result = *tzt; 759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru found = TRUE; 760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (tt <= base) { 761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fFinalRules != NULL) { 762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Find a transion time with finalRules 763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru TimeZoneRule *r0 = (TimeZoneRule*)fFinalRules->elementAt(0); 764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru TimeZoneRule *r1 = (TimeZoneRule*)fFinalRules->elementAt(1); 765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate start0, start1; 766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool avail0 = r0->getNextStart(base, r1->getRawOffset(), r1->getDSTSavings(), inclusive, start0); 767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool avail1 = r1->getNextStart(base, r0->getRawOffset(), r0->getDSTSavings(), inclusive, start1); 768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // avail0/avail1 should be always TRUE 769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!avail0 && !avail1) { 770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!avail1 || start0 < start1) { 773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result.time = start0; 774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result.from = r1; 775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result.to = r0; 776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result.time = start1; 778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result.from = r0; 779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result.to = r1; 780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru isFinal = TRUE; 782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru found = TRUE; 783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Find a transition within the historic transitions 786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru idx--; 787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Transition *prev = tzt; 788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (idx > 0) { 789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru tzt = (Transition*)fHistoricTransitions->elementAt(idx); 790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru tt = tzt->time; 791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (tt < base || (!inclusive && tt == base)) { 792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru idx--; 795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru prev = tzt; 796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result.time = prev->time; 798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result.from = prev->from; 799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result.to = prev->to; 800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru found = TRUE; 801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (found) { 804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // For now, this implementation ignore transitions with only zone name changes. 805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (result.from->getRawOffset() == result.to->getRawOffset() 806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru && result.from->getDSTSavings() == result.to->getDSTSavings()) { 807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (isFinal) { 808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // No offset changes. Try next one if not final 811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return findNext(result.time, FALSE /* always exclusive */, 812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru transitionTime, fromRule, toRule); 813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru transitionTime = result.time; 816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fromRule = result.from; 817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru toRule = result.to; 818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return TRUE; 819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool 824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::findPrev(UDate base, UBool inclusive, UDate& transitionTime, 825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru TimeZoneRule*& fromRule, TimeZoneRule*& toRule) const { 826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fHistoricTransitions == NULL) { 827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool found = FALSE; 830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Transition result; 831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Transition *tzt = (Transition*)fHistoricTransitions->elementAt(0); 832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate tt = tzt->time; 833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (inclusive && tt == base) { 834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result = *tzt; 835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru found = TRUE; 836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (tt < base) { 837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t idx = fHistoricTransitions->size() - 1; 838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru tzt = (Transition*)fHistoricTransitions->elementAt(idx); 839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru tt = tzt->time; 840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (inclusive && tt == base) { 841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result = *tzt; 842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru found = TRUE; 843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (tt < base) { 844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fFinalRules != NULL) { 845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Find a transion time with finalRules 846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru TimeZoneRule *r0 = (TimeZoneRule*)fFinalRules->elementAt(0); 847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru TimeZoneRule *r1 = (TimeZoneRule*)fFinalRules->elementAt(1); 848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate start0, start1; 849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool avail0 = r0->getPreviousStart(base, r1->getRawOffset(), r1->getDSTSavings(), inclusive, start0); 850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool avail1 = r1->getPreviousStart(base, r0->getRawOffset(), r0->getDSTSavings(), inclusive, start1); 851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // avail0/avail1 should be always TRUE 852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!avail0 && !avail1) { 853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!avail1 || start0 > start1) { 856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result.time = start0; 857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result.from = r1; 858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result.to = r0; 859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result.time = start1; 861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result.from = r0; 862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result.to = r1; 863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result = *tzt; 866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru found = TRUE; 868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Find a transition within the historic transitions 870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru idx--; 871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (idx >= 0) { 872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru tzt = (Transition*)fHistoricTransitions->elementAt(idx); 873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru tt = tzt->time; 874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (tt < base || (inclusive && tt == base)) { 875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru idx--; 878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result = *tzt; 880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru found = TRUE; 881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (found) { 884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // For now, this implementation ignore transitions with only zone name changes. 885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (result.from->getRawOffset() == result.to->getRawOffset() 886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru && result.from->getDSTSavings() == result.to->getDSTSavings()) { 887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // No offset changes. Try next one if not final 888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return findPrev(result.time, FALSE /* always exclusive */, 889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru transitionTime, fromRule, toRule); 890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru transitionTime = result.time; 892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fromRule = result.from; 893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru toRule = result.to; 894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return TRUE; 895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUDate 900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::getTransitionTime(Transition* transition, UBool local, 901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt) const { 902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate time = transition->time; 903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (local) { 904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru time += getLocalDelta(transition->from->getRawOffset(), transition->from->getDSTSavings(), 905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru transition->to->getRawOffset(), transition->to->getDSTSavings(), 906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NonExistingTimeOpt, DuplicatedTimeOpt); 907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return time; 909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t 912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruRuleBasedTimeZone::getLocalDelta(int32_t rawBefore, int32_t dstBefore, int32_t rawAfter, int32_t dstAfter, 913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt) const { 914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t delta = 0; 915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t offsetBefore = rawBefore + dstBefore; 917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t offsetAfter = rawAfter + dstAfter; 918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool dstToStd = (dstBefore != 0) && (dstAfter == 0); 920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool stdToDst = (dstBefore == 0) && (dstAfter != 0); 921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (offsetAfter - offsetBefore >= 0) { 923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Positive transition, which makes a non-existing local time range 924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (((NonExistingTimeOpt & kStdDstMask) == kStandard && dstToStd) 925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru || ((NonExistingTimeOpt & kStdDstMask) == kDaylight && stdToDst)) { 926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delta = offsetBefore; 927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (((NonExistingTimeOpt & kStdDstMask) == kStandard && stdToDst) 928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru || ((NonExistingTimeOpt & kStdDstMask) == kDaylight && dstToStd)) { 929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delta = offsetAfter; 930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if ((NonExistingTimeOpt & kFormerLatterMask) == kLatter) { 931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delta = offsetBefore; 932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Interprets the time with rule before the transition, 934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // default for non-existing time range 935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delta = offsetAfter; 936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Negative transition, which makes a duplicated local time range 939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (((DuplicatedTimeOpt & kStdDstMask) == kStandard && dstToStd) 940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru || ((DuplicatedTimeOpt & kStdDstMask) == kDaylight && stdToDst)) { 941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delta = offsetAfter; 942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (((DuplicatedTimeOpt & kStdDstMask) == kStandard && stdToDst) 943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru || ((DuplicatedTimeOpt & kStdDstMask) == kDaylight && dstToStd)) { 944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delta = offsetBefore; 945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if ((DuplicatedTimeOpt & kFormerLatterMask) == kFormer) { 946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delta = offsetBefore; 947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Interprets the time with rule after the transition, 949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // default for duplicated local time range 950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delta = offsetAfter; 951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return delta; 954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_END 957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */ 959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//eof 961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 962