1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/i18n/tzrule.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,627 @@ 1.4 +/* 1.5 +******************************************************************************* 1.6 +* Copyright (C) 2007-2012, International Business Machines Corporation and 1.7 +* others. All Rights Reserved. 1.8 +******************************************************************************* 1.9 +*/ 1.10 + 1.11 +#include "utypeinfo.h" // for 'typeid' to work 1.12 + 1.13 +#include "unicode/utypes.h" 1.14 + 1.15 +#if !UCONFIG_NO_FORMATTING 1.16 + 1.17 +#include "unicode/tzrule.h" 1.18 +#include "unicode/ucal.h" 1.19 +#include "gregoimp.h" 1.20 +#include "cmemory.h" 1.21 +#include "uarrsort.h" 1.22 + 1.23 +U_CDECL_BEGIN 1.24 +// UComparator function for sorting start times 1.25 +static int32_t U_CALLCONV 1.26 +compareDates(const void * /*context*/, const void *left, const void *right) { 1.27 + UDate l = *((UDate*)left); 1.28 + UDate r = *((UDate*)right); 1.29 + int32_t res = l < r ? -1 : (l == r ? 0 : 1); 1.30 + return res; 1.31 +} 1.32 +U_CDECL_END 1.33 + 1.34 +U_NAMESPACE_BEGIN 1.35 + 1.36 +TimeZoneRule::TimeZoneRule(const UnicodeString& name, int32_t rawOffset, int32_t dstSavings) 1.37 +: UObject(), fName(name), fRawOffset(rawOffset), fDSTSavings(dstSavings) { 1.38 +} 1.39 + 1.40 +TimeZoneRule::TimeZoneRule(const TimeZoneRule& source) 1.41 +: UObject(source), fName(source.fName), fRawOffset(source.fRawOffset), fDSTSavings(source.fDSTSavings) { 1.42 +} 1.43 + 1.44 +TimeZoneRule::~TimeZoneRule() { 1.45 +} 1.46 + 1.47 +TimeZoneRule& 1.48 +TimeZoneRule::operator=(const TimeZoneRule& right) { 1.49 + if (this != &right) { 1.50 + fName = right.fName; 1.51 + fRawOffset = right.fRawOffset; 1.52 + fDSTSavings = right.fDSTSavings; 1.53 + } 1.54 + return *this; 1.55 +} 1.56 + 1.57 +UBool 1.58 +TimeZoneRule::operator==(const TimeZoneRule& that) const { 1.59 + return ((this == &that) || 1.60 + (typeid(*this) == typeid(that) && 1.61 + fName == that.fName && 1.62 + fRawOffset == that.fRawOffset && 1.63 + fDSTSavings == that.fDSTSavings)); 1.64 +} 1.65 + 1.66 +UBool 1.67 +TimeZoneRule::operator!=(const TimeZoneRule& that) const { 1.68 + return !operator==(that); 1.69 +} 1.70 + 1.71 +UnicodeString& 1.72 +TimeZoneRule::getName(UnicodeString& name) const { 1.73 + name = fName; 1.74 + return name; 1.75 +} 1.76 + 1.77 +int32_t 1.78 +TimeZoneRule::getRawOffset(void) const { 1.79 + return fRawOffset; 1.80 +} 1.81 + 1.82 +int32_t 1.83 +TimeZoneRule::getDSTSavings(void) const { 1.84 + return fDSTSavings; 1.85 +} 1.86 + 1.87 +UBool 1.88 +TimeZoneRule::isEquivalentTo(const TimeZoneRule& other) const { 1.89 + return ((this == &other) || 1.90 + (typeid(*this) == typeid(other) && 1.91 + fRawOffset == other.fRawOffset && 1.92 + fDSTSavings == other.fDSTSavings)); 1.93 +} 1.94 + 1.95 + 1.96 +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(InitialTimeZoneRule) 1.97 + 1.98 +InitialTimeZoneRule::InitialTimeZoneRule(const UnicodeString& name, 1.99 + int32_t rawOffset, 1.100 + int32_t dstSavings) 1.101 +: TimeZoneRule(name, rawOffset, dstSavings) { 1.102 +} 1.103 + 1.104 +InitialTimeZoneRule::InitialTimeZoneRule(const InitialTimeZoneRule& source) 1.105 +: TimeZoneRule(source) { 1.106 +} 1.107 + 1.108 +InitialTimeZoneRule::~InitialTimeZoneRule() { 1.109 +} 1.110 + 1.111 +InitialTimeZoneRule* 1.112 +InitialTimeZoneRule::clone(void) const { 1.113 + return new InitialTimeZoneRule(*this); 1.114 +} 1.115 + 1.116 +InitialTimeZoneRule& 1.117 +InitialTimeZoneRule::operator=(const InitialTimeZoneRule& right) { 1.118 + if (this != &right) { 1.119 + TimeZoneRule::operator=(right); 1.120 + } 1.121 + return *this; 1.122 +} 1.123 + 1.124 +UBool 1.125 +InitialTimeZoneRule::operator==(const TimeZoneRule& that) const { 1.126 + return ((this == &that) || 1.127 + (typeid(*this) == typeid(that) && 1.128 + TimeZoneRule::operator==(that))); 1.129 +} 1.130 + 1.131 +UBool 1.132 +InitialTimeZoneRule::operator!=(const TimeZoneRule& that) const { 1.133 + return !operator==(that); 1.134 +} 1.135 + 1.136 +UBool 1.137 +InitialTimeZoneRule::isEquivalentTo(const TimeZoneRule& other) const { 1.138 + if (this == &other) { 1.139 + return TRUE; 1.140 + } 1.141 + if (typeid(*this) != typeid(other) || TimeZoneRule::isEquivalentTo(other) == FALSE) { 1.142 + return FALSE; 1.143 + } 1.144 + return TRUE; 1.145 +} 1.146 + 1.147 +UBool 1.148 +InitialTimeZoneRule::getFirstStart(int32_t /*prevRawOffset*/, 1.149 + int32_t /*prevDSTSavings*/, 1.150 + UDate& /*result*/) const { 1.151 + return FALSE; 1.152 +} 1.153 + 1.154 +UBool 1.155 +InitialTimeZoneRule::getFinalStart(int32_t /*prevRawOffset*/, 1.156 + int32_t /*prevDSTSavings*/, 1.157 + UDate& /*result*/) const { 1.158 + return FALSE; 1.159 +} 1.160 + 1.161 +UBool 1.162 +InitialTimeZoneRule::getNextStart(UDate /*base*/, 1.163 + int32_t /*prevRawOffset*/, 1.164 + int32_t /*prevDSTSavings*/, 1.165 + UBool /*inclusive*/, 1.166 + UDate& /*result*/) const { 1.167 + return FALSE; 1.168 +} 1.169 + 1.170 +UBool 1.171 +InitialTimeZoneRule::getPreviousStart(UDate /*base*/, 1.172 + int32_t /*prevRawOffset*/, 1.173 + int32_t /*prevDSTSavings*/, 1.174 + UBool /*inclusive*/, 1.175 + UDate& /*result*/) const { 1.176 + return FALSE; 1.177 +} 1.178 + 1.179 + 1.180 +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(AnnualTimeZoneRule) 1.181 + 1.182 +const int32_t AnnualTimeZoneRule::MAX_YEAR = 0x7FFFFFFF; /* max signed int32 */ 1.183 + 1.184 +AnnualTimeZoneRule::AnnualTimeZoneRule(const UnicodeString& name, 1.185 + int32_t rawOffset, 1.186 + int32_t dstSavings, 1.187 + const DateTimeRule& dateTimeRule, 1.188 + int32_t startYear, 1.189 + int32_t endYear) 1.190 +: TimeZoneRule(name, rawOffset, dstSavings), fDateTimeRule(new DateTimeRule(dateTimeRule)), 1.191 + fStartYear(startYear), fEndYear(endYear) { 1.192 +} 1.193 + 1.194 +AnnualTimeZoneRule::AnnualTimeZoneRule(const UnicodeString& name, 1.195 + int32_t rawOffset, 1.196 + int32_t dstSavings, 1.197 + DateTimeRule* dateTimeRule, 1.198 + int32_t startYear, 1.199 + int32_t endYear) 1.200 +: TimeZoneRule(name, rawOffset, dstSavings), fDateTimeRule(dateTimeRule), 1.201 + fStartYear(startYear), fEndYear(endYear) { 1.202 +} 1.203 + 1.204 +AnnualTimeZoneRule::AnnualTimeZoneRule(const AnnualTimeZoneRule& source) 1.205 +: TimeZoneRule(source), fDateTimeRule(new DateTimeRule(*(source.fDateTimeRule))), 1.206 + fStartYear(source.fStartYear), fEndYear(source.fEndYear) { 1.207 +} 1.208 + 1.209 +AnnualTimeZoneRule::~AnnualTimeZoneRule() { 1.210 + delete fDateTimeRule; 1.211 +} 1.212 + 1.213 +AnnualTimeZoneRule* 1.214 +AnnualTimeZoneRule::clone(void) const { 1.215 + return new AnnualTimeZoneRule(*this); 1.216 +} 1.217 + 1.218 +AnnualTimeZoneRule& 1.219 +AnnualTimeZoneRule::operator=(const AnnualTimeZoneRule& right) { 1.220 + if (this != &right) { 1.221 + TimeZoneRule::operator=(right); 1.222 + delete fDateTimeRule; 1.223 + fDateTimeRule = right.fDateTimeRule->clone(); 1.224 + fStartYear = right.fStartYear; 1.225 + fEndYear = right.fEndYear; 1.226 + } 1.227 + return *this; 1.228 +} 1.229 + 1.230 +UBool 1.231 +AnnualTimeZoneRule::operator==(const TimeZoneRule& that) const { 1.232 + if (this == &that) { 1.233 + return TRUE; 1.234 + } 1.235 + if (typeid(*this) != typeid(that)) { 1.236 + return FALSE; 1.237 + } 1.238 + AnnualTimeZoneRule *atzr = (AnnualTimeZoneRule*)&that; 1.239 + return (*fDateTimeRule == *(atzr->fDateTimeRule) && 1.240 + fStartYear == atzr->fStartYear && 1.241 + fEndYear == atzr->fEndYear); 1.242 +} 1.243 + 1.244 +UBool 1.245 +AnnualTimeZoneRule::operator!=(const TimeZoneRule& that) const { 1.246 + return !operator==(that); 1.247 +} 1.248 + 1.249 +const DateTimeRule* 1.250 +AnnualTimeZoneRule::getRule() const { 1.251 + return fDateTimeRule; 1.252 +} 1.253 + 1.254 +int32_t 1.255 +AnnualTimeZoneRule::getStartYear() const { 1.256 + return fStartYear; 1.257 +} 1.258 + 1.259 +int32_t 1.260 +AnnualTimeZoneRule::getEndYear() const { 1.261 + return fEndYear; 1.262 +} 1.263 + 1.264 +UBool 1.265 +AnnualTimeZoneRule::getStartInYear(int32_t year, 1.266 + int32_t prevRawOffset, 1.267 + int32_t prevDSTSavings, 1.268 + UDate &result) const { 1.269 + if (year < fStartYear || year > fEndYear) { 1.270 + return FALSE; 1.271 + } 1.272 + double ruleDay; 1.273 + DateTimeRule::DateRuleType type = fDateTimeRule->getDateRuleType(); 1.274 + if (type == DateTimeRule::DOM) { 1.275 + ruleDay = Grego::fieldsToDay(year, fDateTimeRule->getRuleMonth(), fDateTimeRule->getRuleDayOfMonth()); 1.276 + } else { 1.277 + UBool after = TRUE; 1.278 + if (type == DateTimeRule::DOW) { 1.279 + // Normalize DOW rule into DOW_GEQ_DOM or DOW_LEQ_DOM 1.280 + int32_t weeks = fDateTimeRule->getRuleWeekInMonth(); 1.281 + if (weeks > 0) { 1.282 + ruleDay = Grego::fieldsToDay(year, fDateTimeRule->getRuleMonth(), 1); 1.283 + ruleDay += 7 * (weeks - 1); 1.284 + } else { 1.285 + after = FALSE; 1.286 + ruleDay = Grego::fieldsToDay(year, fDateTimeRule->getRuleMonth(), 1.287 + Grego::monthLength(year, fDateTimeRule->getRuleMonth())); 1.288 + ruleDay += 7 * (weeks + 1); 1.289 + } 1.290 + } else { 1.291 + int32_t month = fDateTimeRule->getRuleMonth(); 1.292 + int32_t dom = fDateTimeRule->getRuleDayOfMonth(); 1.293 + if (type == DateTimeRule::DOW_LEQ_DOM) { 1.294 + after = FALSE; 1.295 + // Handle Feb <=29 1.296 + if (month == UCAL_FEBRUARY && dom == 29 && !Grego::isLeapYear(year)) { 1.297 + dom--; 1.298 + } 1.299 + } 1.300 + ruleDay = Grego::fieldsToDay(year, month, dom); 1.301 + } 1.302 + int32_t dow = Grego::dayOfWeek(ruleDay); 1.303 + int32_t delta = fDateTimeRule->getRuleDayOfWeek() - dow; 1.304 + if (after) { 1.305 + delta = delta < 0 ? delta + 7 : delta; 1.306 + } else { 1.307 + delta = delta > 0 ? delta - 7 : delta; 1.308 + } 1.309 + ruleDay += delta; 1.310 + } 1.311 + 1.312 + result = ruleDay*U_MILLIS_PER_DAY + fDateTimeRule->getRuleMillisInDay(); 1.313 + if (fDateTimeRule->getTimeRuleType() != DateTimeRule::UTC_TIME) { 1.314 + result -= prevRawOffset; 1.315 + } 1.316 + if (fDateTimeRule->getTimeRuleType() == DateTimeRule::WALL_TIME) { 1.317 + result -= prevDSTSavings; 1.318 + } 1.319 + return TRUE; 1.320 +} 1.321 + 1.322 +UBool 1.323 +AnnualTimeZoneRule::isEquivalentTo(const TimeZoneRule& other) const { 1.324 + if (this == &other) { 1.325 + return TRUE; 1.326 + } 1.327 + if (typeid(*this) != typeid(other) || TimeZoneRule::isEquivalentTo(other) == FALSE) { 1.328 + return FALSE; 1.329 + } 1.330 + AnnualTimeZoneRule* that = (AnnualTimeZoneRule*)&other; 1.331 + return (*fDateTimeRule == *(that->fDateTimeRule) && 1.332 + fStartYear == that->fStartYear && 1.333 + fEndYear == that->fEndYear); 1.334 +} 1.335 + 1.336 +UBool 1.337 +AnnualTimeZoneRule::getFirstStart(int32_t prevRawOffset, 1.338 + int32_t prevDSTSavings, 1.339 + UDate& result) const { 1.340 + return getStartInYear(fStartYear, prevRawOffset, prevDSTSavings, result); 1.341 +} 1.342 + 1.343 +UBool 1.344 +AnnualTimeZoneRule::getFinalStart(int32_t prevRawOffset, 1.345 + int32_t prevDSTSavings, 1.346 + UDate& result) const { 1.347 + if (fEndYear == MAX_YEAR) { 1.348 + return FALSE; 1.349 + } 1.350 + return getStartInYear(fEndYear, prevRawOffset, prevDSTSavings, result); 1.351 +} 1.352 + 1.353 +UBool 1.354 +AnnualTimeZoneRule::getNextStart(UDate base, 1.355 + int32_t prevRawOffset, 1.356 + int32_t prevDSTSavings, 1.357 + UBool inclusive, 1.358 + UDate& result) const { 1.359 + int32_t year, month, dom, dow, doy, mid; 1.360 + Grego::timeToFields(base, year, month, dom, dow, doy, mid); 1.361 + if (year < fStartYear) { 1.362 + return getFirstStart(prevRawOffset, prevDSTSavings, result); 1.363 + } 1.364 + UDate tmp; 1.365 + if (getStartInYear(year, prevRawOffset, prevDSTSavings, tmp)) { 1.366 + if (tmp < base || (!inclusive && (tmp == base))) { 1.367 + // Return the next one 1.368 + return getStartInYear(year + 1, prevRawOffset, prevDSTSavings, result); 1.369 + } else { 1.370 + result = tmp; 1.371 + return TRUE; 1.372 + } 1.373 + } 1.374 + return FALSE; 1.375 +} 1.376 + 1.377 +UBool 1.378 +AnnualTimeZoneRule::getPreviousStart(UDate base, 1.379 + int32_t prevRawOffset, 1.380 + int32_t prevDSTSavings, 1.381 + UBool inclusive, 1.382 + UDate& result) const { 1.383 + int32_t year, month, dom, dow, doy, mid; 1.384 + Grego::timeToFields(base, year, month, dom, dow, doy, mid); 1.385 + if (year > fEndYear) { 1.386 + return getFinalStart(prevRawOffset, prevDSTSavings, result); 1.387 + } 1.388 + UDate tmp; 1.389 + if (getStartInYear(year, prevRawOffset, prevDSTSavings, tmp)) { 1.390 + if (tmp > base || (!inclusive && (tmp == base))) { 1.391 + // Return the previous one 1.392 + return getStartInYear(year - 1, prevRawOffset, prevDSTSavings, result); 1.393 + } else { 1.394 + result = tmp; 1.395 + return TRUE; 1.396 + } 1.397 + } 1.398 + return FALSE; 1.399 +} 1.400 + 1.401 +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(TimeArrayTimeZoneRule) 1.402 + 1.403 +TimeArrayTimeZoneRule::TimeArrayTimeZoneRule(const UnicodeString& name, 1.404 + int32_t rawOffset, 1.405 + int32_t dstSavings, 1.406 + const UDate* startTimes, 1.407 + int32_t numStartTimes, 1.408 + DateTimeRule::TimeRuleType timeRuleType) 1.409 +: TimeZoneRule(name, rawOffset, dstSavings), fTimeRuleType(timeRuleType), 1.410 + fStartTimes(NULL) { 1.411 + UErrorCode status = U_ZERO_ERROR; 1.412 + initStartTimes(startTimes, numStartTimes, status); 1.413 + //TODO - status? 1.414 +} 1.415 + 1.416 + 1.417 +TimeArrayTimeZoneRule::TimeArrayTimeZoneRule(const TimeArrayTimeZoneRule& source) 1.418 +: TimeZoneRule(source), fTimeRuleType(source.fTimeRuleType), fStartTimes(NULL) { 1.419 + UErrorCode status = U_ZERO_ERROR; 1.420 + initStartTimes(source.fStartTimes, source.fNumStartTimes, status); 1.421 + //TODO - status? 1.422 +} 1.423 + 1.424 + 1.425 +TimeArrayTimeZoneRule::~TimeArrayTimeZoneRule() { 1.426 + if (fStartTimes != NULL && fStartTimes != fLocalStartTimes) { 1.427 + uprv_free(fStartTimes); 1.428 + } 1.429 +} 1.430 + 1.431 +TimeArrayTimeZoneRule* 1.432 +TimeArrayTimeZoneRule::clone(void) const { 1.433 + return new TimeArrayTimeZoneRule(*this); 1.434 +} 1.435 + 1.436 + 1.437 +TimeArrayTimeZoneRule& 1.438 +TimeArrayTimeZoneRule::operator=(const TimeArrayTimeZoneRule& right) { 1.439 + if (this != &right) { 1.440 + TimeZoneRule::operator=(right); 1.441 + UErrorCode status = U_ZERO_ERROR; 1.442 + initStartTimes(right.fStartTimes, right.fNumStartTimes, status); 1.443 + //TODO - status? 1.444 + fTimeRuleType = right.fTimeRuleType; 1.445 + } 1.446 + return *this; 1.447 +} 1.448 + 1.449 +UBool 1.450 +TimeArrayTimeZoneRule::operator==(const TimeZoneRule& that) const { 1.451 + if (this == &that) { 1.452 + return TRUE; 1.453 + } 1.454 + if (typeid(*this) != typeid(that) || TimeZoneRule::operator==(that) == FALSE) { 1.455 + return FALSE; 1.456 + } 1.457 + TimeArrayTimeZoneRule *tatzr = (TimeArrayTimeZoneRule*)&that; 1.458 + if (fTimeRuleType != tatzr->fTimeRuleType || 1.459 + fNumStartTimes != tatzr->fNumStartTimes) { 1.460 + return FALSE; 1.461 + } 1.462 + // Compare start times 1.463 + UBool res = TRUE; 1.464 + for (int32_t i = 0; i < fNumStartTimes; i++) { 1.465 + if (fStartTimes[i] != tatzr->fStartTimes[i]) { 1.466 + res = FALSE; 1.467 + break; 1.468 + } 1.469 + } 1.470 + return res; 1.471 +} 1.472 + 1.473 +UBool 1.474 +TimeArrayTimeZoneRule::operator!=(const TimeZoneRule& that) const { 1.475 + return !operator==(that); 1.476 +} 1.477 + 1.478 +DateTimeRule::TimeRuleType 1.479 +TimeArrayTimeZoneRule::getTimeType(void) const { 1.480 + return fTimeRuleType; 1.481 +} 1.482 + 1.483 +UBool 1.484 +TimeArrayTimeZoneRule::getStartTimeAt(int32_t index, UDate& result) const { 1.485 + if (index >= fNumStartTimes || index < 0) { 1.486 + return FALSE; 1.487 + } 1.488 + result = fStartTimes[index]; 1.489 + return TRUE; 1.490 +} 1.491 + 1.492 +int32_t 1.493 +TimeArrayTimeZoneRule::countStartTimes(void) const { 1.494 + return fNumStartTimes; 1.495 +} 1.496 + 1.497 +UBool 1.498 +TimeArrayTimeZoneRule::isEquivalentTo(const TimeZoneRule& other) const { 1.499 + if (this == &other) { 1.500 + return TRUE; 1.501 + } 1.502 + if (typeid(*this) != typeid(other) || TimeZoneRule::isEquivalentTo(other) == FALSE) { 1.503 + return FALSE; 1.504 + } 1.505 + TimeArrayTimeZoneRule* that = (TimeArrayTimeZoneRule*)&other; 1.506 + if (fTimeRuleType != that->fTimeRuleType || 1.507 + fNumStartTimes != that->fNumStartTimes) { 1.508 + return FALSE; 1.509 + } 1.510 + // Compare start times 1.511 + UBool res = TRUE; 1.512 + for (int32_t i = 0; i < fNumStartTimes; i++) { 1.513 + if (fStartTimes[i] != that->fStartTimes[i]) { 1.514 + res = FALSE; 1.515 + break; 1.516 + } 1.517 + } 1.518 + return res; 1.519 +} 1.520 + 1.521 +UBool 1.522 +TimeArrayTimeZoneRule::getFirstStart(int32_t prevRawOffset, 1.523 + int32_t prevDSTSavings, 1.524 + UDate& result) const { 1.525 + if (fNumStartTimes <= 0 || fStartTimes == NULL) { 1.526 + return FALSE; 1.527 + } 1.528 + result = getUTC(fStartTimes[0], prevRawOffset, prevDSTSavings); 1.529 + return TRUE; 1.530 +} 1.531 + 1.532 +UBool 1.533 +TimeArrayTimeZoneRule::getFinalStart(int32_t prevRawOffset, 1.534 + int32_t prevDSTSavings, 1.535 + UDate& result) const { 1.536 + if (fNumStartTimes <= 0 || fStartTimes == NULL) { 1.537 + return FALSE; 1.538 + } 1.539 + result = getUTC(fStartTimes[fNumStartTimes - 1], prevRawOffset, prevDSTSavings); 1.540 + return TRUE; 1.541 +} 1.542 + 1.543 +UBool 1.544 +TimeArrayTimeZoneRule::getNextStart(UDate base, 1.545 + int32_t prevRawOffset, 1.546 + int32_t prevDSTSavings, 1.547 + UBool inclusive, 1.548 + UDate& result) const { 1.549 + int32_t i = fNumStartTimes - 1; 1.550 + for (; i >= 0; i--) { 1.551 + UDate time = getUTC(fStartTimes[i], prevRawOffset, prevDSTSavings); 1.552 + if (time < base || (!inclusive && time == base)) { 1.553 + break; 1.554 + } 1.555 + result = time; 1.556 + } 1.557 + if (i == fNumStartTimes - 1) { 1.558 + return FALSE; 1.559 + } 1.560 + return TRUE; 1.561 +} 1.562 + 1.563 +UBool 1.564 +TimeArrayTimeZoneRule::getPreviousStart(UDate base, 1.565 + int32_t prevRawOffset, 1.566 + int32_t prevDSTSavings, 1.567 + UBool inclusive, 1.568 + UDate& result) const { 1.569 + int32_t i = fNumStartTimes - 1; 1.570 + for (; i >= 0; i--) { 1.571 + UDate time = getUTC(fStartTimes[i], prevRawOffset, prevDSTSavings); 1.572 + if (time < base || (inclusive && time == base)) { 1.573 + result = time; 1.574 + return TRUE; 1.575 + } 1.576 + } 1.577 + return FALSE; 1.578 +} 1.579 + 1.580 + 1.581 +// ---- private methods ------ 1.582 + 1.583 +UBool 1.584 +TimeArrayTimeZoneRule::initStartTimes(const UDate source[], int32_t size, UErrorCode& status) { 1.585 + // Free old array 1.586 + if (fStartTimes != NULL && fStartTimes != fLocalStartTimes) { 1.587 + uprv_free(fStartTimes); 1.588 + } 1.589 + // Allocate new one if needed 1.590 + if (size > TIMEARRAY_STACK_BUFFER_SIZE) { 1.591 + fStartTimes = (UDate*)uprv_malloc(sizeof(UDate)*size); 1.592 + if (fStartTimes == NULL) { 1.593 + status = U_MEMORY_ALLOCATION_ERROR; 1.594 + fNumStartTimes = 0; 1.595 + return FALSE; 1.596 + } 1.597 + } else { 1.598 + fStartTimes = (UDate*)fLocalStartTimes; 1.599 + } 1.600 + uprv_memcpy(fStartTimes, source, sizeof(UDate)*size); 1.601 + fNumStartTimes = size; 1.602 + // Sort dates 1.603 + uprv_sortArray(fStartTimes, fNumStartTimes, (int32_t)sizeof(UDate), compareDates, NULL, TRUE, &status); 1.604 + if (U_FAILURE(status)) { 1.605 + if (fStartTimes != NULL && fStartTimes != fLocalStartTimes) { 1.606 + uprv_free(fStartTimes); 1.607 + } 1.608 + fNumStartTimes = 0; 1.609 + return FALSE; 1.610 + } 1.611 + return TRUE; 1.612 +} 1.613 + 1.614 +UDate 1.615 +TimeArrayTimeZoneRule::getUTC(UDate time, int32_t raw, int32_t dst) const { 1.616 + if (fTimeRuleType != DateTimeRule::UTC_TIME) { 1.617 + time -= raw; 1.618 + } 1.619 + if (fTimeRuleType == DateTimeRule::WALL_TIME) { 1.620 + time -= dst; 1.621 + } 1.622 + return time; 1.623 +} 1.624 + 1.625 +U_NAMESPACE_END 1.626 + 1.627 +#endif /* #if !UCONFIG_NO_FORMATTING */ 1.628 + 1.629 +//eof 1.630 +