Index: icu46/source/i18n/tzrule.cpp |
=================================================================== |
--- icu46/source/i18n/tzrule.cpp (revision 0) |
+++ icu46/source/i18n/tzrule.cpp (revision 0) |
@@ -0,0 +1,627 @@ |
+/* |
+******************************************************************************* |
+* Copyright (C) 2007-2010, International Business Machines Corporation and |
+* others. All Rights Reserved. |
+******************************************************************************* |
+*/ |
+ |
+#include <typeinfo> // for 'typeid' to work |
+ |
+#include "unicode/utypes.h" |
+ |
+#if !UCONFIG_NO_FORMATTING |
+ |
+#include "unicode/tzrule.h" |
+#include "unicode/ucal.h" |
+#include "gregoimp.h" |
+#include "cmemory.h" |
+#include "uarrsort.h" |
+ |
+U_CDECL_BEGIN |
+// UComparator function for sorting start times |
+static int32_t U_CALLCONV |
+compareDates(const void * /*context*/, const void *left, const void *right) { |
+ UDate l = *((UDate*)left); |
+ UDate r = *((UDate*)right); |
+ int32_t res = l < r ? -1 : (l == r ? 0 : 1); |
+ return res; |
+} |
+U_CDECL_END |
+ |
+U_NAMESPACE_BEGIN |
+ |
+TimeZoneRule::TimeZoneRule(const UnicodeString& name, int32_t rawOffset, int32_t dstSavings) |
+: UObject(), fName(name), fRawOffset(rawOffset), fDSTSavings(dstSavings) { |
+} |
+ |
+TimeZoneRule::TimeZoneRule(const TimeZoneRule& source) |
+: UObject(source), fName(source.fName), fRawOffset(source.fRawOffset), fDSTSavings(source.fDSTSavings) { |
+} |
+ |
+TimeZoneRule::~TimeZoneRule() { |
+} |
+ |
+TimeZoneRule& |
+TimeZoneRule::operator=(const TimeZoneRule& right) { |
+ if (this != &right) { |
+ fName = right.fName; |
+ fRawOffset = right.fRawOffset; |
+ fDSTSavings = right.fDSTSavings; |
+ } |
+ return *this; |
+} |
+ |
+UBool |
+TimeZoneRule::operator==(const TimeZoneRule& that) const { |
+ return ((this == &that) || |
+ (typeid(*this) == typeid(that) && |
+ fName == that.fName && |
+ fRawOffset == that.fRawOffset && |
+ fDSTSavings == that.fDSTSavings)); |
+} |
+ |
+UBool |
+TimeZoneRule::operator!=(const TimeZoneRule& that) const { |
+ return !operator==(that); |
+} |
+ |
+UnicodeString& |
+TimeZoneRule::getName(UnicodeString& name) const { |
+ name = fName; |
+ return name; |
+} |
+ |
+int32_t |
+TimeZoneRule::getRawOffset(void) const { |
+ return fRawOffset; |
+} |
+ |
+int32_t |
+TimeZoneRule::getDSTSavings(void) const { |
+ return fDSTSavings; |
+} |
+ |
+UBool |
+TimeZoneRule::isEquivalentTo(const TimeZoneRule& other) const { |
+ return ((this == &other) || |
+ (typeid(*this) == typeid(other) && |
+ fRawOffset == other.fRawOffset && |
+ fDSTSavings == other.fDSTSavings)); |
+} |
+ |
+ |
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(InitialTimeZoneRule) |
+ |
+InitialTimeZoneRule::InitialTimeZoneRule(const UnicodeString& name, |
+ int32_t rawOffset, |
+ int32_t dstSavings) |
+: TimeZoneRule(name, rawOffset, dstSavings) { |
+} |
+ |
+InitialTimeZoneRule::InitialTimeZoneRule(const InitialTimeZoneRule& source) |
+: TimeZoneRule(source) { |
+} |
+ |
+InitialTimeZoneRule::~InitialTimeZoneRule() { |
+} |
+ |
+InitialTimeZoneRule* |
+InitialTimeZoneRule::clone(void) const { |
+ return new InitialTimeZoneRule(*this); |
+} |
+ |
+InitialTimeZoneRule& |
+InitialTimeZoneRule::operator=(const InitialTimeZoneRule& right) { |
+ if (this != &right) { |
+ TimeZoneRule::operator=(right); |
+ } |
+ return *this; |
+} |
+ |
+UBool |
+InitialTimeZoneRule::operator==(const TimeZoneRule& that) const { |
+ return ((this == &that) || |
+ (typeid(*this) == typeid(that) && |
+ TimeZoneRule::operator==(that))); |
+} |
+ |
+UBool |
+InitialTimeZoneRule::operator!=(const TimeZoneRule& that) const { |
+ return !operator==(that); |
+} |
+ |
+UBool |
+InitialTimeZoneRule::isEquivalentTo(const TimeZoneRule& other) const { |
+ if (this == &other) { |
+ return TRUE; |
+ } |
+ if (typeid(*this) != typeid(other) || TimeZoneRule::isEquivalentTo(other) == FALSE) { |
+ return FALSE; |
+ } |
+ return TRUE; |
+} |
+ |
+UBool |
+InitialTimeZoneRule::getFirstStart(int32_t /*prevRawOffset*/, |
+ int32_t /*prevDSTSavings*/, |
+ UDate& /*result*/) const { |
+ return FALSE; |
+} |
+ |
+UBool |
+InitialTimeZoneRule::getFinalStart(int32_t /*prevRawOffset*/, |
+ int32_t /*prevDSTSavings*/, |
+ UDate& /*result*/) const { |
+ return FALSE; |
+} |
+ |
+UBool |
+InitialTimeZoneRule::getNextStart(UDate /*base*/, |
+ int32_t /*prevRawOffset*/, |
+ int32_t /*prevDSTSavings*/, |
+ UBool /*inclusive*/, |
+ UDate& /*result*/) const { |
+ return FALSE; |
+} |
+ |
+UBool |
+InitialTimeZoneRule::getPreviousStart(UDate /*base*/, |
+ int32_t /*prevRawOffset*/, |
+ int32_t /*prevDSTSavings*/, |
+ UBool /*inclusive*/, |
+ UDate& /*result*/) const { |
+ return FALSE; |
+} |
+ |
+ |
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(AnnualTimeZoneRule) |
+ |
+const int32_t AnnualTimeZoneRule::MAX_YEAR = 0x7FFFFFFF; /* max signed int32 */ |
+ |
+AnnualTimeZoneRule::AnnualTimeZoneRule(const UnicodeString& name, |
+ int32_t rawOffset, |
+ int32_t dstSavings, |
+ const DateTimeRule& dateTimeRule, |
+ int32_t startYear, |
+ int32_t endYear) |
+: TimeZoneRule(name, rawOffset, dstSavings), fDateTimeRule(new DateTimeRule(dateTimeRule)), |
+ fStartYear(startYear), fEndYear(endYear) { |
+} |
+ |
+AnnualTimeZoneRule::AnnualTimeZoneRule(const UnicodeString& name, |
+ int32_t rawOffset, |
+ int32_t dstSavings, |
+ DateTimeRule* dateTimeRule, |
+ int32_t startYear, |
+ int32_t endYear) |
+: TimeZoneRule(name, rawOffset, dstSavings), fDateTimeRule(dateTimeRule), |
+ fStartYear(startYear), fEndYear(endYear) { |
+} |
+ |
+AnnualTimeZoneRule::AnnualTimeZoneRule(const AnnualTimeZoneRule& source) |
+: TimeZoneRule(source), fDateTimeRule(new DateTimeRule(*(source.fDateTimeRule))), |
+ fStartYear(source.fStartYear), fEndYear(source.fEndYear) { |
+} |
+ |
+AnnualTimeZoneRule::~AnnualTimeZoneRule() { |
+ delete fDateTimeRule; |
+} |
+ |
+AnnualTimeZoneRule* |
+AnnualTimeZoneRule::clone(void) const { |
+ return new AnnualTimeZoneRule(*this); |
+} |
+ |
+AnnualTimeZoneRule& |
+AnnualTimeZoneRule::operator=(const AnnualTimeZoneRule& right) { |
+ if (this != &right) { |
+ TimeZoneRule::operator=(right); |
+ delete fDateTimeRule; |
+ fDateTimeRule = right.fDateTimeRule->clone(); |
+ fStartYear = right.fStartYear; |
+ fEndYear = right.fEndYear; |
+ } |
+ return *this; |
+} |
+ |
+UBool |
+AnnualTimeZoneRule::operator==(const TimeZoneRule& that) const { |
+ if (this == &that) { |
+ return TRUE; |
+ } |
+ if (typeid(*this) != typeid(that)) { |
+ return FALSE; |
+ } |
+ AnnualTimeZoneRule *atzr = (AnnualTimeZoneRule*)&that; |
+ return (*fDateTimeRule == *(atzr->fDateTimeRule) && |
+ fStartYear == atzr->fStartYear && |
+ fEndYear == atzr->fEndYear); |
+} |
+ |
+UBool |
+AnnualTimeZoneRule::operator!=(const TimeZoneRule& that) const { |
+ return !operator==(that); |
+} |
+ |
+const DateTimeRule* |
+AnnualTimeZoneRule::getRule() const { |
+ return fDateTimeRule; |
+} |
+ |
+int32_t |
+AnnualTimeZoneRule::getStartYear() const { |
+ return fStartYear; |
+} |
+ |
+int32_t |
+AnnualTimeZoneRule::getEndYear() const { |
+ return fEndYear; |
+} |
+ |
+UBool |
+AnnualTimeZoneRule::getStartInYear(int32_t year, |
+ int32_t prevRawOffset, |
+ int32_t prevDSTSavings, |
+ UDate &result) const { |
+ if (year < fStartYear || year > fEndYear) { |
+ return FALSE; |
+ } |
+ double ruleDay; |
+ DateTimeRule::DateRuleType type = fDateTimeRule->getDateRuleType(); |
+ if (type == DateTimeRule::DOM) { |
+ ruleDay = Grego::fieldsToDay(year, fDateTimeRule->getRuleMonth(), fDateTimeRule->getRuleDayOfMonth()); |
+ } else { |
+ UBool after = TRUE; |
+ if (type == DateTimeRule::DOW) { |
+ // Normalize DOW rule into DOW_GEQ_DOM or DOW_LEQ_DOM |
+ int32_t weeks = fDateTimeRule->getRuleWeekInMonth(); |
+ if (weeks > 0) { |
+ ruleDay = Grego::fieldsToDay(year, fDateTimeRule->getRuleMonth(), 1); |
+ ruleDay += 7 * (weeks - 1); |
+ } else { |
+ after = FALSE; |
+ ruleDay = Grego::fieldsToDay(year, fDateTimeRule->getRuleMonth(), |
+ Grego::monthLength(year, fDateTimeRule->getRuleMonth())); |
+ ruleDay += 7 * (weeks + 1); |
+ } |
+ } else { |
+ int32_t month = fDateTimeRule->getRuleMonth(); |
+ int32_t dom = fDateTimeRule->getRuleDayOfMonth(); |
+ if (type == DateTimeRule::DOW_LEQ_DOM) { |
+ after = FALSE; |
+ // Handle Feb <=29 |
+ if (month == UCAL_FEBRUARY && dom == 29 && !Grego::isLeapYear(year)) { |
+ dom--; |
+ } |
+ } |
+ ruleDay = Grego::fieldsToDay(year, month, dom); |
+ } |
+ int32_t dow = Grego::dayOfWeek(ruleDay); |
+ int32_t delta = fDateTimeRule->getRuleDayOfWeek() - dow; |
+ if (after) { |
+ delta = delta < 0 ? delta + 7 : delta; |
+ } else { |
+ delta = delta > 0 ? delta - 7 : delta; |
+ } |
+ ruleDay += delta; |
+ } |
+ |
+ result = ruleDay*U_MILLIS_PER_DAY + fDateTimeRule->getRuleMillisInDay(); |
+ if (fDateTimeRule->getTimeRuleType() != DateTimeRule::UTC_TIME) { |
+ result -= prevRawOffset; |
+ } |
+ if (fDateTimeRule->getTimeRuleType() == DateTimeRule::WALL_TIME) { |
+ result -= prevDSTSavings; |
+ } |
+ return TRUE; |
+} |
+ |
+UBool |
+AnnualTimeZoneRule::isEquivalentTo(const TimeZoneRule& other) const { |
+ if (this == &other) { |
+ return TRUE; |
+ } |
+ if (typeid(*this) != typeid(other) || TimeZoneRule::isEquivalentTo(other) == FALSE) { |
+ return FALSE; |
+ } |
+ AnnualTimeZoneRule* that = (AnnualTimeZoneRule*)&other; |
+ return (*fDateTimeRule == *(that->fDateTimeRule) && |
+ fStartYear == that->fStartYear && |
+ fEndYear == that->fEndYear); |
+} |
+ |
+UBool |
+AnnualTimeZoneRule::getFirstStart(int32_t prevRawOffset, |
+ int32_t prevDSTSavings, |
+ UDate& result) const { |
+ return getStartInYear(fStartYear, prevRawOffset, prevDSTSavings, result); |
+} |
+ |
+UBool |
+AnnualTimeZoneRule::getFinalStart(int32_t prevRawOffset, |
+ int32_t prevDSTSavings, |
+ UDate& result) const { |
+ if (fEndYear == MAX_YEAR) { |
+ return FALSE; |
+ } |
+ return getStartInYear(fEndYear, prevRawOffset, prevDSTSavings, result); |
+} |
+ |
+UBool |
+AnnualTimeZoneRule::getNextStart(UDate base, |
+ int32_t prevRawOffset, |
+ int32_t prevDSTSavings, |
+ UBool inclusive, |
+ UDate& result) const { |
+ int32_t year, month, dom, dow, doy, mid; |
+ Grego::timeToFields(base, year, month, dom, dow, doy, mid); |
+ if (year < fStartYear) { |
+ return getFirstStart(prevRawOffset, prevDSTSavings, result); |
+ } |
+ UDate tmp; |
+ if (getStartInYear(year, prevRawOffset, prevDSTSavings, tmp)) { |
+ if (tmp < base || (!inclusive && (tmp == base))) { |
+ // Return the next one |
+ return getStartInYear(year + 1, prevRawOffset, prevDSTSavings, result); |
+ } else { |
+ result = tmp; |
+ return TRUE; |
+ } |
+ } |
+ return FALSE; |
+} |
+ |
+UBool |
+AnnualTimeZoneRule::getPreviousStart(UDate base, |
+ int32_t prevRawOffset, |
+ int32_t prevDSTSavings, |
+ UBool inclusive, |
+ UDate& result) const { |
+ int32_t year, month, dom, dow, doy, mid; |
+ Grego::timeToFields(base, year, month, dom, dow, doy, mid); |
+ if (year > fEndYear) { |
+ return getFinalStart(prevRawOffset, prevDSTSavings, result); |
+ } |
+ UDate tmp; |
+ if (getStartInYear(year, prevRawOffset, prevDSTSavings, tmp)) { |
+ if (tmp > base || (!inclusive && (tmp == base))) { |
+ // Return the previous one |
+ return getStartInYear(year - 1, prevRawOffset, prevDSTSavings, result); |
+ } else { |
+ result = tmp; |
+ return TRUE; |
+ } |
+ } |
+ return FALSE; |
+} |
+ |
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(TimeArrayTimeZoneRule) |
+ |
+TimeArrayTimeZoneRule::TimeArrayTimeZoneRule(const UnicodeString& name, |
+ int32_t rawOffset, |
+ int32_t dstSavings, |
+ const UDate* startTimes, |
+ int32_t numStartTimes, |
+ DateTimeRule::TimeRuleType timeRuleType) |
+: TimeZoneRule(name, rawOffset, dstSavings), fTimeRuleType(timeRuleType), |
+ fStartTimes(NULL) { |
+ UErrorCode status = U_ZERO_ERROR; |
+ initStartTimes(startTimes, numStartTimes, status); |
+ //TODO - status? |
+} |
+ |
+ |
+TimeArrayTimeZoneRule::TimeArrayTimeZoneRule(const TimeArrayTimeZoneRule& source) |
+: TimeZoneRule(source), fTimeRuleType(source.fTimeRuleType), fStartTimes(NULL) { |
+ UErrorCode status = U_ZERO_ERROR; |
+ initStartTimes(source.fStartTimes, source.fNumStartTimes, status); |
+ //TODO - status? |
+} |
+ |
+ |
+TimeArrayTimeZoneRule::~TimeArrayTimeZoneRule() { |
+ if (fStartTimes != NULL && fStartTimes != fLocalStartTimes) { |
+ uprv_free(fStartTimes); |
+ } |
+} |
+ |
+TimeArrayTimeZoneRule* |
+TimeArrayTimeZoneRule::clone(void) const { |
+ return new TimeArrayTimeZoneRule(*this); |
+} |
+ |
+ |
+TimeArrayTimeZoneRule& |
+TimeArrayTimeZoneRule::operator=(const TimeArrayTimeZoneRule& right) { |
+ if (this != &right) { |
+ TimeZoneRule::operator=(right); |
+ UErrorCode status = U_ZERO_ERROR; |
+ initStartTimes(right.fStartTimes, right.fNumStartTimes, status); |
+ //TODO - status? |
+ fTimeRuleType = right.fTimeRuleType; |
+ } |
+ return *this; |
+} |
+ |
+UBool |
+TimeArrayTimeZoneRule::operator==(const TimeZoneRule& that) const { |
+ if (this == &that) { |
+ return TRUE; |
+ } |
+ if (typeid(*this) != typeid(that) || TimeZoneRule::operator==(that) == FALSE) { |
+ return FALSE; |
+ } |
+ TimeArrayTimeZoneRule *tatzr = (TimeArrayTimeZoneRule*)&that; |
+ if (fTimeRuleType != tatzr->fTimeRuleType || |
+ fNumStartTimes != tatzr->fNumStartTimes) { |
+ return FALSE; |
+ } |
+ // Compare start times |
+ UBool res = TRUE; |
+ for (int32_t i = 0; i < fNumStartTimes; i++) { |
+ if (fStartTimes[i] != tatzr->fStartTimes[i]) { |
+ res = FALSE; |
+ break; |
+ } |
+ } |
+ return res; |
+} |
+ |
+UBool |
+TimeArrayTimeZoneRule::operator!=(const TimeZoneRule& that) const { |
+ return !operator==(that); |
+} |
+ |
+DateTimeRule::TimeRuleType |
+TimeArrayTimeZoneRule::getTimeType(void) const { |
+ return fTimeRuleType; |
+} |
+ |
+UBool |
+TimeArrayTimeZoneRule::getStartTimeAt(int32_t index, UDate& result) const { |
+ if (index >= fNumStartTimes || index < 0) { |
+ return FALSE; |
+ } |
+ result = fStartTimes[index]; |
+ return TRUE; |
+} |
+ |
+int32_t |
+TimeArrayTimeZoneRule::countStartTimes(void) const { |
+ return fNumStartTimes; |
+} |
+ |
+UBool |
+TimeArrayTimeZoneRule::isEquivalentTo(const TimeZoneRule& other) const { |
+ if (this == &other) { |
+ return TRUE; |
+ } |
+ if (typeid(*this) != typeid(other) || TimeZoneRule::isEquivalentTo(other) == FALSE) { |
+ return FALSE; |
+ } |
+ TimeArrayTimeZoneRule* that = (TimeArrayTimeZoneRule*)&other; |
+ if (fTimeRuleType != that->fTimeRuleType || |
+ fNumStartTimes != that->fNumStartTimes) { |
+ return FALSE; |
+ } |
+ // Compare start times |
+ UBool res = TRUE; |
+ for (int32_t i = 0; i < fNumStartTimes; i++) { |
+ if (fStartTimes[i] != that->fStartTimes[i]) { |
+ res = FALSE; |
+ break; |
+ } |
+ } |
+ return res; |
+} |
+ |
+UBool |
+TimeArrayTimeZoneRule::getFirstStart(int32_t prevRawOffset, |
+ int32_t prevDSTSavings, |
+ UDate& result) const { |
+ if (fNumStartTimes <= 0 || fStartTimes == NULL) { |
+ return FALSE; |
+ } |
+ result = getUTC(fStartTimes[0], prevRawOffset, prevDSTSavings); |
+ return TRUE; |
+} |
+ |
+UBool |
+TimeArrayTimeZoneRule::getFinalStart(int32_t prevRawOffset, |
+ int32_t prevDSTSavings, |
+ UDate& result) const { |
+ if (fNumStartTimes <= 0 || fStartTimes == NULL) { |
+ return FALSE; |
+ } |
+ result = getUTC(fStartTimes[fNumStartTimes - 1], prevRawOffset, prevDSTSavings); |
+ return TRUE; |
+} |
+ |
+UBool |
+TimeArrayTimeZoneRule::getNextStart(UDate base, |
+ int32_t prevRawOffset, |
+ int32_t prevDSTSavings, |
+ UBool inclusive, |
+ UDate& result) const { |
+ int32_t i = fNumStartTimes - 1; |
+ for (; i >= 0; i--) { |
+ UDate time = getUTC(fStartTimes[i], prevRawOffset, prevDSTSavings); |
+ if (time < base || (!inclusive && time == base)) { |
+ break; |
+ } |
+ result = time; |
+ } |
+ if (i == fNumStartTimes - 1) { |
+ return FALSE; |
+ } |
+ return TRUE; |
+} |
+ |
+UBool |
+TimeArrayTimeZoneRule::getPreviousStart(UDate base, |
+ int32_t prevRawOffset, |
+ int32_t prevDSTSavings, |
+ UBool inclusive, |
+ UDate& result) const { |
+ int32_t i = fNumStartTimes - 1; |
+ for (; i >= 0; i--) { |
+ UDate time = getUTC(fStartTimes[i], prevRawOffset, prevDSTSavings); |
+ if (time < base || (inclusive && time == base)) { |
+ result = time; |
+ return TRUE; |
+ } |
+ } |
+ return FALSE; |
+} |
+ |
+ |
+// ---- private methods ------ |
+ |
+UBool |
+TimeArrayTimeZoneRule::initStartTimes(const UDate source[], int32_t size, UErrorCode& status) { |
+ // Free old array |
+ if (fStartTimes != NULL && fStartTimes != fLocalStartTimes) { |
+ uprv_free(fStartTimes); |
+ } |
+ // Allocate new one if needed |
+ if (size > TIMEARRAY_STACK_BUFFER_SIZE) { |
+ fStartTimes = (UDate*)uprv_malloc(sizeof(UDate)*size); |
+ if (fStartTimes == NULL) { |
+ status = U_MEMORY_ALLOCATION_ERROR; |
+ fNumStartTimes = 0; |
+ return FALSE; |
+ } |
+ } else { |
+ fStartTimes = (UDate*)fLocalStartTimes; |
+ } |
+ uprv_memcpy(fStartTimes, source, sizeof(UDate)*size); |
+ fNumStartTimes = size; |
+ // Sort dates |
+ uprv_sortArray(fStartTimes, fNumStartTimes, (int32_t)sizeof(UDate), compareDates, NULL, TRUE, &status); |
+ if (U_FAILURE(status)) { |
+ if (fStartTimes != NULL && fStartTimes != fLocalStartTimes) { |
+ uprv_free(fStartTimes); |
+ } |
+ fNumStartTimes = 0; |
+ return FALSE; |
+ } |
+ return TRUE; |
+} |
+ |
+UDate |
+TimeArrayTimeZoneRule::getUTC(UDate time, int32_t raw, int32_t dst) const { |
+ if (fTimeRuleType != DateTimeRule::UTC_TIME) { |
+ time -= raw; |
+ } |
+ if (fTimeRuleType == DateTimeRule::WALL_TIME) { |
+ time -= dst; |
+ } |
+ return time; |
+} |
+ |
+U_NAMESPACE_END |
+ |
+#endif /* #if !UCONFIG_NO_FORMATTING */ |
+ |
+//eof |
+ |
Property changes on: icu46/source/i18n/tzrule.cpp |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |