/*
*******************************************************************************
-* Copyright (C) 2007-2008, International Business Machines Corporation and *
-* others. All Rights Reserved. *
+* Copyright (C) 2007-2010, International Business Machines Corporation and
+* others. All Rights Reserved.
*******************************************************************************
*/
if (ignoreDstAmount) {
// Skip a transition which only differ the amount of DST savings
- if (avail1
- && (tr1.getFrom()->getRawOffset() + tr1.getFrom()->getDSTSavings()
- == tr1.getTo()->getRawOffset() + tr1.getTo()->getDSTSavings())
- && (tr1.getFrom()->getDSTSavings() != 0 && tr1.getTo()->getDSTSavings() != 0)) {
- getNextTransition(tr1.getTime(), FALSE, tr1);
+ while (TRUE) {
+ if (avail1
+ && tr1.getTime() <= end
+ && (tr1.getFrom()->getRawOffset() + tr1.getFrom()->getDSTSavings()
+ == tr1.getTo()->getRawOffset() + tr1.getTo()->getDSTSavings())
+ && (tr1.getFrom()->getDSTSavings() != 0 && tr1.getTo()->getDSTSavings() != 0)) {
+ getNextTransition(tr1.getTime(), FALSE, tr1);
+ } else {
+ break;
+ }
}
- if (avail2
- && (tr2.getFrom()->getRawOffset() + tr2.getFrom()->getDSTSavings()
- == tr2.getTo()->getRawOffset() + tr2.getTo()->getDSTSavings())
- && (tr2.getFrom()->getDSTSavings() != 0 && tr2.getTo()->getDSTSavings() != 0)) {
- getNextTransition(tr2.getTime(), FALSE, tr2);
+ while (TRUE) {
+ if (avail2
+ && tr2.getTime() <= end
+ && (tr2.getFrom()->getRawOffset() + tr2.getFrom()->getDSTSavings()
+ == tr2.getTo()->getRawOffset() + tr2.getTo()->getDSTSavings())
+ && (tr2.getFrom()->getDSTSavings() != 0 && tr2.getTo()->getDSTSavings() != 0)) {
+ tz.getNextTransition(tr2.getTime(), FALSE, tr2);
+ } else {
+ break;
+ }
}
}
if (ignoreDstAmount) {
if (tr1.getTo()->getRawOffset() + tr1.getTo()->getDSTSavings()
!= tr2.getTo()->getRawOffset() + tr2.getTo()->getDSTSavings()
- || tr1.getTo()->getDSTSavings() != 0 && tr2.getTo()->getDSTSavings() == 0
- || tr1.getTo()->getDSTSavings() == 0 && tr2.getTo()->getDSTSavings() != 0) {
+ || (tr1.getTo()->getDSTSavings() != 0 && tr2.getTo()->getDSTSavings() == 0)
+ || (tr1.getTo()->getDSTSavings() == 0 && tr2.getTo()->getDSTSavings() != 0)) {
return FALSE;
}
} else {
// Create DOW rule
DateTimeRule *dtr = new DateTimeRule(month, weekInMonth, dow, mid, DateTimeRule::WALL_TIME);
tr.getTo()->getName(name);
- ar1 = new AnnualTimeZoneRule(name, tr.getTo()->getRawOffset(), tr.getTo()->getDSTSavings(),
+
+ // Note: SimpleTimeZone does not support raw offset change.
+ // So we always use raw offset of the given time for the rule,
+ // even raw offset is changed. This will result that the result
+ // zone to return wrong offset after the transition.
+ // When we encounter such case, we do not inspect next next
+ // transition for another rule.
+ ar1 = new AnnualTimeZoneRule(name, initialRaw, tr.getTo()->getDSTSavings(),
dtr, year, AnnualTimeZoneRule::MAX_YEAR);
- // Get the next next transition
- avail = getNextTransition(nextTransitionTime, FALSE, tr);
- if (avail) {
- // Check if the next next transition is either DST->STD or STD->DST
- // and within roughly 1 year from the next transition
- if (((tr.getFrom()->getDSTSavings() == 0 && tr.getTo()->getDSTSavings() != 0)
- || (tr.getFrom()->getDSTSavings() != 0 && tr.getTo()->getDSTSavings() == 0))
- && nextTransitionTime + MILLIS_PER_YEAR > tr.getTime()) {
-
- // Get local wall time for the next transition time
- Grego::timeToFields(tr.getTime() + tr.getFrom()->getRawOffset() + tr.getFrom()->getDSTSavings(),
- year, month, dom, dow, doy, mid);
- weekInMonth = Grego::dayOfWeekInMonth(year, month, dom);
- // Generate another DOW rule
- dtr = new DateTimeRule(month, weekInMonth, dow, mid, DateTimeRule::WALL_TIME);
- tr.getTo()->getName(name);
- ar2 = new AnnualTimeZoneRule(name, tr.getTo()->getRawOffset(), tr.getTo()->getDSTSavings(),
- dtr, year - 1, AnnualTimeZoneRule::MAX_YEAR);
-
- // Make sure this rule can be applied to the specified date
- avail = ar2->getPreviousStart(date, tr.getFrom()->getRawOffset(), tr.getFrom()->getDSTSavings(), TRUE, d);
- if (!avail || d > date
- || initialRaw != tr.getTo()->getRawOffset()
- || initialDst != tr.getTo()->getDSTSavings()) {
- // We cannot use this rule as the second transition rule
- delete ar2;
- ar2 = NULL;
+ if (tr.getTo()->getRawOffset() == initialRaw) {
+ // Get the next next transition
+ avail = getNextTransition(nextTransitionTime, FALSE, tr);
+ if (avail) {
+ // Check if the next next transition is either DST->STD or STD->DST
+ // and within roughly 1 year from the next transition
+ if (((tr.getFrom()->getDSTSavings() == 0 && tr.getTo()->getDSTSavings() != 0)
+ || (tr.getFrom()->getDSTSavings() != 0 && tr.getTo()->getDSTSavings() == 0))
+ && nextTransitionTime + MILLIS_PER_YEAR > tr.getTime()) {
+
+ // Get local wall time for the next transition time
+ Grego::timeToFields(tr.getTime() + tr.getFrom()->getRawOffset() + tr.getFrom()->getDSTSavings(),
+ year, month, dom, dow, doy, mid);
+ weekInMonth = Grego::dayOfWeekInMonth(year, month, dom);
+ // Generate another DOW rule
+ dtr = new DateTimeRule(month, weekInMonth, dow, mid, DateTimeRule::WALL_TIME);
+ tr.getTo()->getName(name);
+ ar2 = new AnnualTimeZoneRule(name, tr.getTo()->getRawOffset(), tr.getTo()->getDSTSavings(),
+ dtr, year - 1, AnnualTimeZoneRule::MAX_YEAR);
+
+ // Make sure this rule can be applied to the specified date
+ avail = ar2->getPreviousStart(date, tr.getFrom()->getRawOffset(), tr.getFrom()->getDSTSavings(), TRUE, d);
+ if (!avail || d > date
+ || initialRaw != tr.getTo()->getRawOffset()
+ || initialDst != tr.getTo()->getDSTSavings()) {
+ // We cannot use this rule as the second transition rule
+ delete ar2;
+ ar2 = NULL;
+ }
}
}
}
weekInMonth = Grego::dayOfWeekInMonth(year, month, dom);
dtr = new DateTimeRule(month, weekInMonth, dow, mid, DateTimeRule::WALL_TIME);
tr.getTo()->getName(name);
- ar2 = new AnnualTimeZoneRule(name, tr.getTo()->getRawOffset(), tr.getTo()->getDSTSavings(),
+
+ // second rule raw/dst offsets should match raw/dst offsets
+ // at the given time
+ ar2 = new AnnualTimeZoneRule(name, initialRaw, initialDst,
dtr, ar1->getStartYear() - 1, AnnualTimeZoneRule::MAX_YEAR);
// Check if this rule start after the first rule after the specified date
if (!avail) {
break;
}
- time = tzt.getTime();
+ UDate updatedTime = tzt.getTime();
+ if (updatedTime == time) {
+ // Can get here if rules for start & end of daylight time have exactly
+ // the same time.
+ // TODO: fix getNextTransition() to prevent it?
+ status = U_INVALID_STATE_ERROR;
+ goto error;
+ }
+ time = updatedTime;
const TimeZoneRule *toRule = tzt.getTo();
for (i = 0; i < ruleCount; i++) {
if (done[i]) {
continue;
}
- if (toRule->getDynamicClassID() == TimeArrayTimeZoneRule::getStaticClassID()) {
- TimeArrayTimeZoneRule *tar = (TimeArrayTimeZoneRule*)toRule;
-
+ const TimeArrayTimeZoneRule *tar = dynamic_cast<const TimeArrayTimeZoneRule *>(toRule);
+ const AnnualTimeZoneRule *ar;
+ if (tar != NULL) {
// Get the previous raw offset and DST savings before the very first start time
TimeZoneTransition tzt0;
t = start;
}
}
}
- } else if (toRule->getDynamicClassID() == AnnualTimeZoneRule::getStaticClassID()) {
- AnnualTimeZoneRule *ar = (AnnualTimeZoneRule*)toRule;
+ } else if ((ar = dynamic_cast<const AnnualTimeZoneRule *>(toRule)) != NULL) {
ar->getFirstStart(tzt.getFrom()->getRawOffset(), tzt.getFrom()->getDSTSavings(), firstStart);
if (firstStart == tzt.getTime()) {
// Just add the rule as is
delete orgRules;
}
if (done != NULL) {
+ if (filteredRules != NULL) {
+ while (!filteredRules->isEmpty()) {
+ r = (TimeZoneRule*)filteredRules->orphanElementAt(0);
+ delete r;
+ }
+ delete filteredRules;
+ }
+ delete res_initial;
uprv_free(done);
}
}
void
-BasicTimeZone::getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt,
- int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) /*const*/ {
+BasicTimeZone::getOffsetFromLocal(UDate /*date*/, int32_t /*nonExistingTimeOpt*/, int32_t /*duplicatedTimeOpt*/,
+ int32_t& /*rawOffset*/, int32_t& /*dstOffset*/, UErrorCode& status) /*const*/ {
if (U_FAILURE(status)) {
return;
}