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