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