intl/icu/source/i18n/tzrule.cpp

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

michael@0 1 /*
michael@0 2 *******************************************************************************
michael@0 3 * Copyright (C) 2007-2012, International Business Machines Corporation and
michael@0 4 * others. All Rights Reserved.
michael@0 5 *******************************************************************************
michael@0 6 */
michael@0 7
michael@0 8 #include "utypeinfo.h" // for 'typeid' to work
michael@0 9
michael@0 10 #include "unicode/utypes.h"
michael@0 11
michael@0 12 #if !UCONFIG_NO_FORMATTING
michael@0 13
michael@0 14 #include "unicode/tzrule.h"
michael@0 15 #include "unicode/ucal.h"
michael@0 16 #include "gregoimp.h"
michael@0 17 #include "cmemory.h"
michael@0 18 #include "uarrsort.h"
michael@0 19
michael@0 20 U_CDECL_BEGIN
michael@0 21 // UComparator function for sorting start times
michael@0 22 static int32_t U_CALLCONV
michael@0 23 compareDates(const void * /*context*/, const void *left, const void *right) {
michael@0 24 UDate l = *((UDate*)left);
michael@0 25 UDate r = *((UDate*)right);
michael@0 26 int32_t res = l < r ? -1 : (l == r ? 0 : 1);
michael@0 27 return res;
michael@0 28 }
michael@0 29 U_CDECL_END
michael@0 30
michael@0 31 U_NAMESPACE_BEGIN
michael@0 32
michael@0 33 TimeZoneRule::TimeZoneRule(const UnicodeString& name, int32_t rawOffset, int32_t dstSavings)
michael@0 34 : UObject(), fName(name), fRawOffset(rawOffset), fDSTSavings(dstSavings) {
michael@0 35 }
michael@0 36
michael@0 37 TimeZoneRule::TimeZoneRule(const TimeZoneRule& source)
michael@0 38 : UObject(source), fName(source.fName), fRawOffset(source.fRawOffset), fDSTSavings(source.fDSTSavings) {
michael@0 39 }
michael@0 40
michael@0 41 TimeZoneRule::~TimeZoneRule() {
michael@0 42 }
michael@0 43
michael@0 44 TimeZoneRule&
michael@0 45 TimeZoneRule::operator=(const TimeZoneRule& right) {
michael@0 46 if (this != &right) {
michael@0 47 fName = right.fName;
michael@0 48 fRawOffset = right.fRawOffset;
michael@0 49 fDSTSavings = right.fDSTSavings;
michael@0 50 }
michael@0 51 return *this;
michael@0 52 }
michael@0 53
michael@0 54 UBool
michael@0 55 TimeZoneRule::operator==(const TimeZoneRule& that) const {
michael@0 56 return ((this == &that) ||
michael@0 57 (typeid(*this) == typeid(that) &&
michael@0 58 fName == that.fName &&
michael@0 59 fRawOffset == that.fRawOffset &&
michael@0 60 fDSTSavings == that.fDSTSavings));
michael@0 61 }
michael@0 62
michael@0 63 UBool
michael@0 64 TimeZoneRule::operator!=(const TimeZoneRule& that) const {
michael@0 65 return !operator==(that);
michael@0 66 }
michael@0 67
michael@0 68 UnicodeString&
michael@0 69 TimeZoneRule::getName(UnicodeString& name) const {
michael@0 70 name = fName;
michael@0 71 return name;
michael@0 72 }
michael@0 73
michael@0 74 int32_t
michael@0 75 TimeZoneRule::getRawOffset(void) const {
michael@0 76 return fRawOffset;
michael@0 77 }
michael@0 78
michael@0 79 int32_t
michael@0 80 TimeZoneRule::getDSTSavings(void) const {
michael@0 81 return fDSTSavings;
michael@0 82 }
michael@0 83
michael@0 84 UBool
michael@0 85 TimeZoneRule::isEquivalentTo(const TimeZoneRule& other) const {
michael@0 86 return ((this == &other) ||
michael@0 87 (typeid(*this) == typeid(other) &&
michael@0 88 fRawOffset == other.fRawOffset &&
michael@0 89 fDSTSavings == other.fDSTSavings));
michael@0 90 }
michael@0 91
michael@0 92
michael@0 93 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(InitialTimeZoneRule)
michael@0 94
michael@0 95 InitialTimeZoneRule::InitialTimeZoneRule(const UnicodeString& name,
michael@0 96 int32_t rawOffset,
michael@0 97 int32_t dstSavings)
michael@0 98 : TimeZoneRule(name, rawOffset, dstSavings) {
michael@0 99 }
michael@0 100
michael@0 101 InitialTimeZoneRule::InitialTimeZoneRule(const InitialTimeZoneRule& source)
michael@0 102 : TimeZoneRule(source) {
michael@0 103 }
michael@0 104
michael@0 105 InitialTimeZoneRule::~InitialTimeZoneRule() {
michael@0 106 }
michael@0 107
michael@0 108 InitialTimeZoneRule*
michael@0 109 InitialTimeZoneRule::clone(void) const {
michael@0 110 return new InitialTimeZoneRule(*this);
michael@0 111 }
michael@0 112
michael@0 113 InitialTimeZoneRule&
michael@0 114 InitialTimeZoneRule::operator=(const InitialTimeZoneRule& right) {
michael@0 115 if (this != &right) {
michael@0 116 TimeZoneRule::operator=(right);
michael@0 117 }
michael@0 118 return *this;
michael@0 119 }
michael@0 120
michael@0 121 UBool
michael@0 122 InitialTimeZoneRule::operator==(const TimeZoneRule& that) const {
michael@0 123 return ((this == &that) ||
michael@0 124 (typeid(*this) == typeid(that) &&
michael@0 125 TimeZoneRule::operator==(that)));
michael@0 126 }
michael@0 127
michael@0 128 UBool
michael@0 129 InitialTimeZoneRule::operator!=(const TimeZoneRule& that) const {
michael@0 130 return !operator==(that);
michael@0 131 }
michael@0 132
michael@0 133 UBool
michael@0 134 InitialTimeZoneRule::isEquivalentTo(const TimeZoneRule& other) const {
michael@0 135 if (this == &other) {
michael@0 136 return TRUE;
michael@0 137 }
michael@0 138 if (typeid(*this) != typeid(other) || TimeZoneRule::isEquivalentTo(other) == FALSE) {
michael@0 139 return FALSE;
michael@0 140 }
michael@0 141 return TRUE;
michael@0 142 }
michael@0 143
michael@0 144 UBool
michael@0 145 InitialTimeZoneRule::getFirstStart(int32_t /*prevRawOffset*/,
michael@0 146 int32_t /*prevDSTSavings*/,
michael@0 147 UDate& /*result*/) const {
michael@0 148 return FALSE;
michael@0 149 }
michael@0 150
michael@0 151 UBool
michael@0 152 InitialTimeZoneRule::getFinalStart(int32_t /*prevRawOffset*/,
michael@0 153 int32_t /*prevDSTSavings*/,
michael@0 154 UDate& /*result*/) const {
michael@0 155 return FALSE;
michael@0 156 }
michael@0 157
michael@0 158 UBool
michael@0 159 InitialTimeZoneRule::getNextStart(UDate /*base*/,
michael@0 160 int32_t /*prevRawOffset*/,
michael@0 161 int32_t /*prevDSTSavings*/,
michael@0 162 UBool /*inclusive*/,
michael@0 163 UDate& /*result*/) const {
michael@0 164 return FALSE;
michael@0 165 }
michael@0 166
michael@0 167 UBool
michael@0 168 InitialTimeZoneRule::getPreviousStart(UDate /*base*/,
michael@0 169 int32_t /*prevRawOffset*/,
michael@0 170 int32_t /*prevDSTSavings*/,
michael@0 171 UBool /*inclusive*/,
michael@0 172 UDate& /*result*/) const {
michael@0 173 return FALSE;
michael@0 174 }
michael@0 175
michael@0 176
michael@0 177 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(AnnualTimeZoneRule)
michael@0 178
michael@0 179 const int32_t AnnualTimeZoneRule::MAX_YEAR = 0x7FFFFFFF; /* max signed int32 */
michael@0 180
michael@0 181 AnnualTimeZoneRule::AnnualTimeZoneRule(const UnicodeString& name,
michael@0 182 int32_t rawOffset,
michael@0 183 int32_t dstSavings,
michael@0 184 const DateTimeRule& dateTimeRule,
michael@0 185 int32_t startYear,
michael@0 186 int32_t endYear)
michael@0 187 : TimeZoneRule(name, rawOffset, dstSavings), fDateTimeRule(new DateTimeRule(dateTimeRule)),
michael@0 188 fStartYear(startYear), fEndYear(endYear) {
michael@0 189 }
michael@0 190
michael@0 191 AnnualTimeZoneRule::AnnualTimeZoneRule(const UnicodeString& name,
michael@0 192 int32_t rawOffset,
michael@0 193 int32_t dstSavings,
michael@0 194 DateTimeRule* dateTimeRule,
michael@0 195 int32_t startYear,
michael@0 196 int32_t endYear)
michael@0 197 : TimeZoneRule(name, rawOffset, dstSavings), fDateTimeRule(dateTimeRule),
michael@0 198 fStartYear(startYear), fEndYear(endYear) {
michael@0 199 }
michael@0 200
michael@0 201 AnnualTimeZoneRule::AnnualTimeZoneRule(const AnnualTimeZoneRule& source)
michael@0 202 : TimeZoneRule(source), fDateTimeRule(new DateTimeRule(*(source.fDateTimeRule))),
michael@0 203 fStartYear(source.fStartYear), fEndYear(source.fEndYear) {
michael@0 204 }
michael@0 205
michael@0 206 AnnualTimeZoneRule::~AnnualTimeZoneRule() {
michael@0 207 delete fDateTimeRule;
michael@0 208 }
michael@0 209
michael@0 210 AnnualTimeZoneRule*
michael@0 211 AnnualTimeZoneRule::clone(void) const {
michael@0 212 return new AnnualTimeZoneRule(*this);
michael@0 213 }
michael@0 214
michael@0 215 AnnualTimeZoneRule&
michael@0 216 AnnualTimeZoneRule::operator=(const AnnualTimeZoneRule& right) {
michael@0 217 if (this != &right) {
michael@0 218 TimeZoneRule::operator=(right);
michael@0 219 delete fDateTimeRule;
michael@0 220 fDateTimeRule = right.fDateTimeRule->clone();
michael@0 221 fStartYear = right.fStartYear;
michael@0 222 fEndYear = right.fEndYear;
michael@0 223 }
michael@0 224 return *this;
michael@0 225 }
michael@0 226
michael@0 227 UBool
michael@0 228 AnnualTimeZoneRule::operator==(const TimeZoneRule& that) const {
michael@0 229 if (this == &that) {
michael@0 230 return TRUE;
michael@0 231 }
michael@0 232 if (typeid(*this) != typeid(that)) {
michael@0 233 return FALSE;
michael@0 234 }
michael@0 235 AnnualTimeZoneRule *atzr = (AnnualTimeZoneRule*)&that;
michael@0 236 return (*fDateTimeRule == *(atzr->fDateTimeRule) &&
michael@0 237 fStartYear == atzr->fStartYear &&
michael@0 238 fEndYear == atzr->fEndYear);
michael@0 239 }
michael@0 240
michael@0 241 UBool
michael@0 242 AnnualTimeZoneRule::operator!=(const TimeZoneRule& that) const {
michael@0 243 return !operator==(that);
michael@0 244 }
michael@0 245
michael@0 246 const DateTimeRule*
michael@0 247 AnnualTimeZoneRule::getRule() const {
michael@0 248 return fDateTimeRule;
michael@0 249 }
michael@0 250
michael@0 251 int32_t
michael@0 252 AnnualTimeZoneRule::getStartYear() const {
michael@0 253 return fStartYear;
michael@0 254 }
michael@0 255
michael@0 256 int32_t
michael@0 257 AnnualTimeZoneRule::getEndYear() const {
michael@0 258 return fEndYear;
michael@0 259 }
michael@0 260
michael@0 261 UBool
michael@0 262 AnnualTimeZoneRule::getStartInYear(int32_t year,
michael@0 263 int32_t prevRawOffset,
michael@0 264 int32_t prevDSTSavings,
michael@0 265 UDate &result) const {
michael@0 266 if (year < fStartYear || year > fEndYear) {
michael@0 267 return FALSE;
michael@0 268 }
michael@0 269 double ruleDay;
michael@0 270 DateTimeRule::DateRuleType type = fDateTimeRule->getDateRuleType();
michael@0 271 if (type == DateTimeRule::DOM) {
michael@0 272 ruleDay = Grego::fieldsToDay(year, fDateTimeRule->getRuleMonth(), fDateTimeRule->getRuleDayOfMonth());
michael@0 273 } else {
michael@0 274 UBool after = TRUE;
michael@0 275 if (type == DateTimeRule::DOW) {
michael@0 276 // Normalize DOW rule into DOW_GEQ_DOM or DOW_LEQ_DOM
michael@0 277 int32_t weeks = fDateTimeRule->getRuleWeekInMonth();
michael@0 278 if (weeks > 0) {
michael@0 279 ruleDay = Grego::fieldsToDay(year, fDateTimeRule->getRuleMonth(), 1);
michael@0 280 ruleDay += 7 * (weeks - 1);
michael@0 281 } else {
michael@0 282 after = FALSE;
michael@0 283 ruleDay = Grego::fieldsToDay(year, fDateTimeRule->getRuleMonth(),
michael@0 284 Grego::monthLength(year, fDateTimeRule->getRuleMonth()));
michael@0 285 ruleDay += 7 * (weeks + 1);
michael@0 286 }
michael@0 287 } else {
michael@0 288 int32_t month = fDateTimeRule->getRuleMonth();
michael@0 289 int32_t dom = fDateTimeRule->getRuleDayOfMonth();
michael@0 290 if (type == DateTimeRule::DOW_LEQ_DOM) {
michael@0 291 after = FALSE;
michael@0 292 // Handle Feb <=29
michael@0 293 if (month == UCAL_FEBRUARY && dom == 29 && !Grego::isLeapYear(year)) {
michael@0 294 dom--;
michael@0 295 }
michael@0 296 }
michael@0 297 ruleDay = Grego::fieldsToDay(year, month, dom);
michael@0 298 }
michael@0 299 int32_t dow = Grego::dayOfWeek(ruleDay);
michael@0 300 int32_t delta = fDateTimeRule->getRuleDayOfWeek() - dow;
michael@0 301 if (after) {
michael@0 302 delta = delta < 0 ? delta + 7 : delta;
michael@0 303 } else {
michael@0 304 delta = delta > 0 ? delta - 7 : delta;
michael@0 305 }
michael@0 306 ruleDay += delta;
michael@0 307 }
michael@0 308
michael@0 309 result = ruleDay*U_MILLIS_PER_DAY + fDateTimeRule->getRuleMillisInDay();
michael@0 310 if (fDateTimeRule->getTimeRuleType() != DateTimeRule::UTC_TIME) {
michael@0 311 result -= prevRawOffset;
michael@0 312 }
michael@0 313 if (fDateTimeRule->getTimeRuleType() == DateTimeRule::WALL_TIME) {
michael@0 314 result -= prevDSTSavings;
michael@0 315 }
michael@0 316 return TRUE;
michael@0 317 }
michael@0 318
michael@0 319 UBool
michael@0 320 AnnualTimeZoneRule::isEquivalentTo(const TimeZoneRule& other) const {
michael@0 321 if (this == &other) {
michael@0 322 return TRUE;
michael@0 323 }
michael@0 324 if (typeid(*this) != typeid(other) || TimeZoneRule::isEquivalentTo(other) == FALSE) {
michael@0 325 return FALSE;
michael@0 326 }
michael@0 327 AnnualTimeZoneRule* that = (AnnualTimeZoneRule*)&other;
michael@0 328 return (*fDateTimeRule == *(that->fDateTimeRule) &&
michael@0 329 fStartYear == that->fStartYear &&
michael@0 330 fEndYear == that->fEndYear);
michael@0 331 }
michael@0 332
michael@0 333 UBool
michael@0 334 AnnualTimeZoneRule::getFirstStart(int32_t prevRawOffset,
michael@0 335 int32_t prevDSTSavings,
michael@0 336 UDate& result) const {
michael@0 337 return getStartInYear(fStartYear, prevRawOffset, prevDSTSavings, result);
michael@0 338 }
michael@0 339
michael@0 340 UBool
michael@0 341 AnnualTimeZoneRule::getFinalStart(int32_t prevRawOffset,
michael@0 342 int32_t prevDSTSavings,
michael@0 343 UDate& result) const {
michael@0 344 if (fEndYear == MAX_YEAR) {
michael@0 345 return FALSE;
michael@0 346 }
michael@0 347 return getStartInYear(fEndYear, prevRawOffset, prevDSTSavings, result);
michael@0 348 }
michael@0 349
michael@0 350 UBool
michael@0 351 AnnualTimeZoneRule::getNextStart(UDate base,
michael@0 352 int32_t prevRawOffset,
michael@0 353 int32_t prevDSTSavings,
michael@0 354 UBool inclusive,
michael@0 355 UDate& result) const {
michael@0 356 int32_t year, month, dom, dow, doy, mid;
michael@0 357 Grego::timeToFields(base, year, month, dom, dow, doy, mid);
michael@0 358 if (year < fStartYear) {
michael@0 359 return getFirstStart(prevRawOffset, prevDSTSavings, result);
michael@0 360 }
michael@0 361 UDate tmp;
michael@0 362 if (getStartInYear(year, prevRawOffset, prevDSTSavings, tmp)) {
michael@0 363 if (tmp < base || (!inclusive && (tmp == base))) {
michael@0 364 // Return the next one
michael@0 365 return getStartInYear(year + 1, prevRawOffset, prevDSTSavings, result);
michael@0 366 } else {
michael@0 367 result = tmp;
michael@0 368 return TRUE;
michael@0 369 }
michael@0 370 }
michael@0 371 return FALSE;
michael@0 372 }
michael@0 373
michael@0 374 UBool
michael@0 375 AnnualTimeZoneRule::getPreviousStart(UDate base,
michael@0 376 int32_t prevRawOffset,
michael@0 377 int32_t prevDSTSavings,
michael@0 378 UBool inclusive,
michael@0 379 UDate& result) const {
michael@0 380 int32_t year, month, dom, dow, doy, mid;
michael@0 381 Grego::timeToFields(base, year, month, dom, dow, doy, mid);
michael@0 382 if (year > fEndYear) {
michael@0 383 return getFinalStart(prevRawOffset, prevDSTSavings, result);
michael@0 384 }
michael@0 385 UDate tmp;
michael@0 386 if (getStartInYear(year, prevRawOffset, prevDSTSavings, tmp)) {
michael@0 387 if (tmp > base || (!inclusive && (tmp == base))) {
michael@0 388 // Return the previous one
michael@0 389 return getStartInYear(year - 1, prevRawOffset, prevDSTSavings, result);
michael@0 390 } else {
michael@0 391 result = tmp;
michael@0 392 return TRUE;
michael@0 393 }
michael@0 394 }
michael@0 395 return FALSE;
michael@0 396 }
michael@0 397
michael@0 398 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(TimeArrayTimeZoneRule)
michael@0 399
michael@0 400 TimeArrayTimeZoneRule::TimeArrayTimeZoneRule(const UnicodeString& name,
michael@0 401 int32_t rawOffset,
michael@0 402 int32_t dstSavings,
michael@0 403 const UDate* startTimes,
michael@0 404 int32_t numStartTimes,
michael@0 405 DateTimeRule::TimeRuleType timeRuleType)
michael@0 406 : TimeZoneRule(name, rawOffset, dstSavings), fTimeRuleType(timeRuleType),
michael@0 407 fStartTimes(NULL) {
michael@0 408 UErrorCode status = U_ZERO_ERROR;
michael@0 409 initStartTimes(startTimes, numStartTimes, status);
michael@0 410 //TODO - status?
michael@0 411 }
michael@0 412
michael@0 413
michael@0 414 TimeArrayTimeZoneRule::TimeArrayTimeZoneRule(const TimeArrayTimeZoneRule& source)
michael@0 415 : TimeZoneRule(source), fTimeRuleType(source.fTimeRuleType), fStartTimes(NULL) {
michael@0 416 UErrorCode status = U_ZERO_ERROR;
michael@0 417 initStartTimes(source.fStartTimes, source.fNumStartTimes, status);
michael@0 418 //TODO - status?
michael@0 419 }
michael@0 420
michael@0 421
michael@0 422 TimeArrayTimeZoneRule::~TimeArrayTimeZoneRule() {
michael@0 423 if (fStartTimes != NULL && fStartTimes != fLocalStartTimes) {
michael@0 424 uprv_free(fStartTimes);
michael@0 425 }
michael@0 426 }
michael@0 427
michael@0 428 TimeArrayTimeZoneRule*
michael@0 429 TimeArrayTimeZoneRule::clone(void) const {
michael@0 430 return new TimeArrayTimeZoneRule(*this);
michael@0 431 }
michael@0 432
michael@0 433
michael@0 434 TimeArrayTimeZoneRule&
michael@0 435 TimeArrayTimeZoneRule::operator=(const TimeArrayTimeZoneRule& right) {
michael@0 436 if (this != &right) {
michael@0 437 TimeZoneRule::operator=(right);
michael@0 438 UErrorCode status = U_ZERO_ERROR;
michael@0 439 initStartTimes(right.fStartTimes, right.fNumStartTimes, status);
michael@0 440 //TODO - status?
michael@0 441 fTimeRuleType = right.fTimeRuleType;
michael@0 442 }
michael@0 443 return *this;
michael@0 444 }
michael@0 445
michael@0 446 UBool
michael@0 447 TimeArrayTimeZoneRule::operator==(const TimeZoneRule& that) const {
michael@0 448 if (this == &that) {
michael@0 449 return TRUE;
michael@0 450 }
michael@0 451 if (typeid(*this) != typeid(that) || TimeZoneRule::operator==(that) == FALSE) {
michael@0 452 return FALSE;
michael@0 453 }
michael@0 454 TimeArrayTimeZoneRule *tatzr = (TimeArrayTimeZoneRule*)&that;
michael@0 455 if (fTimeRuleType != tatzr->fTimeRuleType ||
michael@0 456 fNumStartTimes != tatzr->fNumStartTimes) {
michael@0 457 return FALSE;
michael@0 458 }
michael@0 459 // Compare start times
michael@0 460 UBool res = TRUE;
michael@0 461 for (int32_t i = 0; i < fNumStartTimes; i++) {
michael@0 462 if (fStartTimes[i] != tatzr->fStartTimes[i]) {
michael@0 463 res = FALSE;
michael@0 464 break;
michael@0 465 }
michael@0 466 }
michael@0 467 return res;
michael@0 468 }
michael@0 469
michael@0 470 UBool
michael@0 471 TimeArrayTimeZoneRule::operator!=(const TimeZoneRule& that) const {
michael@0 472 return !operator==(that);
michael@0 473 }
michael@0 474
michael@0 475 DateTimeRule::TimeRuleType
michael@0 476 TimeArrayTimeZoneRule::getTimeType(void) const {
michael@0 477 return fTimeRuleType;
michael@0 478 }
michael@0 479
michael@0 480 UBool
michael@0 481 TimeArrayTimeZoneRule::getStartTimeAt(int32_t index, UDate& result) const {
michael@0 482 if (index >= fNumStartTimes || index < 0) {
michael@0 483 return FALSE;
michael@0 484 }
michael@0 485 result = fStartTimes[index];
michael@0 486 return TRUE;
michael@0 487 }
michael@0 488
michael@0 489 int32_t
michael@0 490 TimeArrayTimeZoneRule::countStartTimes(void) const {
michael@0 491 return fNumStartTimes;
michael@0 492 }
michael@0 493
michael@0 494 UBool
michael@0 495 TimeArrayTimeZoneRule::isEquivalentTo(const TimeZoneRule& other) const {
michael@0 496 if (this == &other) {
michael@0 497 return TRUE;
michael@0 498 }
michael@0 499 if (typeid(*this) != typeid(other) || TimeZoneRule::isEquivalentTo(other) == FALSE) {
michael@0 500 return FALSE;
michael@0 501 }
michael@0 502 TimeArrayTimeZoneRule* that = (TimeArrayTimeZoneRule*)&other;
michael@0 503 if (fTimeRuleType != that->fTimeRuleType ||
michael@0 504 fNumStartTimes != that->fNumStartTimes) {
michael@0 505 return FALSE;
michael@0 506 }
michael@0 507 // Compare start times
michael@0 508 UBool res = TRUE;
michael@0 509 for (int32_t i = 0; i < fNumStartTimes; i++) {
michael@0 510 if (fStartTimes[i] != that->fStartTimes[i]) {
michael@0 511 res = FALSE;
michael@0 512 break;
michael@0 513 }
michael@0 514 }
michael@0 515 return res;
michael@0 516 }
michael@0 517
michael@0 518 UBool
michael@0 519 TimeArrayTimeZoneRule::getFirstStart(int32_t prevRawOffset,
michael@0 520 int32_t prevDSTSavings,
michael@0 521 UDate& result) const {
michael@0 522 if (fNumStartTimes <= 0 || fStartTimes == NULL) {
michael@0 523 return FALSE;
michael@0 524 }
michael@0 525 result = getUTC(fStartTimes[0], prevRawOffset, prevDSTSavings);
michael@0 526 return TRUE;
michael@0 527 }
michael@0 528
michael@0 529 UBool
michael@0 530 TimeArrayTimeZoneRule::getFinalStart(int32_t prevRawOffset,
michael@0 531 int32_t prevDSTSavings,
michael@0 532 UDate& result) const {
michael@0 533 if (fNumStartTimes <= 0 || fStartTimes == NULL) {
michael@0 534 return FALSE;
michael@0 535 }
michael@0 536 result = getUTC(fStartTimes[fNumStartTimes - 1], prevRawOffset, prevDSTSavings);
michael@0 537 return TRUE;
michael@0 538 }
michael@0 539
michael@0 540 UBool
michael@0 541 TimeArrayTimeZoneRule::getNextStart(UDate base,
michael@0 542 int32_t prevRawOffset,
michael@0 543 int32_t prevDSTSavings,
michael@0 544 UBool inclusive,
michael@0 545 UDate& result) const {
michael@0 546 int32_t i = fNumStartTimes - 1;
michael@0 547 for (; i >= 0; i--) {
michael@0 548 UDate time = getUTC(fStartTimes[i], prevRawOffset, prevDSTSavings);
michael@0 549 if (time < base || (!inclusive && time == base)) {
michael@0 550 break;
michael@0 551 }
michael@0 552 result = time;
michael@0 553 }
michael@0 554 if (i == fNumStartTimes - 1) {
michael@0 555 return FALSE;
michael@0 556 }
michael@0 557 return TRUE;
michael@0 558 }
michael@0 559
michael@0 560 UBool
michael@0 561 TimeArrayTimeZoneRule::getPreviousStart(UDate base,
michael@0 562 int32_t prevRawOffset,
michael@0 563 int32_t prevDSTSavings,
michael@0 564 UBool inclusive,
michael@0 565 UDate& result) const {
michael@0 566 int32_t i = fNumStartTimes - 1;
michael@0 567 for (; i >= 0; i--) {
michael@0 568 UDate time = getUTC(fStartTimes[i], prevRawOffset, prevDSTSavings);
michael@0 569 if (time < base || (inclusive && time == base)) {
michael@0 570 result = time;
michael@0 571 return TRUE;
michael@0 572 }
michael@0 573 }
michael@0 574 return FALSE;
michael@0 575 }
michael@0 576
michael@0 577
michael@0 578 // ---- private methods ------
michael@0 579
michael@0 580 UBool
michael@0 581 TimeArrayTimeZoneRule::initStartTimes(const UDate source[], int32_t size, UErrorCode& status) {
michael@0 582 // Free old array
michael@0 583 if (fStartTimes != NULL && fStartTimes != fLocalStartTimes) {
michael@0 584 uprv_free(fStartTimes);
michael@0 585 }
michael@0 586 // Allocate new one if needed
michael@0 587 if (size > TIMEARRAY_STACK_BUFFER_SIZE) {
michael@0 588 fStartTimes = (UDate*)uprv_malloc(sizeof(UDate)*size);
michael@0 589 if (fStartTimes == NULL) {
michael@0 590 status = U_MEMORY_ALLOCATION_ERROR;
michael@0 591 fNumStartTimes = 0;
michael@0 592 return FALSE;
michael@0 593 }
michael@0 594 } else {
michael@0 595 fStartTimes = (UDate*)fLocalStartTimes;
michael@0 596 }
michael@0 597 uprv_memcpy(fStartTimes, source, sizeof(UDate)*size);
michael@0 598 fNumStartTimes = size;
michael@0 599 // Sort dates
michael@0 600 uprv_sortArray(fStartTimes, fNumStartTimes, (int32_t)sizeof(UDate), compareDates, NULL, TRUE, &status);
michael@0 601 if (U_FAILURE(status)) {
michael@0 602 if (fStartTimes != NULL && fStartTimes != fLocalStartTimes) {
michael@0 603 uprv_free(fStartTimes);
michael@0 604 }
michael@0 605 fNumStartTimes = 0;
michael@0 606 return FALSE;
michael@0 607 }
michael@0 608 return TRUE;
michael@0 609 }
michael@0 610
michael@0 611 UDate
michael@0 612 TimeArrayTimeZoneRule::getUTC(UDate time, int32_t raw, int32_t dst) const {
michael@0 613 if (fTimeRuleType != DateTimeRule::UTC_TIME) {
michael@0 614 time -= raw;
michael@0 615 }
michael@0 616 if (fTimeRuleType == DateTimeRule::WALL_TIME) {
michael@0 617 time -= dst;
michael@0 618 }
michael@0 619 return time;
michael@0 620 }
michael@0 621
michael@0 622 U_NAMESPACE_END
michael@0 623
michael@0 624 #endif /* #if !UCONFIG_NO_FORMATTING */
michael@0 625
michael@0 626 //eof
michael@0 627

mercurial