+// © 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
#include "uvector.h"
#include "gregoimp.h"
#include "cmemory.h"
+#include "umutex.h"
U_NAMESPACE_BEGIN
if (this == &that) {
return TRUE;
}
- if (getDynamicClassID() != that.getDynamicClassID()
+ if (typeid(*this) != typeid(that)
|| BasicTimeZone::operator==(that) == FALSE) {
return FALSE;
}
if (U_FAILURE(status)) {
return;
}
- if (rule->getDynamicClassID() == AnnualTimeZoneRule::getStaticClassID()
- && ((AnnualTimeZoneRule*)rule)->getEndYear() == AnnualTimeZoneRule::MAX_YEAR) {
+ AnnualTimeZoneRule* atzrule = dynamic_cast<AnnualTimeZoneRule*>(rule);
+ if (atzrule != NULL && atzrule->getEndYear() == AnnualTimeZoneRule::MAX_YEAR) {
// A final rule
if (fFinalRules == NULL) {
fFinalRules = new UVector(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<RuleBasedTimeZone*>(this);
+ ncThis->complete(status);
+ }
+ umtx_unlock(&gLock);
+}
+
void
RuleBasedTimeZone::complete(UErrorCode& status) {
if (U_FAILURE(status)) {
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);
}
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 {
if (this == &other) {
return TRUE;
}
- if (getDynamicClassID() != other.getDynamicClassID()) {
+ if (typeid(*this) != typeid(other)) {
return FALSE;
}
const RuleBasedTimeZone& that = (const RuleBasedTimeZone&)other;
}
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;
}
}
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;
}
}
int32_t
-RuleBasedTimeZone::countTransitionRules(UErrorCode& /*status*/) /*const*/ {
+RuleBasedTimeZone::countTransitionRules(UErrorCode& /*status*/) const {
int32_t count = 0;
if (fHistoricRules != NULL) {
count += fHistoricRules->size();
RuleBasedTimeZone::getTimeZoneRules(const InitialTimeZoneRule*& initial,
const TimeZoneRule* trsrules[],
int32_t& trscount,
- UErrorCode& status) /*const*/ {
+ UErrorCode& status) const {
if (U_FAILURE(status)) {
return;
}
}
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