1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/i18n/basictz.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,560 @@ 1.4 +/* 1.5 +******************************************************************************* 1.6 +* Copyright (C) 2007-2013, International Business Machines Corporation and 1.7 +* others. All Rights Reserved. 1.8 +******************************************************************************* 1.9 +*/ 1.10 + 1.11 +#include "unicode/utypes.h" 1.12 + 1.13 +#if !UCONFIG_NO_FORMATTING 1.14 + 1.15 +#include "unicode/basictz.h" 1.16 +#include "gregoimp.h" 1.17 +#include "uvector.h" 1.18 +#include "cmemory.h" 1.19 + 1.20 +U_NAMESPACE_BEGIN 1.21 + 1.22 +#define MILLIS_PER_YEAR (365*24*60*60*1000.0) 1.23 + 1.24 +BasicTimeZone::BasicTimeZone() 1.25 +: TimeZone() { 1.26 +} 1.27 + 1.28 +BasicTimeZone::BasicTimeZone(const UnicodeString &id) 1.29 +: TimeZone(id) { 1.30 +} 1.31 + 1.32 +BasicTimeZone::BasicTimeZone(const BasicTimeZone& source) 1.33 +: TimeZone(source) { 1.34 +} 1.35 + 1.36 +BasicTimeZone::~BasicTimeZone() { 1.37 +} 1.38 + 1.39 +UBool 1.40 +BasicTimeZone::hasEquivalentTransitions(const BasicTimeZone& tz, UDate start, UDate end, 1.41 + UBool ignoreDstAmount, UErrorCode& status) const { 1.42 + if (U_FAILURE(status)) { 1.43 + return FALSE; 1.44 + } 1.45 + if (hasSameRules(tz)) { 1.46 + return TRUE; 1.47 + } 1.48 + // Check the offsets at the start time 1.49 + int32_t raw1, raw2, dst1, dst2; 1.50 + getOffset(start, FALSE, raw1, dst1, status); 1.51 + if (U_FAILURE(status)) { 1.52 + return FALSE; 1.53 + } 1.54 + tz.getOffset(start, FALSE, raw2, dst2, status); 1.55 + if (U_FAILURE(status)) { 1.56 + return FALSE; 1.57 + } 1.58 + if (ignoreDstAmount) { 1.59 + if ((raw1 + dst1 != raw2 + dst2) 1.60 + || (dst1 != 0 && dst2 == 0) 1.61 + || (dst1 == 0 && dst2 != 0)) { 1.62 + return FALSE; 1.63 + } 1.64 + } else { 1.65 + if (raw1 != raw2 || dst1 != dst2) { 1.66 + return FALSE; 1.67 + } 1.68 + } 1.69 + // Check transitions in the range 1.70 + UDate time = start; 1.71 + TimeZoneTransition tr1, tr2; 1.72 + while (TRUE) { 1.73 + UBool avail1 = getNextTransition(time, FALSE, tr1); 1.74 + UBool avail2 = tz.getNextTransition(time, FALSE, tr2); 1.75 + 1.76 + if (ignoreDstAmount) { 1.77 + // Skip a transition which only differ the amount of DST savings 1.78 + while (TRUE) { 1.79 + if (avail1 1.80 + && tr1.getTime() <= end 1.81 + && (tr1.getFrom()->getRawOffset() + tr1.getFrom()->getDSTSavings() 1.82 + == tr1.getTo()->getRawOffset() + tr1.getTo()->getDSTSavings()) 1.83 + && (tr1.getFrom()->getDSTSavings() != 0 && tr1.getTo()->getDSTSavings() != 0)) { 1.84 + getNextTransition(tr1.getTime(), FALSE, tr1); 1.85 + } else { 1.86 + break; 1.87 + } 1.88 + } 1.89 + while (TRUE) { 1.90 + if (avail2 1.91 + && tr2.getTime() <= end 1.92 + && (tr2.getFrom()->getRawOffset() + tr2.getFrom()->getDSTSavings() 1.93 + == tr2.getTo()->getRawOffset() + tr2.getTo()->getDSTSavings()) 1.94 + && (tr2.getFrom()->getDSTSavings() != 0 && tr2.getTo()->getDSTSavings() != 0)) { 1.95 + tz.getNextTransition(tr2.getTime(), FALSE, tr2); 1.96 + } else { 1.97 + break; 1.98 + } 1.99 + } 1.100 + } 1.101 + 1.102 + UBool inRange1 = (avail1 && tr1.getTime() <= end); 1.103 + UBool inRange2 = (avail2 && tr2.getTime() <= end); 1.104 + if (!inRange1 && !inRange2) { 1.105 + // No more transition in the range 1.106 + break; 1.107 + } 1.108 + if (!inRange1 || !inRange2) { 1.109 + return FALSE; 1.110 + } 1.111 + if (tr1.getTime() != tr2.getTime()) { 1.112 + return FALSE; 1.113 + } 1.114 + if (ignoreDstAmount) { 1.115 + if (tr1.getTo()->getRawOffset() + tr1.getTo()->getDSTSavings() 1.116 + != tr2.getTo()->getRawOffset() + tr2.getTo()->getDSTSavings() 1.117 + || (tr1.getTo()->getDSTSavings() != 0 && tr2.getTo()->getDSTSavings() == 0) 1.118 + || (tr1.getTo()->getDSTSavings() == 0 && tr2.getTo()->getDSTSavings() != 0)) { 1.119 + return FALSE; 1.120 + } 1.121 + } else { 1.122 + if (tr1.getTo()->getRawOffset() != tr2.getTo()->getRawOffset() || 1.123 + tr1.getTo()->getDSTSavings() != tr2.getTo()->getDSTSavings()) { 1.124 + return FALSE; 1.125 + } 1.126 + } 1.127 + time = tr1.getTime(); 1.128 + } 1.129 + return TRUE; 1.130 +} 1.131 + 1.132 +void 1.133 +BasicTimeZone::getSimpleRulesNear(UDate date, InitialTimeZoneRule*& initial, 1.134 + AnnualTimeZoneRule*& std, AnnualTimeZoneRule*& dst, UErrorCode& status) const { 1.135 + initial = NULL; 1.136 + std = NULL; 1.137 + dst = NULL; 1.138 + if (U_FAILURE(status)) { 1.139 + return; 1.140 + } 1.141 + int32_t initialRaw, initialDst; 1.142 + UnicodeString initialName; 1.143 + 1.144 + AnnualTimeZoneRule *ar1 = NULL; 1.145 + AnnualTimeZoneRule *ar2 = NULL; 1.146 + UnicodeString name; 1.147 + 1.148 + UBool avail; 1.149 + TimeZoneTransition tr; 1.150 + // Get the next transition 1.151 + avail = getNextTransition(date, FALSE, tr); 1.152 + if (avail) { 1.153 + tr.getFrom()->getName(initialName); 1.154 + initialRaw = tr.getFrom()->getRawOffset(); 1.155 + initialDst = tr.getFrom()->getDSTSavings(); 1.156 + 1.157 + // Check if the next transition is either DST->STD or STD->DST and 1.158 + // within roughly 1 year from the specified date 1.159 + UDate nextTransitionTime = tr.getTime(); 1.160 + if (((tr.getFrom()->getDSTSavings() == 0 && tr.getTo()->getDSTSavings() != 0) 1.161 + || (tr.getFrom()->getDSTSavings() != 0 && tr.getTo()->getDSTSavings() == 0)) 1.162 + && (date + MILLIS_PER_YEAR > nextTransitionTime)) { 1.163 + 1.164 + int32_t year, month, dom, dow, doy, mid; 1.165 + UDate d; 1.166 + 1.167 + // Get local wall time for the next transition time 1.168 + Grego::timeToFields(nextTransitionTime + initialRaw + initialDst, 1.169 + year, month, dom, dow, doy, mid); 1.170 + int32_t weekInMonth = Grego::dayOfWeekInMonth(year, month, dom); 1.171 + // Create DOW rule 1.172 + DateTimeRule *dtr = new DateTimeRule(month, weekInMonth, dow, mid, DateTimeRule::WALL_TIME); 1.173 + tr.getTo()->getName(name); 1.174 + 1.175 + // Note: SimpleTimeZone does not support raw offset change. 1.176 + // So we always use raw offset of the given time for the rule, 1.177 + // even raw offset is changed. This will result that the result 1.178 + // zone to return wrong offset after the transition. 1.179 + // When we encounter such case, we do not inspect next next 1.180 + // transition for another rule. 1.181 + ar1 = new AnnualTimeZoneRule(name, initialRaw, tr.getTo()->getDSTSavings(), 1.182 + dtr, year, AnnualTimeZoneRule::MAX_YEAR); 1.183 + 1.184 + if (tr.getTo()->getRawOffset() == initialRaw) { 1.185 + // Get the next next transition 1.186 + avail = getNextTransition(nextTransitionTime, FALSE, tr); 1.187 + if (avail) { 1.188 + // Check if the next next transition is either DST->STD or STD->DST 1.189 + // and within roughly 1 year from the next transition 1.190 + if (((tr.getFrom()->getDSTSavings() == 0 && tr.getTo()->getDSTSavings() != 0) 1.191 + || (tr.getFrom()->getDSTSavings() != 0 && tr.getTo()->getDSTSavings() == 0)) 1.192 + && nextTransitionTime + MILLIS_PER_YEAR > tr.getTime()) { 1.193 + 1.194 + // Get local wall time for the next transition time 1.195 + Grego::timeToFields(tr.getTime() + tr.getFrom()->getRawOffset() + tr.getFrom()->getDSTSavings(), 1.196 + year, month, dom, dow, doy, mid); 1.197 + weekInMonth = Grego::dayOfWeekInMonth(year, month, dom); 1.198 + // Generate another DOW rule 1.199 + dtr = new DateTimeRule(month, weekInMonth, dow, mid, DateTimeRule::WALL_TIME); 1.200 + tr.getTo()->getName(name); 1.201 + ar2 = new AnnualTimeZoneRule(name, tr.getTo()->getRawOffset(), tr.getTo()->getDSTSavings(), 1.202 + dtr, year - 1, AnnualTimeZoneRule::MAX_YEAR); 1.203 + 1.204 + // Make sure this rule can be applied to the specified date 1.205 + avail = ar2->getPreviousStart(date, tr.getFrom()->getRawOffset(), tr.getFrom()->getDSTSavings(), TRUE, d); 1.206 + if (!avail || d > date 1.207 + || initialRaw != tr.getTo()->getRawOffset() 1.208 + || initialDst != tr.getTo()->getDSTSavings()) { 1.209 + // We cannot use this rule as the second transition rule 1.210 + delete ar2; 1.211 + ar2 = NULL; 1.212 + } 1.213 + } 1.214 + } 1.215 + } 1.216 + if (ar2 == NULL) { 1.217 + // Try previous transition 1.218 + avail = getPreviousTransition(date, TRUE, tr); 1.219 + if (avail) { 1.220 + // Check if the previous transition is either DST->STD or STD->DST. 1.221 + // The actual transition time does not matter here. 1.222 + if ((tr.getFrom()->getDSTSavings() == 0 && tr.getTo()->getDSTSavings() != 0) 1.223 + || (tr.getFrom()->getDSTSavings() != 0 && tr.getTo()->getDSTSavings() == 0)) { 1.224 + 1.225 + // Generate another DOW rule 1.226 + Grego::timeToFields(tr.getTime() + tr.getFrom()->getRawOffset() + tr.getFrom()->getDSTSavings(), 1.227 + year, month, dom, dow, doy, mid); 1.228 + weekInMonth = Grego::dayOfWeekInMonth(year, month, dom); 1.229 + dtr = new DateTimeRule(month, weekInMonth, dow, mid, DateTimeRule::WALL_TIME); 1.230 + tr.getTo()->getName(name); 1.231 + 1.232 + // second rule raw/dst offsets should match raw/dst offsets 1.233 + // at the given time 1.234 + ar2 = new AnnualTimeZoneRule(name, initialRaw, initialDst, 1.235 + dtr, ar1->getStartYear() - 1, AnnualTimeZoneRule::MAX_YEAR); 1.236 + 1.237 + // Check if this rule start after the first rule after the specified date 1.238 + avail = ar2->getNextStart(date, tr.getFrom()->getRawOffset(), tr.getFrom()->getDSTSavings(), FALSE, d); 1.239 + if (!avail || d <= nextTransitionTime) { 1.240 + // We cannot use this rule as the second transition rule 1.241 + delete ar2; 1.242 + ar2 = NULL; 1.243 + } 1.244 + } 1.245 + } 1.246 + } 1.247 + if (ar2 == NULL) { 1.248 + // Cannot find a good pair of AnnualTimeZoneRule 1.249 + delete ar1; 1.250 + ar1 = NULL; 1.251 + } else { 1.252 + // The initial rule should represent the rule before the previous transition 1.253 + ar1->getName(initialName); 1.254 + initialRaw = ar1->getRawOffset(); 1.255 + initialDst = ar1->getDSTSavings(); 1.256 + } 1.257 + } 1.258 + } 1.259 + else { 1.260 + // Try the previous one 1.261 + avail = getPreviousTransition(date, TRUE, tr); 1.262 + if (avail) { 1.263 + tr.getTo()->getName(initialName); 1.264 + initialRaw = tr.getTo()->getRawOffset(); 1.265 + initialDst = tr.getTo()->getDSTSavings(); 1.266 + } else { 1.267 + // No transitions in the past. Just use the current offsets 1.268 + getOffset(date, FALSE, initialRaw, initialDst, status); 1.269 + if (U_FAILURE(status)) { 1.270 + return; 1.271 + } 1.272 + } 1.273 + } 1.274 + // Set the initial rule 1.275 + initial = new InitialTimeZoneRule(initialName, initialRaw, initialDst); 1.276 + 1.277 + // Set the standard and daylight saving rules 1.278 + if (ar1 != NULL && ar2 != NULL) { 1.279 + if (ar1->getDSTSavings() != 0) { 1.280 + dst = ar1; 1.281 + std = ar2; 1.282 + } else { 1.283 + std = ar1; 1.284 + dst = ar2; 1.285 + } 1.286 + } 1.287 +} 1.288 + 1.289 +void 1.290 +BasicTimeZone::getTimeZoneRulesAfter(UDate start, InitialTimeZoneRule*& initial, 1.291 + UVector*& transitionRules, UErrorCode& status) const { 1.292 + if (U_FAILURE(status)) { 1.293 + return; 1.294 + } 1.295 + 1.296 + const InitialTimeZoneRule *orgini; 1.297 + const TimeZoneRule **orgtrs = NULL; 1.298 + TimeZoneTransition tzt; 1.299 + UBool avail; 1.300 + UVector *orgRules = NULL; 1.301 + int32_t ruleCount; 1.302 + TimeZoneRule *r = NULL; 1.303 + UBool *done = NULL; 1.304 + InitialTimeZoneRule *res_initial = NULL; 1.305 + UVector *filteredRules = NULL; 1.306 + UnicodeString name; 1.307 + int32_t i; 1.308 + UDate time, t; 1.309 + UDate *newTimes = NULL; 1.310 + UDate firstStart; 1.311 + UBool bFinalStd = FALSE, bFinalDst = FALSE; 1.312 + 1.313 + // Original transition rules 1.314 + ruleCount = countTransitionRules(status); 1.315 + if (U_FAILURE(status)) { 1.316 + return; 1.317 + } 1.318 + orgRules = new UVector(ruleCount, status); 1.319 + if (U_FAILURE(status)) { 1.320 + return; 1.321 + } 1.322 + orgtrs = (const TimeZoneRule**)uprv_malloc(sizeof(TimeZoneRule*)*ruleCount); 1.323 + if (orgtrs == NULL) { 1.324 + status = U_MEMORY_ALLOCATION_ERROR; 1.325 + goto error; 1.326 + } 1.327 + getTimeZoneRules(orgini, orgtrs, ruleCount, status); 1.328 + if (U_FAILURE(status)) { 1.329 + goto error; 1.330 + } 1.331 + for (i = 0; i < ruleCount; i++) { 1.332 + orgRules->addElement(orgtrs[i]->clone(), status); 1.333 + if (U_FAILURE(status)) { 1.334 + goto error; 1.335 + } 1.336 + } 1.337 + uprv_free(orgtrs); 1.338 + orgtrs = NULL; 1.339 + 1.340 + avail = getPreviousTransition(start, TRUE, tzt); 1.341 + if (!avail) { 1.342 + // No need to filter out rules only applicable to time before the start 1.343 + initial = orgini->clone(); 1.344 + transitionRules = orgRules; 1.345 + return; 1.346 + } 1.347 + 1.348 + done = (UBool*)uprv_malloc(sizeof(UBool)*ruleCount); 1.349 + if (done == NULL) { 1.350 + status = U_MEMORY_ALLOCATION_ERROR; 1.351 + goto error; 1.352 + } 1.353 + filteredRules = new UVector(status); 1.354 + if (U_FAILURE(status)) { 1.355 + goto error; 1.356 + } 1.357 + 1.358 + // Create initial rule 1.359 + tzt.getTo()->getName(name); 1.360 + res_initial = new InitialTimeZoneRule(name, tzt.getTo()->getRawOffset(), 1.361 + tzt.getTo()->getDSTSavings()); 1.362 + 1.363 + // Mark rules which does not need to be processed 1.364 + for (i = 0; i < ruleCount; i++) { 1.365 + r = (TimeZoneRule*)orgRules->elementAt(i); 1.366 + avail = r->getNextStart(start, res_initial->getRawOffset(), res_initial->getDSTSavings(), FALSE, time); 1.367 + done[i] = !avail; 1.368 + } 1.369 + 1.370 + time = start; 1.371 + while (!bFinalStd || !bFinalDst) { 1.372 + avail = getNextTransition(time, FALSE, tzt); 1.373 + if (!avail) { 1.374 + break; 1.375 + } 1.376 + UDate updatedTime = tzt.getTime(); 1.377 + if (updatedTime == time) { 1.378 + // Can get here if rules for start & end of daylight time have exactly 1.379 + // the same time. 1.380 + // TODO: fix getNextTransition() to prevent it? 1.381 + status = U_INVALID_STATE_ERROR; 1.382 + goto error; 1.383 + } 1.384 + time = updatedTime; 1.385 + 1.386 + const TimeZoneRule *toRule = tzt.getTo(); 1.387 + for (i = 0; i < ruleCount; i++) { 1.388 + r = (TimeZoneRule*)orgRules->elementAt(i); 1.389 + if (*r == *toRule) { 1.390 + break; 1.391 + } 1.392 + } 1.393 + if (i >= ruleCount) { 1.394 + // This case should never happen 1.395 + status = U_INVALID_STATE_ERROR; 1.396 + goto error; 1.397 + } 1.398 + if (done[i]) { 1.399 + continue; 1.400 + } 1.401 + const TimeArrayTimeZoneRule *tar = dynamic_cast<const TimeArrayTimeZoneRule *>(toRule); 1.402 + const AnnualTimeZoneRule *ar; 1.403 + if (tar != NULL) { 1.404 + // Get the previous raw offset and DST savings before the very first start time 1.405 + TimeZoneTransition tzt0; 1.406 + t = start; 1.407 + while (TRUE) { 1.408 + avail = getNextTransition(t, FALSE, tzt0); 1.409 + if (!avail) { 1.410 + break; 1.411 + } 1.412 + if (*(tzt0.getTo()) == *tar) { 1.413 + break; 1.414 + } 1.415 + t = tzt0.getTime(); 1.416 + } 1.417 + if (avail) { 1.418 + // Check if the entire start times to be added 1.419 + tar->getFirstStart(tzt.getFrom()->getRawOffset(), tzt.getFrom()->getDSTSavings(), firstStart); 1.420 + if (firstStart > start) { 1.421 + // Just add the rule as is 1.422 + filteredRules->addElement(tar->clone(), status); 1.423 + if (U_FAILURE(status)) { 1.424 + goto error; 1.425 + } 1.426 + } else { 1.427 + // Colllect transitions after the start time 1.428 + int32_t startTimes; 1.429 + DateTimeRule::TimeRuleType timeType; 1.430 + int32_t idx; 1.431 + 1.432 + startTimes = tar->countStartTimes(); 1.433 + timeType = tar->getTimeType(); 1.434 + for (idx = 0; idx < startTimes; idx++) { 1.435 + tar->getStartTimeAt(idx, t); 1.436 + if (timeType == DateTimeRule::STANDARD_TIME) { 1.437 + t -= tzt.getFrom()->getRawOffset(); 1.438 + } 1.439 + if (timeType == DateTimeRule::WALL_TIME) { 1.440 + t -= tzt.getFrom()->getDSTSavings(); 1.441 + } 1.442 + if (t > start) { 1.443 + break; 1.444 + } 1.445 + } 1.446 + int32_t asize = startTimes - idx; 1.447 + if (asize > 0) { 1.448 + newTimes = (UDate*)uprv_malloc(sizeof(UDate) * asize); 1.449 + if (newTimes == NULL) { 1.450 + status = U_MEMORY_ALLOCATION_ERROR; 1.451 + goto error; 1.452 + } 1.453 + for (int32_t newidx = 0; newidx < asize; newidx++) { 1.454 + tar->getStartTimeAt(idx + newidx, newTimes[newidx]); 1.455 + if (U_FAILURE(status)) { 1.456 + uprv_free(newTimes); 1.457 + newTimes = NULL; 1.458 + goto error; 1.459 + } 1.460 + } 1.461 + tar->getName(name); 1.462 + TimeArrayTimeZoneRule *newTar = new TimeArrayTimeZoneRule(name, 1.463 + tar->getRawOffset(), tar->getDSTSavings(), newTimes, asize, timeType); 1.464 + uprv_free(newTimes); 1.465 + filteredRules->addElement(newTar, status); 1.466 + if (U_FAILURE(status)) { 1.467 + goto error; 1.468 + } 1.469 + } 1.470 + } 1.471 + } 1.472 + } else if ((ar = dynamic_cast<const AnnualTimeZoneRule *>(toRule)) != NULL) { 1.473 + ar->getFirstStart(tzt.getFrom()->getRawOffset(), tzt.getFrom()->getDSTSavings(), firstStart); 1.474 + if (firstStart == tzt.getTime()) { 1.475 + // Just add the rule as is 1.476 + filteredRules->addElement(ar->clone(), status); 1.477 + if (U_FAILURE(status)) { 1.478 + goto error; 1.479 + } 1.480 + } else { 1.481 + // Calculate the transition year 1.482 + int32_t year, month, dom, dow, doy, mid; 1.483 + Grego::timeToFields(tzt.getTime(), year, month, dom, dow, doy, mid); 1.484 + // Re-create the rule 1.485 + ar->getName(name); 1.486 + AnnualTimeZoneRule *newAr = new AnnualTimeZoneRule(name, ar->getRawOffset(), ar->getDSTSavings(), 1.487 + *(ar->getRule()), year, ar->getEndYear()); 1.488 + filteredRules->addElement(newAr, status); 1.489 + if (U_FAILURE(status)) { 1.490 + goto error; 1.491 + } 1.492 + } 1.493 + // check if this is a final rule 1.494 + if (ar->getEndYear() == AnnualTimeZoneRule::MAX_YEAR) { 1.495 + // After bot final standard and dst rules are processed, 1.496 + // exit this while loop. 1.497 + if (ar->getDSTSavings() == 0) { 1.498 + bFinalStd = TRUE; 1.499 + } else { 1.500 + bFinalDst = TRUE; 1.501 + } 1.502 + } 1.503 + } 1.504 + done[i] = TRUE; 1.505 + } 1.506 + 1.507 + // Set the results 1.508 + if (orgRules != NULL) { 1.509 + while (!orgRules->isEmpty()) { 1.510 + r = (TimeZoneRule*)orgRules->orphanElementAt(0); 1.511 + delete r; 1.512 + } 1.513 + delete orgRules; 1.514 + } 1.515 + if (done != NULL) { 1.516 + uprv_free(done); 1.517 + } 1.518 + 1.519 + initial = res_initial; 1.520 + transitionRules = filteredRules; 1.521 + return; 1.522 + 1.523 +error: 1.524 + if (orgtrs != NULL) { 1.525 + uprv_free(orgtrs); 1.526 + } 1.527 + if (orgRules != NULL) { 1.528 + while (!orgRules->isEmpty()) { 1.529 + r = (TimeZoneRule*)orgRules->orphanElementAt(0); 1.530 + delete r; 1.531 + } 1.532 + delete orgRules; 1.533 + } 1.534 + if (done != NULL) { 1.535 + if (filteredRules != NULL) { 1.536 + while (!filteredRules->isEmpty()) { 1.537 + r = (TimeZoneRule*)filteredRules->orphanElementAt(0); 1.538 + delete r; 1.539 + } 1.540 + delete filteredRules; 1.541 + } 1.542 + delete res_initial; 1.543 + uprv_free(done); 1.544 + } 1.545 + 1.546 + initial = NULL; 1.547 + transitionRules = NULL; 1.548 +} 1.549 + 1.550 +void 1.551 +BasicTimeZone::getOffsetFromLocal(UDate /*date*/, int32_t /*nonExistingTimeOpt*/, int32_t /*duplicatedTimeOpt*/, 1.552 + int32_t& /*rawOffset*/, int32_t& /*dstOffset*/, UErrorCode& status) const { 1.553 + if (U_FAILURE(status)) { 1.554 + return; 1.555 + } 1.556 + status = U_UNSUPPORTED_ERROR; 1.557 +} 1.558 + 1.559 +U_NAMESPACE_END 1.560 + 1.561 +#endif /* #if !UCONFIG_NO_FORMATTING */ 1.562 + 1.563 +//eof