void
RuleBasedTimeZone::complete(UErrorCode& status) { if (U_FAILURE(status)) { return;
} if (fUpToDate) { return;
} // Make sure either no final rules or a pair of AnnualTimeZoneRules // are available. if (fFinalRules != nullptr && fFinalRules->size() != 2) {
status = U_INVALID_STATE_ERROR; return;
}
// Create a TimezoneTransition and add to the list if (fHistoricRules != nullptr || fFinalRules != nullptr) {
TimeZoneRule *curRule = fInitialRule;
UDate lastTransitionTime = MIN_MILLIS;
// Build the transition array which represents historical time zone // transitions. if (fHistoricRules != nullptr && fHistoricRules->size() > 0) {
int32_t i;
int32_t historicCount = fHistoricRules->size();
LocalMemory<bool> done(static_cast<bool*>(uprv_malloc(sizeof(bool) * historicCount))); if (done == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR; goto cleanup;
} for (i = 0; i < historicCount; i++) {
done[i] = false;
} while (true) {
int32_t curStdOffset = curRule->getRawOffset();
int32_t curDstSavings = curRule->getDSTSavings();
UDate nextTransitionTime = MAX_MILLIS;
TimeZoneRule *nextRule = nullptr;
TimeZoneRule *r = nullptr;
UBool avail;
UDate tt;
UnicodeString curName, name;
curRule->getName(curName);
for (i = 0; i < historicCount; i++) { if (done[i]) { continue;
}
r = static_cast<TimeZoneRule*>(fHistoricRules->elementAt(i));
avail = r->getNextStart(lastTransitionTime, curStdOffset, curDstSavings, false, tt); if (!avail) { // No more transitions from this rule - skip this rule next time
done[i] = true;
} else {
r->getName(name); if (*r == *curRule ||
(name == curName && r->getRawOffset() == curRule->getRawOffset()
&& r->getDSTSavings() == curRule->getDSTSavings())) { continue;
} if (tt < nextTransitionTime) {
nextTransitionTime = tt;
nextRule = r;
}
}
}
if (nextRule == nullptr) { // Check if all historic rules are done
UBool bDoneAll = true; for (int32_t j = 0; j < historicCount; j++) { if (!done[j]) {
bDoneAll = false; break;
}
} if (bDoneAll) { break;
}
}
if (fFinalRules != nullptr) { // Check if one of final rules has earlier transition date for (i = 0; i < 2 /* fFinalRules->size() */; i++) {
TimeZoneRule* fr = static_cast<TimeZoneRule*>(fFinalRules->elementAt(i)); if (*fr == *curRule) { continue;
}
r = static_cast<TimeZoneRule*>(fFinalRules->elementAt(i));
avail = r->getNextStart(lastTransitionTime, curStdOffset, curDstSavings, false, tt); if (avail) { if (tt < nextTransitionTime) {
nextTransitionTime = tt;
nextRule = r;
}
}
}
}
if (nextRule == nullptr) { // Nothing more break;
}
if (fHistoricTransitions == nullptr) {
LocalPointer<UVector> lpHistoricTransitions( new UVector(deleteTransition, nullptr, status), status); if (U_FAILURE(status)) { goto cleanup;
}
fHistoricTransitions = lpHistoricTransitions.orphan();
}
LocalPointer<Transition> trst(new Transition, status); if (U_FAILURE(status)) { goto cleanup;
}
trst->time = nextTransitionTime;
trst->from = curRule;
trst->to = nextRule;
fHistoricTransitions->adoptElement(trst.orphan(), status); if (U_FAILURE(status)) { goto cleanup;
}
lastTransitionTime = nextTransitionTime;
curRule = nextRule;
}
} if (fFinalRules != nullptr) { if (fHistoricTransitions == nullptr) {
LocalPointer<UVector> lpHistoricTransitions( new UVector(deleteTransition, nullptr, status), status); if (U_FAILURE(status)) { goto cleanup;
}
fHistoricTransitions = lpHistoricTransitions.orphan();
} // Append the first transition for each
TimeZoneRule* rule0 = static_cast<TimeZoneRule*>(fFinalRules->elementAt(0));
TimeZoneRule* rule1 = static_cast<TimeZoneRule*>(fFinalRules->elementAt(1));
UDate tt0, tt1;
UBool avail0 = rule0->getNextStart(lastTransitionTime, curRule->getRawOffset(), curRule->getDSTSavings(), false, tt0);
UBool avail1 = rule1->getNextStart(lastTransitionTime, curRule->getRawOffset(), curRule->getDSTSavings(), false, tt1); if (!avail0 || !avail1) { // Should not happen, because both rules are permanent
status = U_INVALID_STATE_ERROR; goto cleanup;
}
LocalPointer<Transition> final0(new Transition, status);
LocalPointer<Transition> final1(new Transition, status); if (U_FAILURE(status)) { goto cleanup;
} if (tt0 < tt1) {
final0->time = tt0;
final0->from = curRule;
final0->to = rule0;
rule1->getNextStart(tt0, rule0->getRawOffset(), rule0->getDSTSavings(), false, final1->time);
final1->from = rule0;
final1->to = rule1;
} else {
final0->time = tt1;
final0->from = curRule;
final0->to = rule1;
rule0->getNextStart(tt1, rule1->getRawOffset(), rule1->getDSTSavings(), false, final1->time);
final1->from = rule1;
final1->to = rule0;
}
fHistoricTransitions->adoptElement(final0.orphan(), status);
fHistoricTransitions->adoptElement(final1.orphan(), status); if (U_FAILURE(status)) { goto cleanup;
}
}
}
fUpToDate = true; return;
if (U_FAILURE(status)) { return;
} if (!fUpToDate) { // Transitions are not yet resolved. We cannot do it here // because this method is const. Thus, do nothing and return // error status.
status = U_INVALID_STATE_ERROR; return;
} const TimeZoneRule *rule = nullptr; if (fHistoricTransitions == nullptr) {
rule = fInitialRule;
} else {
UDate tstart = getTransitionTime(static_cast<Transition*>(fHistoricTransitions->elementAt(0)),
local, NonExistingTimeOpt, DuplicatedTimeOpt); if (date < tstart) {
rule = fInitialRule;
} else {
int32_t idx = fHistoricTransitions->size() - 1;
UDate tend = getTransitionTime(static_cast<Transition*>(fHistoricTransitions->elementAt(idx)),
local, NonExistingTimeOpt, DuplicatedTimeOpt); if (date > tend) { if (fFinalRules != nullptr) {
rule = findRuleInFinal(date, local, NonExistingTimeOpt, DuplicatedTimeOpt);
} if (rule == nullptr) { // no final rules or the given time is before the first transition // specified by the final rules -> use the last rule
rule = static_cast<Transition*>(fHistoricTransitions->elementAt(idx))->to;
}
} else { // Find a historical transition while (idx >= 0) { if (date >= getTransitionTime(static_cast<Transition*>(fHistoricTransitions->elementAt(idx)),
local, NonExistingTimeOpt, DuplicatedTimeOpt)) { break;
}
idx--;
}
rule = static_cast<Transition*>(fHistoricTransitions->elementAt(idx))->to;
}
}
} if (rule != nullptr) {
rawOffset = rule->getRawOffset();
dstOffset = rule->getDSTSavings();
}
}
void
RuleBasedTimeZone::setRawOffset(int32_t /*offsetMillis*/) { // We don't support this operation at this moment. // Nothing to do!
}
int32_t
RuleBasedTimeZone::getRawOffset() const { // Note: This implementation returns standard GMT offset // as of current time.
UErrorCode status = U_ZERO_ERROR;
int32_t raw, dst;
getOffset(uprv_getUTCtime(), false, raw, dst, status); return raw;
}
UBool
RuleBasedTimeZone::useDaylightTime() const { // Note: This implementation returns true when // daylight saving time is used as of now or // after the next transition.
UErrorCode status = U_ZERO_ERROR;
UDate now = uprv_getUTCtime();
int32_t raw, dst;
getOffset(now, false, raw, dst, status); if (dst != 0) { returntrue;
} // If DST is not used now, check if DST is used after the next transition
UDate time;
TimeZoneRule *from, *to;
UBool avail = findNext(now, false, time, from, to); if (avail && to->getDSTSavings() != 0) { returntrue;
} returnfalse;
}
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.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.