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