2
*******************************************************************************
3
* Copyright (C) 2007-2012, International Business Machines Corporation and
4
* others. All Rights Reserved.
5
*******************************************************************************
8
#include "utypeinfo.h" // for 'typeid' to work
10
#include "unicode/utypes.h"
12
#if !UCONFIG_NO_FORMATTING
14
#include "unicode/rbtz.h"
15
#include "unicode/gregocal.h"
23
* A struct representing a time zone transition
31
static UBool compareRules(UVector* rules1, UVector* rules2) {
32
if (rules1 == NULL && rules2 == NULL) {
34
} else if (rules1 == NULL || rules2 == NULL) {
37
int32_t size = rules1->size();
38
if (size != rules2->size()) {
41
for (int32_t i = 0; i < size; i++) {
42
TimeZoneRule *r1 = (TimeZoneRule*)rules1->elementAt(i);
43
TimeZoneRule *r2 = (TimeZoneRule*)rules2->elementAt(i);
51
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RuleBasedTimeZone)
53
RuleBasedTimeZone::RuleBasedTimeZone(const UnicodeString& id, InitialTimeZoneRule* initialRule)
54
: BasicTimeZone(id), fInitialRule(initialRule), fHistoricRules(NULL), fFinalRules(NULL),
55
fHistoricTransitions(NULL), fUpToDate(FALSE) {
58
RuleBasedTimeZone::RuleBasedTimeZone(const RuleBasedTimeZone& source)
59
: BasicTimeZone(source), fInitialRule(source.fInitialRule->clone()),
60
fHistoricTransitions(NULL), fUpToDate(FALSE) {
61
fHistoricRules = copyRules(source.fHistoricRules);
62
fFinalRules = copyRules(source.fFinalRules);
63
if (source.fUpToDate) {
64
UErrorCode status = U_ZERO_ERROR;
69
RuleBasedTimeZone::~RuleBasedTimeZone() {
75
RuleBasedTimeZone::operator=(const RuleBasedTimeZone& right) {
77
BasicTimeZone::operator=(right);
79
fInitialRule = right.fInitialRule->clone();
80
fHistoricRules = copyRules(right.fHistoricRules);
81
fFinalRules = copyRules(right.fFinalRules);
89
RuleBasedTimeZone::operator==(const TimeZone& that) const {
93
if (typeid(*this) != typeid(that)
94
|| BasicTimeZone::operator==(that) == FALSE) {
97
RuleBasedTimeZone *rbtz = (RuleBasedTimeZone*)&that;
98
if (*fInitialRule != *(rbtz->fInitialRule)) {
101
if (compareRules(fHistoricRules, rbtz->fHistoricRules)
102
&& compareRules(fFinalRules, rbtz->fFinalRules)) {
109
RuleBasedTimeZone::operator!=(const TimeZone& that) const {
110
return !operator==(that);
114
RuleBasedTimeZone::addTransitionRule(TimeZoneRule* rule, UErrorCode& status) {
115
if (U_FAILURE(status)) {
118
AnnualTimeZoneRule* atzrule = dynamic_cast<AnnualTimeZoneRule*>(rule);
119
if (atzrule != NULL && atzrule->getEndYear() == AnnualTimeZoneRule::MAX_YEAR) {
121
if (fFinalRules == NULL) {
122
fFinalRules = new UVector(status);
123
if (U_FAILURE(status)) {
126
} else if (fFinalRules->size() >= 2) {
127
// Cannot handle more than two final rules
128
status = U_INVALID_STATE_ERROR;
131
fFinalRules->addElement((void*)rule, status);
134
if (fHistoricRules == NULL) {
135
fHistoricRules = new UVector(status);
136
if (U_FAILURE(status)) {
140
fHistoricRules->addElement((void*)rule, status);
142
// Mark dirty, so transitions are recalculated at next complete() call
147
RuleBasedTimeZone::complete(UErrorCode& status) {
148
if (U_FAILURE(status)) {
154
// Make sure either no final rules or a pair of AnnualTimeZoneRules
156
if (fFinalRules != NULL && fFinalRules->size() != 2) {
157
status = U_INVALID_STATE_ERROR;
162
// Create a TimezoneTransition and add to the list
163
if (fHistoricRules != NULL || fFinalRules != NULL) {
164
TimeZoneRule *curRule = fInitialRule;
165
UDate lastTransitionTime = MIN_MILLIS;
167
// Build the transition array which represents historical time zone
169
if (fHistoricRules != NULL && fHistoricRules->size() > 0) {
171
int32_t historicCount = fHistoricRules->size();
172
done = (UBool*)uprv_malloc(sizeof(UBool) * historicCount);
174
status = U_MEMORY_ALLOCATION_ERROR;
177
for (i = 0; i < historicCount; i++) {
181
int32_t curStdOffset = curRule->getRawOffset();
182
int32_t curDstSavings = curRule->getDSTSavings();
183
UDate nextTransitionTime = MAX_MILLIS;
184
TimeZoneRule *nextRule = NULL;
185
TimeZoneRule *r = NULL;
188
UnicodeString curName, name;
189
curRule->getName(curName);
191
for (i = 0; i < historicCount; i++) {
195
r = (TimeZoneRule*)fHistoricRules->elementAt(i);
196
avail = r->getNextStart(lastTransitionTime, curStdOffset, curDstSavings, false, tt);
198
// No more transitions from this rule - skip this rule next time
202
if (*r == *curRule ||
203
(name == curName && r->getRawOffset() == curRule->getRawOffset()
204
&& r->getDSTSavings() == curRule->getDSTSavings())) {
207
if (tt < nextTransitionTime) {
208
nextTransitionTime = tt;
214
if (nextRule == NULL) {
215
// Check if all historic rules are done
216
UBool bDoneAll = TRUE;
217
for (int32_t j = 0; j < historicCount; j++) {
228
if (fFinalRules != NULL) {
229
// Check if one of final rules has earlier transition date
230
for (i = 0; i < 2 /* fFinalRules->size() */; i++) {
231
TimeZoneRule *fr = (TimeZoneRule*)fFinalRules->elementAt(i);
232
if (*fr == *curRule) {
235
r = (TimeZoneRule*)fFinalRules->elementAt(i);
236
avail = r->getNextStart(lastTransitionTime, curStdOffset, curDstSavings, false, tt);
238
if (tt < nextTransitionTime) {
239
nextTransitionTime = tt;
246
if (nextRule == NULL) {
251
if (fHistoricTransitions == NULL) {
252
fHistoricTransitions = new UVector(status);
253
if (U_FAILURE(status)) {
257
Transition *trst = (Transition*)uprv_malloc(sizeof(Transition));
259
status = U_MEMORY_ALLOCATION_ERROR;
262
trst->time = nextTransitionTime;
263
trst->from = curRule;
265
fHistoricTransitions->addElement(trst, status);
266
if (U_FAILURE(status)) {
269
lastTransitionTime = nextTransitionTime;
273
if (fFinalRules != NULL) {
274
if (fHistoricTransitions == NULL) {
275
fHistoricTransitions = new UVector(status);
276
if (U_FAILURE(status)) {
280
// Append the first transition for each
281
TimeZoneRule *rule0 = (TimeZoneRule*)fFinalRules->elementAt(0);
282
TimeZoneRule *rule1 = (TimeZoneRule*)fFinalRules->elementAt(1);
284
UBool avail0 = rule0->getNextStart(lastTransitionTime, curRule->getRawOffset(), curRule->getDSTSavings(), false, tt0);
285
UBool avail1 = rule1->getNextStart(lastTransitionTime, curRule->getRawOffset(), curRule->getDSTSavings(), false, tt1);
286
if (!avail0 || !avail1) {
287
// Should not happen, because both rules are permanent
288
status = U_INVALID_STATE_ERROR;
291
Transition *final0 = (Transition*)uprv_malloc(sizeof(Transition));
292
if (final0 == NULL) {
293
status = U_MEMORY_ALLOCATION_ERROR;
296
Transition *final1 = (Transition*)uprv_malloc(sizeof(Transition));
297
if (final1 == NULL) {
299
status = U_MEMORY_ALLOCATION_ERROR;
304
final0->from = curRule;
306
rule1->getNextStart(tt0, rule0->getRawOffset(), rule0->getDSTSavings(), false, final1->time);
307
final1->from = rule0;
311
final0->from = curRule;
313
rule0->getNextStart(tt1, rule1->getRawOffset(), rule1->getDSTSavings(), false, final1->time);
314
final1->from = rule1;
317
fHistoricTransitions->addElement(final0, status);
318
if (U_FAILURE(status)) {
321
fHistoricTransitions->addElement(final1, status);
322
if (U_FAILURE(status)) {
342
RuleBasedTimeZone::clone(void) const {
343
return new RuleBasedTimeZone(*this);
347
RuleBasedTimeZone::getOffset(uint8_t era, int32_t year, int32_t month, int32_t day,
348
uint8_t dayOfWeek, int32_t millis, UErrorCode& status) const {
349
if (U_FAILURE(status)) {
352
if (month < UCAL_JANUARY || month > UCAL_DECEMBER) {
353
status = U_ILLEGAL_ARGUMENT_ERROR;
356
return getOffset(era, year, month, day, dayOfWeek, millis,
357
Grego::monthLength(year, month), status);
362
RuleBasedTimeZone::getOffset(uint8_t era, int32_t year, int32_t month, int32_t day,
363
uint8_t /*dayOfWeek*/, int32_t millis,
364
int32_t /*monthLength*/, UErrorCode& status) const {
365
// dayOfWeek and monthLength are unused
366
if (U_FAILURE(status)) {
369
if (era == GregorianCalendar::BC) {
370
// Convert to extended year
373
int32_t rawOffset, dstOffset;
374
UDate time = (UDate)Grego::fieldsToDay(year, month, day) * U_MILLIS_PER_DAY + millis;
375
getOffsetInternal(time, TRUE, kDaylight, kStandard, rawOffset, dstOffset, status);
376
if (U_FAILURE(status)) {
379
return (rawOffset + dstOffset);
383
RuleBasedTimeZone::getOffset(UDate date, UBool local, int32_t& rawOffset,
384
int32_t& dstOffset, UErrorCode& status) const {
385
getOffsetInternal(date, local, kFormer, kLatter, rawOffset, dstOffset, status);
389
RuleBasedTimeZone::getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt,
390
int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) /*const*/ {
391
getOffsetInternal(date, TRUE, nonExistingTimeOpt, duplicatedTimeOpt, rawOffset, dstOffset, status);
396
* The internal getOffset implementation
399
RuleBasedTimeZone::getOffsetInternal(UDate date, UBool local,
400
int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt,
401
int32_t& rawOffset, int32_t& dstOffset,
402
UErrorCode& status) const {
406
if (U_FAILURE(status)) {
410
// Transitions are not yet resolved. We cannot do it here
411
// because this method is const. Thus, do nothing and return
413
status = U_INVALID_STATE_ERROR;
416
const TimeZoneRule *rule = NULL;
417
if (fHistoricTransitions == NULL) {
420
UDate tstart = getTransitionTime((Transition*)fHistoricTransitions->elementAt(0),
421
local, NonExistingTimeOpt, DuplicatedTimeOpt);
425
int32_t idx = fHistoricTransitions->size() - 1;
426
UDate tend = getTransitionTime((Transition*)fHistoricTransitions->elementAt(idx),
427
local, NonExistingTimeOpt, DuplicatedTimeOpt);
429
if (fFinalRules != NULL) {
430
rule = findRuleInFinal(date, local, NonExistingTimeOpt, DuplicatedTimeOpt);
433
// no final rules or the given time is before the first transition
434
// specified by the final rules -> use the last rule
435
rule = ((Transition*)fHistoricTransitions->elementAt(idx))->to;
438
// Find a historical transition
440
if (date >= getTransitionTime((Transition*)fHistoricTransitions->elementAt(idx),
441
local, NonExistingTimeOpt, DuplicatedTimeOpt)) {
446
rule = ((Transition*)fHistoricTransitions->elementAt(idx))->to;
451
rawOffset = rule->getRawOffset();
452
dstOffset = rule->getDSTSavings();
457
RuleBasedTimeZone::setRawOffset(int32_t /*offsetMillis*/) {
458
// We don't support this operation at this moment.
463
RuleBasedTimeZone::getRawOffset(void) const {
464
// Note: This implementation returns standard GMT offset
465
// as of current time.
466
UErrorCode status = U_ZERO_ERROR;
468
getOffset(uprv_getUTCtime() * U_MILLIS_PER_SECOND,
469
FALSE, raw, dst, status);
474
RuleBasedTimeZone::useDaylightTime(void) const {
475
// Note: This implementation returns true when
476
// daylight saving time is used as of now or
477
// after the next transition.
478
UErrorCode status = U_ZERO_ERROR;
479
UDate now = uprv_getUTCtime() * U_MILLIS_PER_SECOND;
481
getOffset(now, FALSE, raw, dst, status);
485
// If DST is not used now, check if DST is used after the next transition
487
TimeZoneRule *from, *to;
488
UBool avail = findNext(now, FALSE, time, from, to);
489
if (avail && to->getDSTSavings() != 0) {
496
RuleBasedTimeZone::inDaylightTime(UDate date, UErrorCode& status) const {
497
if (U_FAILURE(status)) {
501
getOffset(date, FALSE, raw, dst, status);
509
RuleBasedTimeZone::hasSameRules(const TimeZone& other) const {
510
if (this == &other) {
513
if (typeid(*this) != typeid(other)) {
516
const RuleBasedTimeZone& that = (const RuleBasedTimeZone&)other;
517
if (*fInitialRule != *(that.fInitialRule)) {
520
if (compareRules(fHistoricRules, that.fHistoricRules)
521
&& compareRules(fFinalRules, that.fFinalRules)) {
528
RuleBasedTimeZone::getNextTransition(UDate base, UBool inclusive, TimeZoneTransition& result) /*const*/ {
529
UErrorCode status = U_ZERO_ERROR;
531
if (U_FAILURE(status)) {
534
UDate transitionTime;
535
TimeZoneRule *fromRule, *toRule;
536
UBool found = findNext(base, inclusive, transitionTime, fromRule, toRule);
538
result.setTime(transitionTime);
539
result.setFrom((const TimeZoneRule&)*fromRule);
540
result.setTo((const TimeZoneRule&)*toRule);
547
RuleBasedTimeZone::getPreviousTransition(UDate base, UBool inclusive, TimeZoneTransition& result) /*const*/ {
548
UErrorCode status = U_ZERO_ERROR;
550
if (U_FAILURE(status)) {
553
UDate transitionTime;
554
TimeZoneRule *fromRule, *toRule;
555
UBool found = findPrev(base, inclusive, transitionTime, fromRule, toRule);
557
result.setTime(transitionTime);
558
result.setFrom((const TimeZoneRule&)*fromRule);
559
result.setTo((const TimeZoneRule&)*toRule);
566
RuleBasedTimeZone::countTransitionRules(UErrorCode& /*status*/) /*const*/ {
568
if (fHistoricRules != NULL) {
569
count += fHistoricRules->size();
571
if (fFinalRules != NULL) {
572
count += fFinalRules->size();
578
RuleBasedTimeZone::getTimeZoneRules(const InitialTimeZoneRule*& initial,
579
const TimeZoneRule* trsrules[],
581
UErrorCode& status) /*const*/ {
582
if (U_FAILURE(status)) {
586
initial = fInitialRule;
591
if (fHistoricRules != NULL && cnt < trscount) {
592
int32_t historicCount = fHistoricRules->size();
594
while (cnt < trscount && idx < historicCount) {
595
trsrules[cnt++] = (const TimeZoneRule*)fHistoricRules->elementAt(idx++);
598
if (fFinalRules != NULL && cnt < trscount) {
599
int32_t finalCount = fFinalRules->size();
601
while (cnt < trscount && idx < finalCount) {
602
trsrules[cnt++] = (const TimeZoneRule*)fFinalRules->elementAt(idx++);
605
// Set the result length
610
RuleBasedTimeZone::deleteRules(void) {
613
if (fHistoricRules != NULL) {
614
while (!fHistoricRules->isEmpty()) {
615
delete (TimeZoneRule*)(fHistoricRules->orphanElementAt(0));
617
delete fHistoricRules;
618
fHistoricRules = NULL;
620
if (fFinalRules != NULL) {
621
while (!fFinalRules->isEmpty()) {
622
delete (AnnualTimeZoneRule*)(fFinalRules->orphanElementAt(0));
630
RuleBasedTimeZone::deleteTransitions(void) {
631
if (fHistoricTransitions != NULL) {
632
while (!fHistoricTransitions->isEmpty()) {
633
Transition *trs = (Transition*)fHistoricTransitions->orphanElementAt(0);
636
delete fHistoricTransitions;
638
fHistoricTransitions = NULL;
642
RuleBasedTimeZone::copyRules(UVector* source) {
643
if (source == NULL) {
646
UErrorCode ec = U_ZERO_ERROR;
647
int32_t size = source->size();
648
UVector *rules = new UVector(size, ec);
653
for (i = 0; i < size; i++) {
654
rules->addElement(((TimeZoneRule*)source->elementAt(i))->clone(), ec);
660
// In case of error, clean up
661
for (i = 0; i < rules->size(); i++) {
662
TimeZoneRule *rule = (TimeZoneRule*)rules->orphanElementAt(i);
672
RuleBasedTimeZone::findRuleInFinal(UDate date, UBool local,
673
int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt) const {
674
if (fFinalRules == NULL) {
678
AnnualTimeZoneRule* fr0 = (AnnualTimeZoneRule*)fFinalRules->elementAt(0);
679
AnnualTimeZoneRule* fr1 = (AnnualTimeZoneRule*)fFinalRules->elementAt(1);
680
if (fr0 == NULL || fr1 == NULL) {
684
UDate start0, start1;
690
localDelta = getLocalDelta(fr1->getRawOffset(), fr1->getDSTSavings(),
691
fr0->getRawOffset(), fr0->getDSTSavings(),
692
NonExistingTimeOpt, DuplicatedTimeOpt);
695
UBool avail0 = fr0->getPreviousStart(base, fr1->getRawOffset(), fr1->getDSTSavings(), TRUE, start0);
699
localDelta = getLocalDelta(fr0->getRawOffset(), fr0->getDSTSavings(),
700
fr1->getRawOffset(), fr1->getDSTSavings(),
701
NonExistingTimeOpt, DuplicatedTimeOpt);
704
UBool avail1 = fr1->getPreviousStart(base, fr0->getRawOffset(), fr0->getDSTSavings(), TRUE, start1);
706
if (!avail0 || !avail1) {
712
// Both rules take effect after the given time
716
return (start0 > start1) ? fr0 : fr1;
720
RuleBasedTimeZone::findNext(UDate base, UBool inclusive, UDate& transitionTime,
721
TimeZoneRule*& fromRule, TimeZoneRule*& toRule) const {
722
if (fHistoricTransitions == NULL) {
725
UBool isFinal = FALSE;
728
Transition *tzt = (Transition*)fHistoricTransitions->elementAt(0);
729
UDate tt = tzt->time;
730
if (tt > base || (inclusive && tt == base)) {
734
int32_t idx = fHistoricTransitions->size() - 1;
735
tzt = (Transition*)fHistoricTransitions->elementAt(idx);
737
if (inclusive && tt == base) {
740
} else if (tt <= base) {
741
if (fFinalRules != NULL) {
742
// Find a transion time with finalRules
743
TimeZoneRule *r0 = (TimeZoneRule*)fFinalRules->elementAt(0);
744
TimeZoneRule *r1 = (TimeZoneRule*)fFinalRules->elementAt(1);
745
UDate start0, start1;
746
UBool avail0 = r0->getNextStart(base, r1->getRawOffset(), r1->getDSTSavings(), inclusive, start0);
747
UBool avail1 = r1->getNextStart(base, r0->getRawOffset(), r0->getDSTSavings(), inclusive, start1);
748
// avail0/avail1 should be always TRUE
749
if (!avail0 && !avail1) {
752
if (!avail1 || start0 < start1) {
753
result.time = start0;
757
result.time = start1;
765
// Find a transition within the historic transitions
767
Transition *prev = tzt;
769
tzt = (Transition*)fHistoricTransitions->elementAt(idx);
771
if (tt < base || (!inclusive && tt == base)) {
777
result.time = prev->time;
778
result.from = prev->from;
779
result.to = prev->to;
784
// For now, this implementation ignore transitions with only zone name changes.
785
if (result.from->getRawOffset() == result.to->getRawOffset()
786
&& result.from->getDSTSavings() == result.to->getDSTSavings()) {
790
// No offset changes. Try next one if not final
791
return findNext(result.time, FALSE /* always exclusive */,
792
transitionTime, fromRule, toRule);
795
transitionTime = result.time;
796
fromRule = result.from;
804
RuleBasedTimeZone::findPrev(UDate base, UBool inclusive, UDate& transitionTime,
805
TimeZoneRule*& fromRule, TimeZoneRule*& toRule) const {
806
if (fHistoricTransitions == NULL) {
811
Transition *tzt = (Transition*)fHistoricTransitions->elementAt(0);
812
UDate tt = tzt->time;
813
if (inclusive && tt == base) {
816
} else if (tt < base) {
817
int32_t idx = fHistoricTransitions->size() - 1;
818
tzt = (Transition*)fHistoricTransitions->elementAt(idx);
820
if (inclusive && tt == base) {
823
} else if (tt < base) {
824
if (fFinalRules != NULL) {
825
// Find a transion time with finalRules
826
TimeZoneRule *r0 = (TimeZoneRule*)fFinalRules->elementAt(0);
827
TimeZoneRule *r1 = (TimeZoneRule*)fFinalRules->elementAt(1);
828
UDate start0, start1;
829
UBool avail0 = r0->getPreviousStart(base, r1->getRawOffset(), r1->getDSTSavings(), inclusive, start0);
830
UBool avail1 = r1->getPreviousStart(base, r0->getRawOffset(), r0->getDSTSavings(), inclusive, start1);
831
// avail0/avail1 should be always TRUE
832
if (!avail0 && !avail1) {
835
if (!avail1 || start0 > start1) {
836
result.time = start0;
840
result.time = start1;
849
// Find a transition within the historic transitions
852
tzt = (Transition*)fHistoricTransitions->elementAt(idx);
854
if (tt < base || (inclusive && tt == base)) {
864
// For now, this implementation ignore transitions with only zone name changes.
865
if (result.from->getRawOffset() == result.to->getRawOffset()
866
&& result.from->getDSTSavings() == result.to->getDSTSavings()) {
867
// No offset changes. Try next one if not final
868
return findPrev(result.time, FALSE /* always exclusive */,
869
transitionTime, fromRule, toRule);
871
transitionTime = result.time;
872
fromRule = result.from;
880
RuleBasedTimeZone::getTransitionTime(Transition* transition, UBool local,
881
int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt) const {
882
UDate time = transition->time;
884
time += getLocalDelta(transition->from->getRawOffset(), transition->from->getDSTSavings(),
885
transition->to->getRawOffset(), transition->to->getDSTSavings(),
886
NonExistingTimeOpt, DuplicatedTimeOpt);
892
RuleBasedTimeZone::getLocalDelta(int32_t rawBefore, int32_t dstBefore, int32_t rawAfter, int32_t dstAfter,
893
int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt) const {
896
int32_t offsetBefore = rawBefore + dstBefore;
897
int32_t offsetAfter = rawAfter + dstAfter;
899
UBool dstToStd = (dstBefore != 0) && (dstAfter == 0);
900
UBool stdToDst = (dstBefore == 0) && (dstAfter != 0);
902
if (offsetAfter - offsetBefore >= 0) {
903
// Positive transition, which makes a non-existing local time range
904
if (((NonExistingTimeOpt & kStdDstMask) == kStandard && dstToStd)
905
|| ((NonExistingTimeOpt & kStdDstMask) == kDaylight && stdToDst)) {
906
delta = offsetBefore;
907
} else if (((NonExistingTimeOpt & kStdDstMask) == kStandard && stdToDst)
908
|| ((NonExistingTimeOpt & kStdDstMask) == kDaylight && dstToStd)) {
910
} else if ((NonExistingTimeOpt & kFormerLatterMask) == kLatter) {
911
delta = offsetBefore;
913
// Interprets the time with rule before the transition,
914
// default for non-existing time range
918
// Negative transition, which makes a duplicated local time range
919
if (((DuplicatedTimeOpt & kStdDstMask) == kStandard && dstToStd)
920
|| ((DuplicatedTimeOpt & kStdDstMask) == kDaylight && stdToDst)) {
922
} else if (((DuplicatedTimeOpt & kStdDstMask) == kStandard && stdToDst)
923
|| ((DuplicatedTimeOpt & kStdDstMask) == kDaylight && dstToStd)) {
924
delta = offsetBefore;
925
} else if ((DuplicatedTimeOpt & kFormerLatterMask) == kFormer) {
926
delta = offsetBefore;
928
// Interprets the time with rule after the transition,
929
// default for duplicated local time range
938
#endif /* #if !UCONFIG_NO_FORMATTING */