• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 *******************************************************************************
3 * Copyright (C) 2007-2012, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 *******************************************************************************
6 */
7 
8 #include "utypeinfo.h"  // for 'typeid' to work
9 
10 #include "unicode/utypes.h"
11 
12 #if !UCONFIG_NO_FORMATTING
13 
14 #include "unicode/tzrule.h"
15 #include "unicode/ucal.h"
16 #include "gregoimp.h"
17 #include "cmemory.h"
18 #include "uarrsort.h"
19 
20 U_CDECL_BEGIN
21 // UComparator function for sorting start times
22 static int32_t U_CALLCONV
compareDates(const void *,const void * left,const void * right)23 compareDates(const void * /*context*/, const void *left, const void *right) {
24     UDate l = *((UDate*)left);
25     UDate r = *((UDate*)right);
26     int32_t res = l < r ? -1 : (l == r ? 0 : 1);
27     return res;
28 }
29 U_CDECL_END
30 
31 U_NAMESPACE_BEGIN
32 
TimeZoneRule(const UnicodeString & name,int32_t rawOffset,int32_t dstSavings)33 TimeZoneRule::TimeZoneRule(const UnicodeString& name, int32_t rawOffset, int32_t dstSavings)
34 : UObject(), fName(name), fRawOffset(rawOffset), fDSTSavings(dstSavings) {
35 }
36 
TimeZoneRule(const TimeZoneRule & source)37 TimeZoneRule::TimeZoneRule(const TimeZoneRule& source)
38 : UObject(source), fName(source.fName), fRawOffset(source.fRawOffset), fDSTSavings(source.fDSTSavings) {
39 }
40 
~TimeZoneRule()41 TimeZoneRule::~TimeZoneRule() {
42 }
43 
44 TimeZoneRule&
operator =(const TimeZoneRule & right)45 TimeZoneRule::operator=(const TimeZoneRule& right) {
46     if (this != &right) {
47         fName = right.fName;
48         fRawOffset = right.fRawOffset;
49         fDSTSavings = right.fDSTSavings;
50     }
51     return *this;
52 }
53 
54 UBool
operator ==(const TimeZoneRule & that) const55 TimeZoneRule::operator==(const TimeZoneRule& that) const {
56     return ((this == &that) ||
57             (typeid(*this) == typeid(that) &&
58             fName == that.fName &&
59             fRawOffset == that.fRawOffset &&
60             fDSTSavings == that.fDSTSavings));
61 }
62 
63 UBool
operator !=(const TimeZoneRule & that) const64 TimeZoneRule::operator!=(const TimeZoneRule& that) const {
65     return !operator==(that);
66 }
67 
68 UnicodeString&
getName(UnicodeString & name) const69 TimeZoneRule::getName(UnicodeString& name) const {
70     name = fName;
71     return name;
72 }
73 
74 int32_t
getRawOffset(void) const75 TimeZoneRule::getRawOffset(void) const {
76     return fRawOffset;
77 }
78 
79 int32_t
getDSTSavings(void) const80 TimeZoneRule::getDSTSavings(void) const {
81     return fDSTSavings;
82 }
83 
84 UBool
isEquivalentTo(const TimeZoneRule & other) const85 TimeZoneRule::isEquivalentTo(const TimeZoneRule& other) const {
86     return ((this == &other) ||
87             (typeid(*this) == typeid(other) &&
88             fRawOffset == other.fRawOffset &&
89             fDSTSavings == other.fDSTSavings));
90 }
91 
92 
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(InitialTimeZoneRule)93 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(InitialTimeZoneRule)
94 
95 InitialTimeZoneRule::InitialTimeZoneRule(const UnicodeString& name,
96                                          int32_t rawOffset,
97                                          int32_t dstSavings)
98 : TimeZoneRule(name, rawOffset, dstSavings) {
99 }
100 
InitialTimeZoneRule(const InitialTimeZoneRule & source)101 InitialTimeZoneRule::InitialTimeZoneRule(const InitialTimeZoneRule& source)
102 : TimeZoneRule(source) {
103 }
104 
~InitialTimeZoneRule()105 InitialTimeZoneRule::~InitialTimeZoneRule() {
106 }
107 
108 InitialTimeZoneRule*
clone(void) const109 InitialTimeZoneRule::clone(void) const {
110     return new InitialTimeZoneRule(*this);
111 }
112 
113 InitialTimeZoneRule&
operator =(const InitialTimeZoneRule & right)114 InitialTimeZoneRule::operator=(const InitialTimeZoneRule& right) {
115     if (this != &right) {
116         TimeZoneRule::operator=(right);
117     }
118     return *this;
119 }
120 
121 UBool
operator ==(const TimeZoneRule & that) const122 InitialTimeZoneRule::operator==(const TimeZoneRule& that) const {
123     return ((this == &that) ||
124             (typeid(*this) == typeid(that) &&
125             TimeZoneRule::operator==(that)));
126 }
127 
128 UBool
operator !=(const TimeZoneRule & that) const129 InitialTimeZoneRule::operator!=(const TimeZoneRule& that) const {
130     return !operator==(that);
131 }
132 
133 UBool
isEquivalentTo(const TimeZoneRule & other) const134 InitialTimeZoneRule::isEquivalentTo(const TimeZoneRule& other) const {
135     if (this == &other) {
136         return TRUE;
137     }
138     if (typeid(*this) != typeid(other) || TimeZoneRule::isEquivalentTo(other) == FALSE) {
139         return FALSE;
140     }
141     return TRUE;
142 }
143 
144 UBool
getFirstStart(int32_t,int32_t,UDate &) const145 InitialTimeZoneRule::getFirstStart(int32_t /*prevRawOffset*/,
146                                   int32_t /*prevDSTSavings*/,
147                                   UDate& /*result*/) const {
148     return FALSE;
149 }
150 
151 UBool
getFinalStart(int32_t,int32_t,UDate &) const152 InitialTimeZoneRule::getFinalStart(int32_t /*prevRawOffset*/,
153                                   int32_t /*prevDSTSavings*/,
154                                   UDate& /*result*/) const {
155     return FALSE;
156 }
157 
158 UBool
getNextStart(UDate,int32_t,int32_t,UBool,UDate &) const159 InitialTimeZoneRule::getNextStart(UDate /*base*/,
160                                  int32_t /*prevRawOffset*/,
161                                  int32_t /*prevDSTSavings*/,
162                                  UBool /*inclusive*/,
163                                  UDate& /*result*/) const {
164     return FALSE;
165 }
166 
167 UBool
getPreviousStart(UDate,int32_t,int32_t,UBool,UDate &) const168 InitialTimeZoneRule::getPreviousStart(UDate /*base*/,
169                                      int32_t /*prevRawOffset*/,
170                                      int32_t /*prevDSTSavings*/,
171                                      UBool /*inclusive*/,
172                                      UDate& /*result*/) const {
173     return FALSE;
174 }
175 
176 
177 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(AnnualTimeZoneRule)
178 
179 const int32_t AnnualTimeZoneRule::MAX_YEAR = 0x7FFFFFFF; /* max signed int32 */
180 
AnnualTimeZoneRule(const UnicodeString & name,int32_t rawOffset,int32_t dstSavings,const DateTimeRule & dateTimeRule,int32_t startYear,int32_t endYear)181 AnnualTimeZoneRule::AnnualTimeZoneRule(const UnicodeString& name,
182                                        int32_t rawOffset,
183                                        int32_t dstSavings,
184                                        const DateTimeRule& dateTimeRule,
185                                        int32_t startYear,
186                                        int32_t endYear)
187 : TimeZoneRule(name, rawOffset, dstSavings), fDateTimeRule(new DateTimeRule(dateTimeRule)),
188   fStartYear(startYear), fEndYear(endYear) {
189 }
190 
AnnualTimeZoneRule(const UnicodeString & name,int32_t rawOffset,int32_t dstSavings,DateTimeRule * dateTimeRule,int32_t startYear,int32_t endYear)191 AnnualTimeZoneRule::AnnualTimeZoneRule(const UnicodeString& name,
192                                        int32_t rawOffset,
193                                        int32_t dstSavings,
194                                        DateTimeRule* dateTimeRule,
195                                        int32_t startYear,
196                                        int32_t endYear)
197 : TimeZoneRule(name, rawOffset, dstSavings), fDateTimeRule(dateTimeRule),
198   fStartYear(startYear), fEndYear(endYear) {
199 }
200 
AnnualTimeZoneRule(const AnnualTimeZoneRule & source)201 AnnualTimeZoneRule::AnnualTimeZoneRule(const AnnualTimeZoneRule& source)
202 : TimeZoneRule(source), fDateTimeRule(new DateTimeRule(*(source.fDateTimeRule))),
203   fStartYear(source.fStartYear), fEndYear(source.fEndYear) {
204 }
205 
~AnnualTimeZoneRule()206 AnnualTimeZoneRule::~AnnualTimeZoneRule() {
207     delete fDateTimeRule;
208 }
209 
210 AnnualTimeZoneRule*
clone(void) const211 AnnualTimeZoneRule::clone(void) const {
212     return new AnnualTimeZoneRule(*this);
213 }
214 
215 AnnualTimeZoneRule&
operator =(const AnnualTimeZoneRule & right)216 AnnualTimeZoneRule::operator=(const AnnualTimeZoneRule& right) {
217     if (this != &right) {
218         TimeZoneRule::operator=(right);
219         delete fDateTimeRule;
220         fDateTimeRule = right.fDateTimeRule->clone();
221         fStartYear = right.fStartYear;
222         fEndYear = right.fEndYear;
223     }
224     return *this;
225 }
226 
227 UBool
operator ==(const TimeZoneRule & that) const228 AnnualTimeZoneRule::operator==(const TimeZoneRule& that) const {
229     if (this == &that) {
230         return TRUE;
231     }
232     if (typeid(*this) != typeid(that)) {
233         return FALSE;
234     }
235     AnnualTimeZoneRule *atzr = (AnnualTimeZoneRule*)&that;
236     return (*fDateTimeRule == *(atzr->fDateTimeRule) &&
237             fStartYear == atzr->fStartYear &&
238             fEndYear == atzr->fEndYear);
239 }
240 
241 UBool
operator !=(const TimeZoneRule & that) const242 AnnualTimeZoneRule::operator!=(const TimeZoneRule& that) const {
243     return !operator==(that);
244 }
245 
246 const DateTimeRule*
getRule() const247 AnnualTimeZoneRule::getRule() const {
248     return fDateTimeRule;
249 }
250 
251 int32_t
getStartYear() const252 AnnualTimeZoneRule::getStartYear() const {
253     return fStartYear;
254 }
255 
256 int32_t
getEndYear() const257 AnnualTimeZoneRule::getEndYear() const {
258     return fEndYear;
259 }
260 
261 UBool
getStartInYear(int32_t year,int32_t prevRawOffset,int32_t prevDSTSavings,UDate & result) const262 AnnualTimeZoneRule::getStartInYear(int32_t year,
263                                    int32_t prevRawOffset,
264                                    int32_t prevDSTSavings,
265                                    UDate &result) const {
266     if (year < fStartYear || year > fEndYear) {
267         return FALSE;
268     }
269     double ruleDay;
270     DateTimeRule::DateRuleType type = fDateTimeRule->getDateRuleType();
271     if (type == DateTimeRule::DOM) {
272         ruleDay = Grego::fieldsToDay(year, fDateTimeRule->getRuleMonth(), fDateTimeRule->getRuleDayOfMonth());
273     } else {
274         UBool after = TRUE;
275         if (type == DateTimeRule::DOW) {
276             // Normalize DOW rule into DOW_GEQ_DOM or DOW_LEQ_DOM
277             int32_t weeks = fDateTimeRule->getRuleWeekInMonth();
278             if (weeks > 0) {
279                 ruleDay = Grego::fieldsToDay(year, fDateTimeRule->getRuleMonth(), 1);
280                 ruleDay += 7 * (weeks - 1);
281             } else {
282                 after = FALSE;
283                 ruleDay = Grego::fieldsToDay(year, fDateTimeRule->getRuleMonth(),
284                     Grego::monthLength(year, fDateTimeRule->getRuleMonth()));
285                 ruleDay += 7 * (weeks + 1);
286            }
287         } else {
288             int32_t month = fDateTimeRule->getRuleMonth();
289             int32_t dom = fDateTimeRule->getRuleDayOfMonth();
290             if (type == DateTimeRule::DOW_LEQ_DOM) {
291                 after = FALSE;
292                 // Handle Feb <=29
293                 if (month == UCAL_FEBRUARY && dom == 29 && !Grego::isLeapYear(year)) {
294                     dom--;
295                 }
296             }
297             ruleDay = Grego::fieldsToDay(year, month, dom);
298         }
299         int32_t dow = Grego::dayOfWeek(ruleDay);
300         int32_t delta = fDateTimeRule->getRuleDayOfWeek() - dow;
301         if (after) {
302             delta = delta < 0 ? delta + 7 : delta;
303         } else {
304             delta = delta > 0 ? delta - 7 : delta;
305         }
306         ruleDay += delta;
307     }
308 
309     result = ruleDay*U_MILLIS_PER_DAY + fDateTimeRule->getRuleMillisInDay();
310     if (fDateTimeRule->getTimeRuleType() != DateTimeRule::UTC_TIME) {
311         result -= prevRawOffset;
312     }
313     if (fDateTimeRule->getTimeRuleType() == DateTimeRule::WALL_TIME) {
314         result -= prevDSTSavings;
315     }
316     return TRUE;
317 }
318 
319 UBool
isEquivalentTo(const TimeZoneRule & other) const320 AnnualTimeZoneRule::isEquivalentTo(const TimeZoneRule& other) const {
321     if (this == &other) {
322         return TRUE;
323     }
324     if (typeid(*this) != typeid(other) || 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(UDate base,int32_t prevRawOffset,int32_t prevDSTSavings,UBool inclusive,UDate & result) const351 AnnualTimeZoneRule::getNextStart(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(UDate base,int32_t prevRawOffset,int32_t prevDSTSavings,UBool inclusive,UDate & result) const375 AnnualTimeZoneRule::getPreviousStart(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 (typeid(*this) != typeid(that) || TimeZoneRule::operator==(that) == FALSE) {
452         return FALSE;
453     }
454     TimeArrayTimeZoneRule *tatzr = (TimeArrayTimeZoneRule*)&that;
455     if (fTimeRuleType != tatzr->fTimeRuleType ||
456         fNumStartTimes != tatzr->fNumStartTimes) {
457         return FALSE;
458     }
459     // Compare start times
460     UBool res = TRUE;
461     for (int32_t i = 0; i < fNumStartTimes; i++) {
462         if (fStartTimes[i] != tatzr->fStartTimes[i]) {
463             res = FALSE;
464             break;
465         }
466     }
467     return res;
468 }
469 
470 UBool
operator !=(const TimeZoneRule & that) const471 TimeArrayTimeZoneRule::operator!=(const TimeZoneRule& that) const {
472     return !operator==(that);
473 }
474 
475 DateTimeRule::TimeRuleType
getTimeType(void) const476 TimeArrayTimeZoneRule::getTimeType(void) const {
477     return fTimeRuleType;
478 }
479 
480 UBool
getStartTimeAt(int32_t index,UDate & result) const481 TimeArrayTimeZoneRule::getStartTimeAt(int32_t index, UDate& result) const {
482     if (index >= fNumStartTimes || index < 0) {
483         return FALSE;
484     }
485     result = fStartTimes[index];
486     return TRUE;
487 }
488 
489 int32_t
countStartTimes(void) const490 TimeArrayTimeZoneRule::countStartTimes(void) const {
491     return fNumStartTimes;
492 }
493 
494 UBool
isEquivalentTo(const TimeZoneRule & other) const495 TimeArrayTimeZoneRule::isEquivalentTo(const TimeZoneRule& other) const {
496     if (this == &other) {
497         return TRUE;
498     }
499     if (typeid(*this) != typeid(other) || TimeZoneRule::isEquivalentTo(other) == FALSE) {
500         return FALSE;
501     }
502     TimeArrayTimeZoneRule* that = (TimeArrayTimeZoneRule*)&other;
503     if (fTimeRuleType != that->fTimeRuleType ||
504         fNumStartTimes != that->fNumStartTimes) {
505         return FALSE;
506     }
507     // Compare start times
508     UBool res = TRUE;
509     for (int32_t i = 0; i < fNumStartTimes; i++) {
510         if (fStartTimes[i] != that->fStartTimes[i]) {
511             res = FALSE;
512             break;
513         }
514     }
515     return res;
516 }
517 
518 UBool
getFirstStart(int32_t prevRawOffset,int32_t prevDSTSavings,UDate & result) const519 TimeArrayTimeZoneRule::getFirstStart(int32_t prevRawOffset,
520                                              int32_t prevDSTSavings,
521                                              UDate& result) const {
522     if (fNumStartTimes <= 0 || fStartTimes == NULL) {
523         return FALSE;
524     }
525     result = getUTC(fStartTimes[0], prevRawOffset, prevDSTSavings);
526     return TRUE;
527 }
528 
529 UBool
getFinalStart(int32_t prevRawOffset,int32_t prevDSTSavings,UDate & result) const530 TimeArrayTimeZoneRule::getFinalStart(int32_t prevRawOffset,
531                                      int32_t prevDSTSavings,
532                                      UDate& result) const {
533     if (fNumStartTimes <= 0 || fStartTimes == NULL) {
534         return FALSE;
535     }
536     result = getUTC(fStartTimes[fNumStartTimes - 1], prevRawOffset, prevDSTSavings);
537     return TRUE;
538 }
539 
540 UBool
getNextStart(UDate base,int32_t prevRawOffset,int32_t prevDSTSavings,UBool inclusive,UDate & result) const541 TimeArrayTimeZoneRule::getNextStart(UDate base,
542                                     int32_t prevRawOffset,
543                                     int32_t prevDSTSavings,
544                                     UBool inclusive,
545                                     UDate& result) const {
546     int32_t i = fNumStartTimes - 1;
547     for (; i >= 0; i--) {
548         UDate time = getUTC(fStartTimes[i], prevRawOffset, prevDSTSavings);
549         if (time < base || (!inclusive && time == base)) {
550             break;
551         }
552         result = time;
553     }
554     if (i == fNumStartTimes - 1) {
555         return FALSE;
556     }
557     return TRUE;
558 }
559 
560 UBool
getPreviousStart(UDate base,int32_t prevRawOffset,int32_t prevDSTSavings,UBool inclusive,UDate & result) const561 TimeArrayTimeZoneRule::getPreviousStart(UDate base,
562                                         int32_t prevRawOffset,
563                                         int32_t prevDSTSavings,
564                                         UBool inclusive,
565                                         UDate& result) const {
566     int32_t i = fNumStartTimes - 1;
567     for (; i >= 0; i--) {
568         UDate time = getUTC(fStartTimes[i], prevRawOffset, prevDSTSavings);
569         if (time < base || (inclusive && time == base)) {
570             result = time;
571             return TRUE;
572         }
573     }
574     return FALSE;
575 }
576 
577 
578 // ---- private methods ------
579 
580 UBool
initStartTimes(const UDate source[],int32_t size,UErrorCode & status)581 TimeArrayTimeZoneRule::initStartTimes(const UDate source[], int32_t size, UErrorCode& status) {
582     // Free old array
583     if (fStartTimes != NULL && fStartTimes != fLocalStartTimes) {
584         uprv_free(fStartTimes);
585     }
586     // Allocate new one if needed
587     if (size > TIMEARRAY_STACK_BUFFER_SIZE) {
588         fStartTimes = (UDate*)uprv_malloc(sizeof(UDate)*size);
589         if (fStartTimes == NULL) {
590             status = U_MEMORY_ALLOCATION_ERROR;
591             fNumStartTimes = 0;
592             return FALSE;
593         }
594     } else {
595         fStartTimes = (UDate*)fLocalStartTimes;
596     }
597     uprv_memcpy(fStartTimes, source, sizeof(UDate)*size);
598     fNumStartTimes = size;
599     // Sort dates
600     uprv_sortArray(fStartTimes, fNumStartTimes, (int32_t)sizeof(UDate), compareDates, NULL, TRUE, &status);
601     if (U_FAILURE(status)) {
602         if (fStartTimes != NULL && fStartTimes != fLocalStartTimes) {
603             uprv_free(fStartTimes);
604         }
605         fNumStartTimes = 0;
606         return FALSE;
607     }
608     return TRUE;
609 }
610 
611 UDate
getUTC(UDate time,int32_t raw,int32_t dst) const612 TimeArrayTimeZoneRule::getUTC(UDate time, int32_t raw, int32_t dst) const {
613     if (fTimeRuleType != DateTimeRule::UTC_TIME) {
614         time -= raw;
615     }
616     if (fTimeRuleType == DateTimeRule::WALL_TIME) {
617         time -= dst;
618     }
619     return time;
620 }
621 
622 U_NAMESPACE_END
623 
624 #endif /* #if !UCONFIG_NO_FORMATTING */
625 
626 //eof
627 
628