UBool avail;
TimeZoneTransition tr; // Get the next transition
avail = getNextTransition(date, false, tr); if (avail) {
tr.getFrom()->getName(initialName);
initialRaw = tr.getFrom()->getRawOffset();
initialDst = tr.getFrom()->getDSTSavings();
// Check if the next transition is either DST->STD or STD->DST and // within roughly 1 year from the specified date
UDate nextTransitionTime = tr.getTime(); if (((tr.getFrom()->getDSTSavings() == 0 && tr.getTo()->getDSTSavings() != 0)
|| (tr.getFrom()->getDSTSavings() != 0 && tr.getTo()->getDSTSavings() == 0))
&& (date + MILLIS_PER_YEAR > nextTransitionTime)) {
int32_t year, month, dom, dow, doy, mid;
UDate d;
// Get local wall time for the next transition time
Grego::timeToFields(nextTransitionTime + initialRaw + initialDst,
year, month, dom, dow, doy, mid, status); if (U_FAILURE(status)) return;
int32_t weekInMonth = Grego::dayOfWeekInMonth(year, month, dom); // Create DOW rule
DateTimeRule *dtr = new DateTimeRule(month, weekInMonth, dow, mid, DateTimeRule::WALL_TIME);
tr.getTo()->getName(name);
// 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);
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, status); if (U_FAILURE(status)) return;
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 = nullptr;
}
}
}
} if (ar2 == nullptr) { // Try previous transition
avail = getPreviousTransition(date, true, tr); if (avail) { // Check if the previous transition is either DST->STD or STD->DST. // The actual transition time does not matter here. if ((tr.getFrom()->getDSTSavings() == 0 && tr.getTo()->getDSTSavings() != 0)
|| (tr.getFrom()->getDSTSavings() != 0 && tr.getTo()->getDSTSavings() == 0)) {
// 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
avail = ar2->getNextStart(date, tr.getFrom()->getRawOffset(), tr.getFrom()->getDSTSavings(), false, d); if (!avail || d <= nextTransitionTime) { // We cannot use this rule as the second transition rule delete ar2;
ar2 = nullptr;
}
}
}
} if (ar2 == nullptr) { // Cannot find a good pair of AnnualTimeZoneRule delete ar1;
ar1 = nullptr;
} else { // The initial rule should represent the rule before the previous transition
ar1->getName(initialName);
initialRaw = ar1->getRawOffset();
initialDst = ar1->getDSTSavings();
}
}
} else { // Try the previous one
avail = getPreviousTransition(date, true, tr); if (avail) {
tr.getTo()->getName(initialName);
initialRaw = tr.getTo()->getRawOffset();
initialDst = tr.getTo()->getDSTSavings();
} else { // No transitions in the past. Just use the current offsets
getOffset(date, false, initialRaw, initialDst, status); if (U_FAILURE(status)) { return;
}
}
} // Set the initial rule
initial = new InitialTimeZoneRule(initialName, initialRaw, initialDst);
// Set the standard and daylight saving rules if (ar1 != nullptr && ar2 != nullptr) { if (ar1->getDSTSavings() != 0) {
dst = ar1;
std = ar2;
} else {
std = ar1;
dst = ar2;
}
}
}
// Original transition rules
ruleCount = countTransitionRules(status); if (U_FAILURE(status)) { return;
}
LocalPointer<UVector> orgRules( new UVector(uprv_deleteUObject, nullptr, ruleCount, status), status); if (U_FAILURE(status)) { return;
}
LocalMemory<const TimeZoneRule *> orgtrs( static_cast<const TimeZoneRule **>(uprv_malloc(sizeof(TimeZoneRule*)*ruleCount))); if (orgtrs.isNull()) {
status = U_MEMORY_ALLOCATION_ERROR; return;
}
getTimeZoneRules(orgini, &orgtrs[0], ruleCount, status); if (U_FAILURE(status)) { return;
} for (i = 0; i < ruleCount; i++) {
LocalPointer<TimeZoneRule> lpRule(orgtrs[i]->clone(), status);
orgRules->adoptElement(lpRule.orphan(), status); if (U_FAILURE(status)) { return;
}
}
avail = getPreviousTransition(start, true, tzt); if (!avail) { // No need to filter out rules only applicable to time before the start
initial = orgini->clone(); if (initial == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR; return;
}
transitionRules = orgRules.orphan(); return;
}
LocalMemory<bool> done(static_cast<bool *>(uprv_malloc(sizeof(bool)*ruleCount))); if (done.isNull()) {
status = U_MEMORY_ALLOCATION_ERROR; return;
}
LocalPointer<UVector> filteredRules( new UVector(uprv_deleteUObject, nullptr, status), status); if (U_FAILURE(status)) { return;
}
// Create initial rule
tzt.getTo()->getName(name);
LocalPointer<InitialTimeZoneRule> res_initial( new InitialTimeZoneRule(name, tzt.getTo()->getRawOffset(), tzt.getTo()->getDSTSavings()), status); if (U_FAILURE(status)) { return;
}
// Mark rules which does not need to be processed for (i = 0; i < ruleCount; i++) {
r = static_cast<TimeZoneRule*>(orgRules->elementAt(i));
avail = r->getNextStart(start, res_initial->getRawOffset(), res_initial->getDSTSavings(), false, time);
done[i] = !avail;
}
time = start; while (!bFinalStd || !bFinalDst) {
avail = getNextTransition(time, false, tzt); if (!avail) { break;
}
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; return;
}
time = updatedTime;
const TimeZoneRule *toRule = tzt.getTo(); for (i = 0; i < ruleCount; i++) {
r = static_cast<TimeZoneRule*>(orgRules->elementAt(i)); if (*r == *toRule) { break;
}
} if (i >= ruleCount) { // This case should never happen
status = U_INVALID_STATE_ERROR; return;
} if (done[i]) { continue;
} const TimeArrayTimeZoneRule *tar = dynamic_cast<const TimeArrayTimeZoneRule *>(toRule); const AnnualTimeZoneRule *ar; if (tar != nullptr) { // Get the previous raw offset and DST savings before the very first start time
TimeZoneTransition tzt0;
t = start; while (true) {
avail = getNextTransition(t, false, tzt0); if (!avail) { break;
} if (*(tzt0.getTo()) == *tar) { break;
}
t = tzt0.getTime();
} if (avail) { // Check if the entire start times to be added
tar->getFirstStart(tzt.getFrom()->getRawOffset(), tzt.getFrom()->getDSTSavings(), firstStart); if (firstStart > start) { // Just add the rule as is
LocalPointer<TimeArrayTimeZoneRule> lpTar(tar->clone(), status);
filteredRules->adoptElement(lpTar.orphan(), status); if (U_FAILURE(status)) { return;
}
} else { // Collect transitions after the start time
int32_t startTimes;
DateTimeRule::TimeRuleType timeType;
int32_t idx;
startTimes = tar->countStartTimes();
timeType = tar->getTimeType(); for (idx = 0; idx < startTimes; idx++) {
tar->getStartTimeAt(idx, t); if (timeType == DateTimeRule::STANDARD_TIME) {
t -= tzt.getFrom()->getRawOffset();
} if (timeType == DateTimeRule::WALL_TIME) {
t -= tzt.getFrom()->getDSTSavings();
} if (t > start) { break;
}
} if (U_FAILURE(status)) { return;
}
int32_t asize = startTimes - idx; if (asize > 0) {
LocalMemory<UDate> newTimes(static_cast<UDate *>(uprv_malloc(sizeof(UDate) * asize))); if (newTimes.isNull()) {
status = U_MEMORY_ALLOCATION_ERROR; return;
} for (int32_t newidx = 0; newidx < asize; newidx++) {
tar->getStartTimeAt(idx + newidx, newTimes[newidx]);
}
tar->getName(name);
LocalPointer<TimeArrayTimeZoneRule> newTar(new TimeArrayTimeZoneRule(
name, tar->getRawOffset(), tar->getDSTSavings(), &newTimes[0], asize, timeType), status);
filteredRules->adoptElement(newTar.orphan(), status); if (U_FAILURE(status)) { return;
}
}
}
}
} elseif ((ar = dynamic_cast<const AnnualTimeZoneRule *>(toRule)) != nullptr) {
ar->getFirstStart(tzt.getFrom()->getRawOffset(), tzt.getFrom()->getDSTSavings(), firstStart); if (firstStart == tzt.getTime()) { // Just add the rule as is
LocalPointer<AnnualTimeZoneRule> arClone(ar->clone(), status);
filteredRules->adoptElement(arClone.orphan(), status); if (U_FAILURE(status)) { return;
}
} else { // Calculate the transition year
int32_t year, month, dom, dow, doy, mid;
Grego::timeToFields(tzt.getTime(), year, month, dom, dow, doy, mid, status); if (U_FAILURE(status)) { return;
} // Re-create the rule
ar->getName(name);
LocalPointer<AnnualTimeZoneRule> newAr(new AnnualTimeZoneRule(name, ar->getRawOffset(), ar->getDSTSavings(),
*(ar->getRule()), year, ar->getEndYear()), status);
filteredRules->adoptElement(newAr.orphan(), status); if (U_FAILURE(status)) { return;
}
} // check if this is a final rule if (ar->getEndYear() == AnnualTimeZoneRule::MAX_YEAR) { // After bot final standard and dst rules are processed, // exit this while loop. if (ar->getDSTSavings() == 0) {
bFinalStd = true;
} else {
bFinalDst = true;
}
}
}
done[i] = true;
}
// Set the results
initial = res_initial.orphan();
transitionRules = filteredRules.orphan();
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.14Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.