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