X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/46f4442e9a5a4f3b98b7c1083586332f6a8a99a4..0f5d89e82340278ed3d7d50029f37cab2c41a57e:/icuSources/i18n/rbtz.cpp diff --git a/icuSources/i18n/rbtz.cpp b/icuSources/i18n/rbtz.cpp index 848ab845..d98613fe 100644 --- a/icuSources/i18n/rbtz.cpp +++ b/icuSources/i18n/rbtz.cpp @@ -1,10 +1,14 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html /* ******************************************************************************* -* Copyright (C) 2007-2008, International Business Machines Corporation and * -* others. All Rights Reserved. * +* Copyright (C) 2007-2013, International Business Machines Corporation and +* others. All Rights Reserved. ******************************************************************************* */ +#include "utypeinfo.h" // for 'typeid' to work + #include "unicode/utypes.h" #if !UCONFIG_NO_FORMATTING @@ -14,6 +18,7 @@ #include "uvector.h" #include "gregoimp.h" #include "cmemory.h" +#include "umutex.h" U_NAMESPACE_BEGIN @@ -88,7 +93,7 @@ RuleBasedTimeZone::operator==(const TimeZone& that) const { if (this == &that) { return TRUE; } - if (getDynamicClassID() != that.getDynamicClassID() + if (typeid(*this) != typeid(that) || BasicTimeZone::operator==(that) == FALSE) { return FALSE; } @@ -113,8 +118,8 @@ RuleBasedTimeZone::addTransitionRule(TimeZoneRule* rule, UErrorCode& status) { if (U_FAILURE(status)) { return; } - if (rule->getDynamicClassID() == AnnualTimeZoneRule::getStaticClassID() - && ((AnnualTimeZoneRule*)rule)->getEndYear() == AnnualTimeZoneRule::MAX_YEAR) { + AnnualTimeZoneRule* atzrule = dynamic_cast(rule); + if (atzrule != NULL && atzrule->getEndYear() == AnnualTimeZoneRule::MAX_YEAR) { // A final rule if (fFinalRules == NULL) { fFinalRules = new UVector(status); @@ -141,6 +146,21 @@ RuleBasedTimeZone::addTransitionRule(TimeZoneRule* rule, UErrorCode& status) { fUpToDate = FALSE; } +static UMutex gLock = U_MUTEX_INITIALIZER; + +void +RuleBasedTimeZone::completeConst(UErrorCode& status) const { + if (U_FAILURE(status)) { + return; + } + umtx_lock(&gLock); + if (!fUpToDate) { + RuleBasedTimeZone *ncThis = const_cast(this); + ncThis->complete(status); + } + umtx_unlock(&gLock); +} + void RuleBasedTimeZone::complete(UErrorCode& status) { if (U_FAILURE(status)) { @@ -385,7 +405,7 @@ RuleBasedTimeZone::getOffset(UDate date, UBool local, int32_t& rawOffset, void RuleBasedTimeZone::getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt, - int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) /*const*/ { + int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) const { getOffsetInternal(date, TRUE, nonExistingTimeOpt, duplicatedTimeOpt, rawOffset, dstOffset, status); } @@ -426,8 +446,10 @@ RuleBasedTimeZone::getOffsetInternal(UDate date, UBool local, if (date > tend) { if (fFinalRules != NULL) { rule = findRuleInFinal(date, local, NonExistingTimeOpt, DuplicatedTimeOpt); - } else { - // no final rule, use the last rule + } + if (rule == NULL) { + // no final rules or the given time is before the first transition + // specified by the final rules -> use the last rule rule = ((Transition*)fHistoricTransitions->elementAt(idx))->to; } } else { @@ -506,7 +528,7 @@ RuleBasedTimeZone::hasSameRules(const TimeZone& other) const { if (this == &other) { return TRUE; } - if (getDynamicClassID() != other.getDynamicClassID()) { + if (typeid(*this) != typeid(other)) { return FALSE; } const RuleBasedTimeZone& that = (const RuleBasedTimeZone&)other; @@ -521,9 +543,9 @@ RuleBasedTimeZone::hasSameRules(const TimeZone& other) const { } UBool -RuleBasedTimeZone::getNextTransition(UDate base, UBool inclusive, TimeZoneTransition& result) /*const*/ { +RuleBasedTimeZone::getNextTransition(UDate base, UBool inclusive, TimeZoneTransition& result) const { UErrorCode status = U_ZERO_ERROR; - complete(status); + completeConst(status); if (U_FAILURE(status)) { return FALSE; } @@ -540,9 +562,9 @@ RuleBasedTimeZone::getNextTransition(UDate base, UBool inclusive, TimeZoneTransi } UBool -RuleBasedTimeZone::getPreviousTransition(UDate base, UBool inclusive, TimeZoneTransition& result) /*const*/ { +RuleBasedTimeZone::getPreviousTransition(UDate base, UBool inclusive, TimeZoneTransition& result) const { UErrorCode status = U_ZERO_ERROR; - complete(status); + completeConst(status); if (U_FAILURE(status)) { return FALSE; } @@ -559,7 +581,7 @@ RuleBasedTimeZone::getPreviousTransition(UDate base, UBool inclusive, TimeZoneTr } int32_t -RuleBasedTimeZone::countTransitionRules(UErrorCode& /*status*/) /*const*/ { +RuleBasedTimeZone::countTransitionRules(UErrorCode& /*status*/) const { int32_t count = 0; if (fHistoricRules != NULL) { count += fHistoricRules->size(); @@ -574,7 +596,7 @@ void RuleBasedTimeZone::getTimeZoneRules(const InitialTimeZoneRule*& initial, const TimeZoneRule* trsrules[], int32_t& trscount, - UErrorCode& status) /*const*/ { + UErrorCode& status) const { if (U_FAILURE(status)) { return; } @@ -699,12 +721,17 @@ RuleBasedTimeZone::findRuleInFinal(UDate date, UBool local, } UBool avail1 = fr1->getPreviousStart(base, fr0->getRawOffset(), fr0->getDSTSavings(), TRUE, start1); - if (avail0 && (!avail1 || start0 > start1)) { - return fr0; - } else if (avail1) { - return fr1; + if (!avail0 || !avail1) { + if (avail0) { + return fr0; + } else if (avail1) { + return fr1; + } + // Both rules take effect after the given time + return NULL; } - return NULL; + + return (start0 > start1) ? fr0 : fr1; } UBool