Index: icu46/source/i18n/simpletz.cpp |
=================================================================== |
--- icu46/source/i18n/simpletz.cpp (revision 0) |
+++ icu46/source/i18n/simpletz.cpp (revision 0) |
@@ -0,0 +1,1221 @@ |
+/* |
+ ******************************************************************************* |
+ * Copyright (C) 1997-2010, International Business Machines Corporation and |
+ * others. All Rights Reserved. |
+ ******************************************************************************* |
+ * |
+ * File SIMPLETZ.H |
+ * |
+ * Modification History: |
+ * |
+ * Date Name Description |
+ * 12/05/96 clhuang Creation. |
+ * 04/21/97 aliu Fixed miscellaneous bugs found by inspection and |
+ * testing. |
+ * 07/29/97 aliu Ported source bodies back from Java version with |
+ * numerous feature enhancements and bug fixes. |
+ * 08/10/98 stephen JDK 1.2 sync. |
+ * 09/17/98 stephen Fixed getOffset() for last hour of year and DST |
+ * 12/02/99 aliu Added TimeMode and constructor and setStart/EndRule |
+ * methods that take TimeMode. Whitespace cleanup. |
+ ******************************************************************************** |
+ */ |
+ |
+#include <typeinfo> // for 'typeid' to work |
+ |
+#include "unicode/utypes.h" |
+ |
+#if !UCONFIG_NO_FORMATTING |
+ |
+#include "unicode/simpletz.h" |
+#include "unicode/gregocal.h" |
+#include "unicode/smpdtfmt.h" |
+ |
+#include "gregoimp.h" |
+ |
+U_NAMESPACE_BEGIN |
+ |
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SimpleTimeZone) |
+ |
+// Use only for decodeStartRule() and decodeEndRule() where the year is not |
+// available. Set February to 29 days to accomodate rules with that date |
+// and day-of-week-on-or-before-that-date mode (DOW_LE_DOM_MODE). |
+// The compareToRule() method adjusts to February 28 in non-leap years. |
+// |
+// For actual getOffset() calculations, use Grego::monthLength() and |
+// Grego::previousMonthLength() which take leap years into account. |
+// We handle leap years assuming always |
+// Gregorian, since we know they didn't have daylight time when |
+// Gregorian calendar started. |
+const int8_t SimpleTimeZone::STATICMONTHLENGTH[] = {31,29,31,30,31,30,31,31,30,31,30,31}; |
+ |
+static const UChar DST_STR[] = {0x0028,0x0044,0x0053,0x0054,0x0029,0}; // "(DST)" |
+static const UChar STD_STR[] = {0x0028,0x0053,0x0054,0x0044,0x0029,0}; // "(STD)" |
+ |
+ |
+// ***************************************************************************** |
+// class SimpleTimeZone |
+// ***************************************************************************** |
+ |
+ |
+SimpleTimeZone::SimpleTimeZone(int32_t rawOffsetGMT, const UnicodeString& ID) |
+: BasicTimeZone(ID), |
+ startMonth(0), |
+ startDay(0), |
+ startDayOfWeek(0), |
+ startTime(0), |
+ startTimeMode(WALL_TIME), |
+ endTimeMode(WALL_TIME), |
+ endMonth(0), |
+ endDay(0), |
+ endDayOfWeek(0), |
+ endTime(0), |
+ startYear(0), |
+ rawOffset(rawOffsetGMT), |
+ useDaylight(FALSE), |
+ startMode(DOM_MODE), |
+ endMode(DOM_MODE), |
+ dstSavings(U_MILLIS_PER_HOUR) |
+{ |
+ clearTransitionRules(); |
+} |
+ |
+// ------------------------------------- |
+ |
+SimpleTimeZone::SimpleTimeZone(int32_t rawOffsetGMT, const UnicodeString& ID, |
+ int8_t savingsStartMonth, int8_t savingsStartDay, |
+ int8_t savingsStartDayOfWeek, int32_t savingsStartTime, |
+ int8_t savingsEndMonth, int8_t savingsEndDay, |
+ int8_t savingsEndDayOfWeek, int32_t savingsEndTime, |
+ UErrorCode& status) |
+: BasicTimeZone(ID) |
+{ |
+ clearTransitionRules(); |
+ construct(rawOffsetGMT, |
+ savingsStartMonth, savingsStartDay, savingsStartDayOfWeek, |
+ savingsStartTime, WALL_TIME, |
+ savingsEndMonth, savingsEndDay, savingsEndDayOfWeek, |
+ savingsEndTime, WALL_TIME, |
+ U_MILLIS_PER_HOUR, status); |
+} |
+ |
+// ------------------------------------- |
+ |
+SimpleTimeZone::SimpleTimeZone(int32_t rawOffsetGMT, const UnicodeString& ID, |
+ int8_t savingsStartMonth, int8_t savingsStartDay, |
+ int8_t savingsStartDayOfWeek, int32_t savingsStartTime, |
+ int8_t savingsEndMonth, int8_t savingsEndDay, |
+ int8_t savingsEndDayOfWeek, int32_t savingsEndTime, |
+ int32_t savingsDST, UErrorCode& status) |
+: BasicTimeZone(ID) |
+{ |
+ clearTransitionRules(); |
+ construct(rawOffsetGMT, |
+ savingsStartMonth, savingsStartDay, savingsStartDayOfWeek, |
+ savingsStartTime, WALL_TIME, |
+ savingsEndMonth, savingsEndDay, savingsEndDayOfWeek, |
+ savingsEndTime, WALL_TIME, |
+ savingsDST, status); |
+} |
+ |
+// ------------------------------------- |
+ |
+SimpleTimeZone::SimpleTimeZone(int32_t rawOffsetGMT, const UnicodeString& ID, |
+ int8_t savingsStartMonth, int8_t savingsStartDay, |
+ int8_t savingsStartDayOfWeek, int32_t savingsStartTime, |
+ TimeMode savingsStartTimeMode, |
+ int8_t savingsEndMonth, int8_t savingsEndDay, |
+ int8_t savingsEndDayOfWeek, int32_t savingsEndTime, |
+ TimeMode savingsEndTimeMode, |
+ int32_t savingsDST, UErrorCode& status) |
+: BasicTimeZone(ID) |
+{ |
+ clearTransitionRules(); |
+ construct(rawOffsetGMT, |
+ savingsStartMonth, savingsStartDay, savingsStartDayOfWeek, |
+ savingsStartTime, savingsStartTimeMode, |
+ savingsEndMonth, savingsEndDay, savingsEndDayOfWeek, |
+ savingsEndTime, savingsEndTimeMode, |
+ savingsDST, status); |
+} |
+ |
+/** |
+ * Internal construction method. |
+ */ |
+void SimpleTimeZone::construct(int32_t rawOffsetGMT, |
+ int8_t savingsStartMonth, |
+ int8_t savingsStartDay, |
+ int8_t savingsStartDayOfWeek, |
+ int32_t savingsStartTime, |
+ TimeMode savingsStartTimeMode, |
+ int8_t savingsEndMonth, |
+ int8_t savingsEndDay, |
+ int8_t savingsEndDayOfWeek, |
+ int32_t savingsEndTime, |
+ TimeMode savingsEndTimeMode, |
+ int32_t savingsDST, |
+ UErrorCode& status) |
+{ |
+ this->rawOffset = rawOffsetGMT; |
+ this->startMonth = savingsStartMonth; |
+ this->startDay = savingsStartDay; |
+ this->startDayOfWeek = savingsStartDayOfWeek; |
+ this->startTime = savingsStartTime; |
+ this->startTimeMode = savingsStartTimeMode; |
+ this->endMonth = savingsEndMonth; |
+ this->endDay = savingsEndDay; |
+ this->endDayOfWeek = savingsEndDayOfWeek; |
+ this->endTime = savingsEndTime; |
+ this->endTimeMode = savingsEndTimeMode; |
+ this->dstSavings = savingsDST; |
+ this->startYear = 0; |
+ this->startMode = DOM_MODE; |
+ this->endMode = DOM_MODE; |
+ |
+ decodeRules(status); |
+ |
+ if (savingsDST <= 0) { |
+ status = U_ILLEGAL_ARGUMENT_ERROR; |
+ } |
+} |
+ |
+// ------------------------------------- |
+ |
+SimpleTimeZone::~SimpleTimeZone() |
+{ |
+ deleteTransitionRules(); |
+} |
+ |
+// ------------------------------------- |
+ |
+// Called by TimeZone::createDefault(), then clone() inside a Mutex - be careful. |
+SimpleTimeZone::SimpleTimeZone(const SimpleTimeZone &source) |
+: BasicTimeZone(source) |
+{ |
+ *this = source; |
+} |
+ |
+// ------------------------------------- |
+ |
+// Called by TimeZone::createDefault(), then clone() inside a Mutex - be careful. |
+SimpleTimeZone & |
+SimpleTimeZone::operator=(const SimpleTimeZone &right) |
+{ |
+ if (this != &right) |
+ { |
+ TimeZone::operator=(right); |
+ rawOffset = right.rawOffset; |
+ startMonth = right.startMonth; |
+ startDay = right.startDay; |
+ startDayOfWeek = right.startDayOfWeek; |
+ startTime = right.startTime; |
+ startTimeMode = right.startTimeMode; |
+ startMode = right.startMode; |
+ endMonth = right.endMonth; |
+ endDay = right.endDay; |
+ endDayOfWeek = right.endDayOfWeek; |
+ endTime = right.endTime; |
+ endTimeMode = right.endTimeMode; |
+ endMode = right.endMode; |
+ startYear = right.startYear; |
+ dstSavings = right.dstSavings; |
+ useDaylight = right.useDaylight; |
+ clearTransitionRules(); |
+ } |
+ return *this; |
+} |
+ |
+// ------------------------------------- |
+ |
+UBool |
+SimpleTimeZone::operator==(const TimeZone& that) const |
+{ |
+ return ((this == &that) || |
+ (typeid(*this) == typeid(that) && |
+ TimeZone::operator==(that) && |
+ hasSameRules(that))); |
+} |
+ |
+// ------------------------------------- |
+ |
+// Called by TimeZone::createDefault() inside a Mutex - be careful. |
+TimeZone* |
+SimpleTimeZone::clone() const |
+{ |
+ return new SimpleTimeZone(*this); |
+} |
+ |
+// ------------------------------------- |
+ |
+/** |
+ * Sets the daylight savings starting year, that is, the year this time zone began |
+ * observing its specified daylight savings time rules. The time zone is considered |
+ * not to observe daylight savings time prior to that year; SimpleTimeZone doesn't |
+ * support historical daylight-savings-time rules. |
+ * @param year the daylight savings starting year. |
+ */ |
+void |
+SimpleTimeZone::setStartYear(int32_t year) |
+{ |
+ startYear = year; |
+ transitionRulesInitialized = FALSE; |
+} |
+ |
+// ------------------------------------- |
+ |
+/** |
+ * Sets the daylight savings starting rule. For example, in the U.S., Daylight Savings |
+ * Time starts at the first Sunday in April, at 2 AM in standard time. |
+ * Therefore, you can set the start rule by calling: |
+ * setStartRule(TimeFields.APRIL, 1, TimeFields.SUNDAY, 2*60*60*1000); |
+ * The dayOfWeekInMonth and dayOfWeek parameters together specify how to calculate |
+ * the exact starting date. Their exact meaning depend on their respective signs, |
+ * allowing various types of rules to be constructed, as follows:<ul> |
+ * <li>If both dayOfWeekInMonth and dayOfWeek are positive, they specify the |
+ * day of week in the month (e.g., (2, WEDNESDAY) is the second Wednesday |
+ * of the month). |
+ * <li>If dayOfWeek is positive and dayOfWeekInMonth is negative, they specify |
+ * the day of week in the month counting backward from the end of the month. |
+ * (e.g., (-1, MONDAY) is the last Monday in the month) |
+ * <li>If dayOfWeek is zero and dayOfWeekInMonth is positive, dayOfWeekInMonth |
+ * specifies the day of the month, regardless of what day of the week it is. |
+ * (e.g., (10, 0) is the tenth day of the month) |
+ * <li>If dayOfWeek is zero and dayOfWeekInMonth is negative, dayOfWeekInMonth |
+ * specifies the day of the month counting backward from the end of the |
+ * month, regardless of what day of the week it is (e.g., (-2, 0) is the |
+ * next-to-last day of the month). |
+ * <li>If dayOfWeek is negative and dayOfWeekInMonth is positive, they specify the |
+ * first specified day of the week on or after the specfied day of the month. |
+ * (e.g., (15, -SUNDAY) is the first Sunday after the 15th of the month |
+ * [or the 15th itself if the 15th is a Sunday].) |
+ * <li>If dayOfWeek and DayOfWeekInMonth are both negative, they specify the |
+ * last specified day of the week on or before the specified day of the month. |
+ * (e.g., (-20, -TUESDAY) is the last Tuesday before the 20th of the month |
+ * [or the 20th itself if the 20th is a Tuesday].)</ul> |
+ * @param month the daylight savings starting month. Month is 0-based. |
+ * eg, 0 for January. |
+ * @param dayOfWeekInMonth the daylight savings starting |
+ * day-of-week-in-month. Please see the member description for an example. |
+ * @param dayOfWeek the daylight savings starting day-of-week. Please see |
+ * the member description for an example. |
+ * @param time the daylight savings starting time. Please see the member |
+ * description for an example. |
+ */ |
+ |
+void |
+SimpleTimeZone::setStartRule(int32_t month, int32_t dayOfWeekInMonth, int32_t dayOfWeek, |
+ int32_t time, TimeMode mode, UErrorCode& status) |
+{ |
+ startMonth = (int8_t)month; |
+ startDay = (int8_t)dayOfWeekInMonth; |
+ startDayOfWeek = (int8_t)dayOfWeek; |
+ startTime = time; |
+ startTimeMode = mode; |
+ decodeStartRule(status); |
+ transitionRulesInitialized = FALSE; |
+} |
+ |
+// ------------------------------------- |
+ |
+void |
+SimpleTimeZone::setStartRule(int32_t month, int32_t dayOfMonth, |
+ int32_t time, TimeMode mode, UErrorCode& status) |
+{ |
+ setStartRule(month, dayOfMonth, 0, time, mode, status); |
+} |
+ |
+// ------------------------------------- |
+ |
+void |
+SimpleTimeZone::setStartRule(int32_t month, int32_t dayOfMonth, int32_t dayOfWeek, |
+ int32_t time, TimeMode mode, UBool after, UErrorCode& status) |
+{ |
+ setStartRule(month, after ? dayOfMonth : -dayOfMonth, |
+ -dayOfWeek, time, mode, status); |
+} |
+ |
+// ------------------------------------- |
+ |
+/** |
+ * Sets the daylight savings ending rule. For example, in the U.S., Daylight |
+ * Savings Time ends at the last (-1) Sunday in October, at 2 AM in standard time. |
+ * Therefore, you can set the end rule by calling: |
+ * setEndRule(TimeFields.OCTOBER, -1, TimeFields.SUNDAY, 2*60*60*1000); |
+ * Various other types of rules can be specified by manipulating the dayOfWeek |
+ * and dayOfWeekInMonth parameters. For complete details, see the documentation |
+ * for setStartRule(). |
+ * @param month the daylight savings ending month. Month is 0-based. |
+ * eg, 0 for January. |
+ * @param dayOfWeekInMonth the daylight savings ending |
+ * day-of-week-in-month. See setStartRule() for a complete explanation. |
+ * @param dayOfWeek the daylight savings ending day-of-week. See setStartRule() |
+ * for a complete explanation. |
+ * @param time the daylight savings ending time. Please see the member |
+ * description for an example. |
+ */ |
+ |
+void |
+SimpleTimeZone::setEndRule(int32_t month, int32_t dayOfWeekInMonth, int32_t dayOfWeek, |
+ int32_t time, TimeMode mode, UErrorCode& status) |
+{ |
+ endMonth = (int8_t)month; |
+ endDay = (int8_t)dayOfWeekInMonth; |
+ endDayOfWeek = (int8_t)dayOfWeek; |
+ endTime = time; |
+ endTimeMode = mode; |
+ decodeEndRule(status); |
+ transitionRulesInitialized = FALSE; |
+} |
+ |
+// ------------------------------------- |
+ |
+void |
+SimpleTimeZone::setEndRule(int32_t month, int32_t dayOfMonth, |
+ int32_t time, TimeMode mode, UErrorCode& status) |
+{ |
+ setEndRule(month, dayOfMonth, 0, time, mode, status); |
+} |
+ |
+// ------------------------------------- |
+ |
+void |
+SimpleTimeZone::setEndRule(int32_t month, int32_t dayOfMonth, int32_t dayOfWeek, |
+ int32_t time, TimeMode mode, UBool after, UErrorCode& status) |
+{ |
+ setEndRule(month, after ? dayOfMonth : -dayOfMonth, |
+ -dayOfWeek, time, mode, status); |
+} |
+ |
+// ------------------------------------- |
+ |
+int32_t |
+SimpleTimeZone::getOffset(uint8_t era, int32_t year, int32_t month, int32_t day, |
+ uint8_t dayOfWeek, int32_t millis, UErrorCode& status) const |
+{ |
+ // Check the month before calling Grego::monthLength(). This |
+ // duplicates the test that occurs in the 7-argument getOffset(), |
+ // however, this is unavoidable. We don't mind because this method, in |
+ // fact, should not be called; internal code should always call the |
+ // 7-argument getOffset(), and outside code should use Calendar.get(int |
+ // field) with fields ZONE_OFFSET and DST_OFFSET. We can't get rid of |
+ // this method because it's public API. - liu 8/10/98 |
+ if(month < UCAL_JANUARY || month > UCAL_DECEMBER) { |
+ status = U_ILLEGAL_ARGUMENT_ERROR; |
+ return 0; |
+ } |
+ |
+ return getOffset(era, year, month, day, dayOfWeek, millis, Grego::monthLength(year, month), status); |
+} |
+ |
+int32_t |
+SimpleTimeZone::getOffset(uint8_t era, int32_t year, int32_t month, int32_t day, |
+ uint8_t dayOfWeek, int32_t millis, |
+ int32_t /*monthLength*/, UErrorCode& status) const |
+{ |
+ // Check the month before calling Grego::monthLength(). This |
+ // duplicates a test that occurs in the 9-argument getOffset(), |
+ // however, this is unavoidable. We don't mind because this method, in |
+ // fact, should not be called; internal code should always call the |
+ // 9-argument getOffset(), and outside code should use Calendar.get(int |
+ // field) with fields ZONE_OFFSET and DST_OFFSET. We can't get rid of |
+ // this method because it's public API. - liu 8/10/98 |
+ if (month < UCAL_JANUARY |
+ || month > UCAL_DECEMBER) { |
+ status = U_ILLEGAL_ARGUMENT_ERROR; |
+ return -1; |
+ } |
+ |
+ // We ignore monthLength because it can be derived from year and month. |
+ // This is so that February in leap years is calculated correctly. |
+ // We keep this argument in this function for backwards compatibility. |
+ return getOffset(era, year, month, day, dayOfWeek, millis, |
+ Grego::monthLength(year, month), |
+ Grego::previousMonthLength(year, month), |
+ status); |
+} |
+ |
+int32_t |
+SimpleTimeZone::getOffset(uint8_t era, int32_t year, int32_t month, int32_t day, |
+ uint8_t dayOfWeek, int32_t millis, |
+ int32_t monthLength, int32_t prevMonthLength, |
+ UErrorCode& status) const |
+{ |
+ if(U_FAILURE(status)) return 0; |
+ |
+ if ((era != GregorianCalendar::AD && era != GregorianCalendar::BC) |
+ || month < UCAL_JANUARY |
+ || month > UCAL_DECEMBER |
+ || day < 1 |
+ || day > monthLength |
+ || dayOfWeek < UCAL_SUNDAY |
+ || dayOfWeek > UCAL_SATURDAY |
+ || millis < 0 |
+ || millis >= U_MILLIS_PER_DAY |
+ || monthLength < 28 |
+ || monthLength > 31 |
+ || prevMonthLength < 28 |
+ || prevMonthLength > 31) { |
+ status = U_ILLEGAL_ARGUMENT_ERROR; |
+ return -1; |
+ } |
+ |
+ int32_t result = rawOffset; |
+ |
+ // Bail out if we are before the onset of daylight savings time |
+ if(!useDaylight || year < startYear || era != GregorianCalendar::AD) |
+ return result; |
+ |
+ // Check for southern hemisphere. We assume that the start and end |
+ // month are different. |
+ UBool southern = (startMonth > endMonth); |
+ |
+ // Compare the date to the starting and ending rules.+1 = date>rule, -1 |
+ // = date<rule, 0 = date==rule. |
+ int32_t startCompare = compareToRule((int8_t)month, (int8_t)monthLength, (int8_t)prevMonthLength, |
+ (int8_t)day, (int8_t)dayOfWeek, millis, |
+ startTimeMode == UTC_TIME ? -rawOffset : 0, |
+ startMode, (int8_t)startMonth, (int8_t)startDayOfWeek, |
+ (int8_t)startDay, startTime); |
+ int32_t endCompare = 0; |
+ |
+ /* We don't always have to compute endCompare. For many instances, |
+ * startCompare is enough to determine if we are in DST or not. In the |
+ * northern hemisphere, if we are before the start rule, we can't have |
+ * DST. In the southern hemisphere, if we are after the start rule, we |
+ * must have DST. This is reflected in the way the next if statement |
+ * (not the one immediately following) short circuits. */ |
+ if(southern != (startCompare >= 0)) { |
+ endCompare = compareToRule((int8_t)month, (int8_t)monthLength, (int8_t)prevMonthLength, |
+ (int8_t)day, (int8_t)dayOfWeek, millis, |
+ endTimeMode == WALL_TIME ? dstSavings : |
+ (endTimeMode == UTC_TIME ? -rawOffset : 0), |
+ endMode, (int8_t)endMonth, (int8_t)endDayOfWeek, |
+ (int8_t)endDay, endTime); |
+ } |
+ |
+ // Check for both the northern and southern hemisphere cases. We |
+ // assume that in the northern hemisphere, the start rule is before the |
+ // end rule within the calendar year, and vice versa for the southern |
+ // hemisphere. |
+ if ((!southern && (startCompare >= 0 && endCompare < 0)) || |
+ (southern && (startCompare >= 0 || endCompare < 0))) |
+ result += dstSavings; |
+ |
+ return result; |
+} |
+ |
+void |
+SimpleTimeZone::getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt, |
+ int32_t& rawOffsetGMT, int32_t& savingsDST, UErrorCode& status) /*const*/ { |
+ if (U_FAILURE(status)) { |
+ return; |
+ } |
+ |
+ rawOffsetGMT = getRawOffset(); |
+ int32_t year, month, dom, dow; |
+ double day = uprv_floor(date / U_MILLIS_PER_DAY); |
+ int32_t millis = (int32_t) (date - day * U_MILLIS_PER_DAY); |
+ |
+ Grego::dayToFields(day, year, month, dom, dow); |
+ |
+ savingsDST = getOffset(GregorianCalendar::AD, year, month, dom, |
+ (uint8_t) dow, millis, |
+ Grego::monthLength(year, month), |
+ status) - rawOffsetGMT; |
+ if (U_FAILURE(status)) { |
+ return; |
+ } |
+ |
+ UBool recalc = FALSE; |
+ |
+ // Now we need some adjustment |
+ if (savingsDST > 0) { |
+ if ((nonExistingTimeOpt & kStdDstMask) == kStandard |
+ || ((nonExistingTimeOpt & kStdDstMask) != kDaylight && (nonExistingTimeOpt & kFormerLatterMask) != kLatter)) { |
+ date -= getDSTSavings(); |
+ recalc = TRUE; |
+ } |
+ } else { |
+ if ((duplicatedTimeOpt & kStdDstMask) == kDaylight |
+ || ((duplicatedTimeOpt & kStdDstMask) != kStandard && (duplicatedTimeOpt & kFormerLatterMask) == kFormer)) { |
+ date -= getDSTSavings(); |
+ recalc = TRUE; |
+ } |
+ } |
+ if (recalc) { |
+ day = uprv_floor(date / U_MILLIS_PER_DAY); |
+ millis = (int32_t) (date - day * U_MILLIS_PER_DAY); |
+ Grego::dayToFields(day, year, month, dom, dow); |
+ savingsDST = getOffset(GregorianCalendar::AD, year, month, dom, |
+ (uint8_t) dow, millis, |
+ Grego::monthLength(year, month), |
+ status) - rawOffsetGMT; |
+ } |
+} |
+ |
+// ------------------------------------- |
+ |
+/** |
+ * Compare a given date in the year to a rule. Return 1, 0, or -1, depending |
+ * on whether the date is after, equal to, or before the rule date. The |
+ * millis are compared directly against the ruleMillis, so any |
+ * standard-daylight adjustments must be handled by the caller. |
+ * |
+ * @return 1 if the date is after the rule date, -1 if the date is before |
+ * the rule date, or 0 if the date is equal to the rule date. |
+ */ |
+int32_t |
+SimpleTimeZone::compareToRule(int8_t month, int8_t monthLen, int8_t prevMonthLen, |
+ int8_t dayOfMonth, |
+ int8_t dayOfWeek, int32_t millis, int32_t millisDelta, |
+ EMode ruleMode, int8_t ruleMonth, int8_t ruleDayOfWeek, |
+ int8_t ruleDay, int32_t ruleMillis) |
+{ |
+ // Make adjustments for startTimeMode and endTimeMode |
+ millis += millisDelta; |
+ while (millis >= U_MILLIS_PER_DAY) { |
+ millis -= U_MILLIS_PER_DAY; |
+ ++dayOfMonth; |
+ dayOfWeek = (int8_t)(1 + (dayOfWeek % 7)); // dayOfWeek is one-based |
+ if (dayOfMonth > monthLen) { |
+ dayOfMonth = 1; |
+ /* When incrementing the month, it is desirible to overflow |
+ * from DECEMBER to DECEMBER+1, since we use the result to |
+ * compare against a real month. Wraparound of the value |
+ * leads to bug 4173604. */ |
+ ++month; |
+ } |
+ } |
+ while (millis < 0) { |
+ millis += U_MILLIS_PER_DAY; |
+ --dayOfMonth; |
+ dayOfWeek = (int8_t)(1 + ((dayOfWeek+5) % 7)); // dayOfWeek is one-based |
+ if (dayOfMonth < 1) { |
+ dayOfMonth = prevMonthLen; |
+ --month; |
+ } |
+ } |
+ |
+ // first compare months. If they're different, we don't have to worry about days |
+ // and times |
+ if (month < ruleMonth) return -1; |
+ else if (month > ruleMonth) return 1; |
+ |
+ // calculate the actual day of month for the rule |
+ int32_t ruleDayOfMonth = 0; |
+ |
+ // Adjust the ruleDay to the monthLen, for non-leap year February 29 rule days. |
+ if (ruleDay > monthLen) { |
+ ruleDay = monthLen; |
+ } |
+ |
+ switch (ruleMode) |
+ { |
+ // if the mode is day-of-month, the day of month is given |
+ case DOM_MODE: |
+ ruleDayOfMonth = ruleDay; |
+ break; |
+ |
+ // if the mode is day-of-week-in-month, calculate the day-of-month from it |
+ case DOW_IN_MONTH_MODE: |
+ // In this case ruleDay is the day-of-week-in-month (this code is using |
+ // the dayOfWeek and dayOfMonth parameters to figure out the day-of-week |
+ // of the first day of the month, so it's trusting that they're really |
+ // consistent with each other) |
+ if (ruleDay > 0) |
+ ruleDayOfMonth = 1 + (ruleDay - 1) * 7 + |
+ (7 + ruleDayOfWeek - (dayOfWeek - dayOfMonth + 1)) % 7; |
+ |
+ // if ruleDay is negative (we assume it's not zero here), we have to do |
+ // the same calculation figuring backward from the last day of the month. |
+ else |
+ { |
+ // (again, this code is trusting that dayOfWeek and dayOfMonth are |
+ // consistent with each other here, since we're using them to figure |
+ // the day of week of the first of the month) |
+ ruleDayOfMonth = monthLen + (ruleDay + 1) * 7 - |
+ (7 + (dayOfWeek + monthLen - dayOfMonth) - ruleDayOfWeek) % 7; |
+ } |
+ break; |
+ |
+ case DOW_GE_DOM_MODE: |
+ ruleDayOfMonth = ruleDay + |
+ (49 + ruleDayOfWeek - ruleDay - dayOfWeek + dayOfMonth) % 7; |
+ break; |
+ |
+ case DOW_LE_DOM_MODE: |
+ ruleDayOfMonth = ruleDay - |
+ (49 - ruleDayOfWeek + ruleDay + dayOfWeek - dayOfMonth) % 7; |
+ // Note at this point ruleDayOfMonth may be <1, although it will |
+ // be >=1 for well-formed rules. |
+ break; |
+ } |
+ |
+ // now that we have a real day-in-month for the rule, we can compare days... |
+ if (dayOfMonth < ruleDayOfMonth) return -1; |
+ else if (dayOfMonth > ruleDayOfMonth) return 1; |
+ |
+ // ...and if they're equal, we compare times |
+ if (millis < ruleMillis) return -1; |
+ else if (millis > ruleMillis) return 1; |
+ else return 0; |
+} |
+ |
+// ------------------------------------- |
+ |
+int32_t |
+SimpleTimeZone::getRawOffset() const |
+{ |
+ return rawOffset; |
+} |
+ |
+// ------------------------------------- |
+ |
+void |
+SimpleTimeZone::setRawOffset(int32_t offsetMillis) |
+{ |
+ rawOffset = offsetMillis; |
+ transitionRulesInitialized = FALSE; |
+} |
+ |
+// ------------------------------------- |
+ |
+void |
+SimpleTimeZone::setDSTSavings(int32_t millisSavedDuringDST, UErrorCode& status) |
+{ |
+ if (millisSavedDuringDST <= 0) { |
+ status = U_ILLEGAL_ARGUMENT_ERROR; |
+ } |
+ else { |
+ dstSavings = millisSavedDuringDST; |
+ } |
+ transitionRulesInitialized = FALSE; |
+} |
+ |
+// ------------------------------------- |
+ |
+int32_t |
+SimpleTimeZone::getDSTSavings() const |
+{ |
+ return dstSavings; |
+} |
+ |
+// ------------------------------------- |
+ |
+UBool |
+SimpleTimeZone::useDaylightTime() const |
+{ |
+ return useDaylight; |
+} |
+ |
+// ------------------------------------- |
+ |
+/** |
+ * Overrides TimeZone |
+ * Queries if the given date is in Daylight Savings Time. |
+ */ |
+UBool SimpleTimeZone::inDaylightTime(UDate date, UErrorCode& status) const |
+{ |
+ // This method is wasteful since it creates a new GregorianCalendar and |
+ // deletes it each time it is called. However, this is a deprecated method |
+ // and provided only for Java compatibility as of 8/6/97 [LIU]. |
+ if (U_FAILURE(status)) return FALSE; |
+ GregorianCalendar *gc = new GregorianCalendar(*this, status); |
+ /* test for NULL */ |
+ if (gc == 0) { |
+ status = U_MEMORY_ALLOCATION_ERROR; |
+ return FALSE; |
+ } |
+ gc->setTime(date, status); |
+ UBool result = gc->inDaylightTime(status); |
+ delete gc; |
+ return result; |
+} |
+ |
+// ------------------------------------- |
+ |
+/** |
+ * Return true if this zone has the same rules and offset as another zone. |
+ * @param other the TimeZone object to be compared with |
+ * @return true if the given zone has the same rules and offset as this one |
+ */ |
+UBool |
+SimpleTimeZone::hasSameRules(const TimeZone& other) const |
+{ |
+ if (this == &other) return TRUE; |
+ if (typeid(*this) != typeid(other)) return FALSE; |
+ SimpleTimeZone *that = (SimpleTimeZone*)&other; |
+ return rawOffset == that->rawOffset && |
+ useDaylight == that->useDaylight && |
+ (!useDaylight |
+ // Only check rules if using DST |
+ || (dstSavings == that->dstSavings && |
+ startMode == that->startMode && |
+ startMonth == that->startMonth && |
+ startDay == that->startDay && |
+ startDayOfWeek == that->startDayOfWeek && |
+ startTime == that->startTime && |
+ startTimeMode == that->startTimeMode && |
+ endMode == that->endMode && |
+ endMonth == that->endMonth && |
+ endDay == that->endDay && |
+ endDayOfWeek == that->endDayOfWeek && |
+ endTime == that->endTime && |
+ endTimeMode == that->endTimeMode && |
+ startYear == that->startYear)); |
+} |
+ |
+// ------------------------------------- |
+ |
+//---------------------------------------------------------------------- |
+// Rule representation |
+// |
+// We represent the following flavors of rules: |
+// 5 the fifth of the month |
+// lastSun the last Sunday in the month |
+// lastMon the last Monday in the month |
+// Sun>=8 first Sunday on or after the eighth |
+// Sun<=25 last Sunday on or before the 25th |
+// This is further complicated by the fact that we need to remain |
+// backward compatible with the 1.1 FCS. Finally, we need to minimize |
+// API changes. In order to satisfy these requirements, we support |
+// three representation systems, and we translate between them. |
+// |
+// INTERNAL REPRESENTATION |
+// This is the format SimpleTimeZone objects take after construction or |
+// streaming in is complete. Rules are represented directly, using an |
+// unencoded format. We will discuss the start rule only below; the end |
+// rule is analogous. |
+// startMode Takes on enumerated values DAY_OF_MONTH, |
+// DOW_IN_MONTH, DOW_AFTER_DOM, or DOW_BEFORE_DOM. |
+// startDay The day of the month, or for DOW_IN_MONTH mode, a |
+// value indicating which DOW, such as +1 for first, |
+// +2 for second, -1 for last, etc. |
+// startDayOfWeek The day of the week. Ignored for DAY_OF_MONTH. |
+// |
+// ENCODED REPRESENTATION |
+// This is the format accepted by the constructor and by setStartRule() |
+// and setEndRule(). It uses various combinations of positive, negative, |
+// and zero values to encode the different rules. This representation |
+// allows us to specify all the different rule flavors without altering |
+// the API. |
+// MODE startMonth startDay startDayOfWeek |
+// DOW_IN_MONTH_MODE >=0 !=0 >0 |
+// DOM_MODE >=0 >0 ==0 |
+// DOW_GE_DOM_MODE >=0 >0 <0 |
+// DOW_LE_DOM_MODE >=0 <0 <0 |
+// (no DST) don't care ==0 don't care |
+// |
+// STREAMED REPRESENTATION |
+// We must retain binary compatibility with the 1.1 FCS. The 1.1 code only |
+// handles DOW_IN_MONTH_MODE and non-DST mode, the latter indicated by the |
+// flag useDaylight. When we stream an object out, we translate into an |
+// approximate DOW_IN_MONTH_MODE representation so the object can be parsed |
+// and used by 1.1 code. Following that, we write out the full |
+// representation separately so that contemporary code can recognize and |
+// parse it. The full representation is written in a "packed" format, |
+// consisting of a version number, a length, and an array of bytes. Future |
+// versions of this class may specify different versions. If they wish to |
+// include additional data, they should do so by storing them after the |
+// packed representation below. |
+//---------------------------------------------------------------------- |
+ |
+/** |
+ * Given a set of encoded rules in startDay and startDayOfMonth, decode |
+ * them and set the startMode appropriately. Do the same for endDay and |
+ * endDayOfMonth. Upon entry, the day of week variables may be zero or |
+ * negative, in order to indicate special modes. The day of month |
+ * variables may also be negative. Upon exit, the mode variables will be |
+ * set, and the day of week and day of month variables will be positive. |
+ * This method also recognizes a startDay or endDay of zero as indicating |
+ * no DST. |
+ */ |
+void |
+SimpleTimeZone::decodeRules(UErrorCode& status) |
+{ |
+ decodeStartRule(status); |
+ decodeEndRule(status); |
+} |
+ |
+/** |
+ * Decode the start rule and validate the parameters. The parameters are |
+ * expected to be in encoded form, which represents the various rule modes |
+ * by negating or zeroing certain values. Representation formats are: |
+ * <p> |
+ * <pre> |
+ * DOW_IN_MONTH DOM DOW>=DOM DOW<=DOM no DST |
+ * ------------ ----- -------- -------- ---------- |
+ * month 0..11 same same same don't care |
+ * day -5..5 1..31 1..31 -1..-31 0 |
+ * dayOfWeek 1..7 0 -1..-7 -1..-7 don't care |
+ * time 0..ONEDAY same same same don't care |
+ * </pre> |
+ * The range for month does not include UNDECIMBER since this class is |
+ * really specific to GregorianCalendar, which does not use that month. |
+ * The range for time includes ONEDAY (vs. ending at ONEDAY-1) because the |
+ * end rule is an exclusive limit point. That is, the range of times that |
+ * are in DST include those >= the start and < the end. For this reason, |
+ * it should be possible to specify an end of ONEDAY in order to include the |
+ * entire day. Although this is equivalent to time 0 of the following day, |
+ * it's not always possible to specify that, for example, on December 31. |
+ * While arguably the start range should still be 0..ONEDAY-1, we keep |
+ * the start and end ranges the same for consistency. |
+ */ |
+void |
+SimpleTimeZone::decodeStartRule(UErrorCode& status) |
+{ |
+ if(U_FAILURE(status)) return; |
+ |
+ useDaylight = (UBool)((startDay != 0) && (endDay != 0) ? TRUE : FALSE); |
+ if (useDaylight && dstSavings == 0) { |
+ dstSavings = U_MILLIS_PER_HOUR; |
+ } |
+ if (startDay != 0) { |
+ if (startMonth < UCAL_JANUARY || startMonth > UCAL_DECEMBER) { |
+ status = U_ILLEGAL_ARGUMENT_ERROR; |
+ return; |
+ } |
+ if (startTime < 0 || startTime > U_MILLIS_PER_DAY || |
+ startTimeMode < WALL_TIME || startTimeMode > UTC_TIME) { |
+ status = U_ILLEGAL_ARGUMENT_ERROR; |
+ return; |
+ } |
+ if (startDayOfWeek == 0) { |
+ startMode = DOM_MODE; |
+ } else { |
+ if (startDayOfWeek > 0) { |
+ startMode = DOW_IN_MONTH_MODE; |
+ } else { |
+ startDayOfWeek = (int8_t)-startDayOfWeek; |
+ if (startDay > 0) { |
+ startMode = DOW_GE_DOM_MODE; |
+ } else { |
+ startDay = (int8_t)-startDay; |
+ startMode = DOW_LE_DOM_MODE; |
+ } |
+ } |
+ if (startDayOfWeek > UCAL_SATURDAY) { |
+ status = U_ILLEGAL_ARGUMENT_ERROR; |
+ return; |
+ } |
+ } |
+ if (startMode == DOW_IN_MONTH_MODE) { |
+ if (startDay < -5 || startDay > 5) { |
+ status = U_ILLEGAL_ARGUMENT_ERROR; |
+ return; |
+ } |
+ } else if (startDay<1 || startDay > STATICMONTHLENGTH[startMonth]) { |
+ status = U_ILLEGAL_ARGUMENT_ERROR; |
+ return; |
+ } |
+ } |
+} |
+ |
+/** |
+ * Decode the end rule and validate the parameters. This method is exactly |
+ * analogous to decodeStartRule(). |
+ * @see decodeStartRule |
+ */ |
+void |
+SimpleTimeZone::decodeEndRule(UErrorCode& status) |
+{ |
+ if(U_FAILURE(status)) return; |
+ |
+ useDaylight = (UBool)((startDay != 0) && (endDay != 0) ? TRUE : FALSE); |
+ if (useDaylight && dstSavings == 0) { |
+ dstSavings = U_MILLIS_PER_HOUR; |
+ } |
+ if (endDay != 0) { |
+ if (endMonth < UCAL_JANUARY || endMonth > UCAL_DECEMBER) { |
+ status = U_ILLEGAL_ARGUMENT_ERROR; |
+ return; |
+ } |
+ if (endTime < 0 || endTime > U_MILLIS_PER_DAY || |
+ endTimeMode < WALL_TIME || endTimeMode > UTC_TIME) { |
+ status = U_ILLEGAL_ARGUMENT_ERROR; |
+ return; |
+ } |
+ if (endDayOfWeek == 0) { |
+ endMode = DOM_MODE; |
+ } else { |
+ if (endDayOfWeek > 0) { |
+ endMode = DOW_IN_MONTH_MODE; |
+ } else { |
+ endDayOfWeek = (int8_t)-endDayOfWeek; |
+ if (endDay > 0) { |
+ endMode = DOW_GE_DOM_MODE; |
+ } else { |
+ endDay = (int8_t)-endDay; |
+ endMode = DOW_LE_DOM_MODE; |
+ } |
+ } |
+ if (endDayOfWeek > UCAL_SATURDAY) { |
+ status = U_ILLEGAL_ARGUMENT_ERROR; |
+ return; |
+ } |
+ } |
+ if (endMode == DOW_IN_MONTH_MODE) { |
+ if (endDay < -5 || endDay > 5) { |
+ status = U_ILLEGAL_ARGUMENT_ERROR; |
+ return; |
+ } |
+ } else if (endDay<1 || endDay > STATICMONTHLENGTH[endMonth]) { |
+ status = U_ILLEGAL_ARGUMENT_ERROR; |
+ return; |
+ } |
+ } |
+} |
+ |
+UBool |
+SimpleTimeZone::getNextTransition(UDate base, UBool inclusive, TimeZoneTransition& result) /*const*/ { |
+ if (!useDaylight) { |
+ return FALSE; |
+ } |
+ |
+ UErrorCode status = U_ZERO_ERROR; |
+ initTransitionRules(status); |
+ if (U_FAILURE(status)) { |
+ return FALSE; |
+ } |
+ |
+ UDate firstTransitionTime = firstTransition->getTime(); |
+ if (base < firstTransitionTime || (inclusive && base == firstTransitionTime)) { |
+ result = *firstTransition; |
+ } |
+ UDate stdDate, dstDate; |
+ UBool stdAvail = stdRule->getNextStart(base, dstRule->getRawOffset(), dstRule->getDSTSavings(), inclusive, stdDate); |
+ UBool dstAvail = dstRule->getNextStart(base, stdRule->getRawOffset(), stdRule->getDSTSavings(), inclusive, dstDate); |
+ if (stdAvail && (!dstAvail || stdDate < dstDate)) { |
+ result.setTime(stdDate); |
+ result.setFrom((const TimeZoneRule&)*dstRule); |
+ result.setTo((const TimeZoneRule&)*stdRule); |
+ return TRUE; |
+ } |
+ if (dstAvail && (!stdAvail || dstDate < stdDate)) { |
+ result.setTime(dstDate); |
+ result.setFrom((const TimeZoneRule&)*stdRule); |
+ result.setTo((const TimeZoneRule&)*dstRule); |
+ return TRUE; |
+ } |
+ return FALSE; |
+} |
+ |
+UBool |
+SimpleTimeZone::getPreviousTransition(UDate base, UBool inclusive, TimeZoneTransition& result) /*const*/ { |
+ if (!useDaylight) { |
+ return FALSE; |
+ } |
+ |
+ UErrorCode status = U_ZERO_ERROR; |
+ initTransitionRules(status); |
+ if (U_FAILURE(status)) { |
+ return FALSE; |
+ } |
+ |
+ UDate firstTransitionTime = firstTransition->getTime(); |
+ if (base < firstTransitionTime || (!inclusive && base == firstTransitionTime)) { |
+ return FALSE; |
+ } |
+ UDate stdDate, dstDate; |
+ UBool stdAvail = stdRule->getPreviousStart(base, dstRule->getRawOffset(), dstRule->getDSTSavings(), inclusive, stdDate); |
+ UBool dstAvail = dstRule->getPreviousStart(base, stdRule->getRawOffset(), stdRule->getDSTSavings(), inclusive, dstDate); |
+ if (stdAvail && (!dstAvail || stdDate > dstDate)) { |
+ result.setTime(stdDate); |
+ result.setFrom((const TimeZoneRule&)*dstRule); |
+ result.setTo((const TimeZoneRule&)*stdRule); |
+ return TRUE; |
+ } |
+ if (dstAvail && (!stdAvail || dstDate > stdDate)) { |
+ result.setTime(dstDate); |
+ result.setFrom((const TimeZoneRule&)*stdRule); |
+ result.setTo((const TimeZoneRule&)*dstRule); |
+ return TRUE; |
+ } |
+ return FALSE; |
+} |
+ |
+void |
+SimpleTimeZone::clearTransitionRules(void) { |
+ initialRule = NULL; |
+ firstTransition = NULL; |
+ stdRule = NULL; |
+ dstRule = NULL; |
+ transitionRulesInitialized = FALSE; |
+} |
+ |
+void |
+SimpleTimeZone::deleteTransitionRules(void) { |
+ if (initialRule != NULL) { |
+ delete initialRule; |
+ } |
+ if (firstTransition != NULL) { |
+ delete firstTransition; |
+ } |
+ if (stdRule != NULL) { |
+ delete stdRule; |
+ } |
+ if (dstRule != NULL) { |
+ delete dstRule; |
+ } |
+ clearTransitionRules(); |
+ } |
+ |
+void |
+SimpleTimeZone::initTransitionRules(UErrorCode& status) { |
+ if (U_FAILURE(status)) { |
+ return; |
+ } |
+ if (transitionRulesInitialized) { |
+ return; |
+ } |
+ deleteTransitionRules(); |
+ UnicodeString tzid; |
+ getID(tzid); |
+ |
+ if (useDaylight) { |
+ DateTimeRule* dtRule; |
+ DateTimeRule::TimeRuleType timeRuleType; |
+ UDate firstStdStart, firstDstStart; |
+ |
+ // Create a TimeZoneRule for daylight saving time |
+ timeRuleType = (startTimeMode == STANDARD_TIME) ? DateTimeRule::STANDARD_TIME : |
+ ((startTimeMode == UTC_TIME) ? DateTimeRule::UTC_TIME : DateTimeRule::WALL_TIME); |
+ switch (startMode) { |
+ case DOM_MODE: |
+ dtRule = new DateTimeRule(startMonth, startDay, startTime, timeRuleType); |
+ break; |
+ case DOW_IN_MONTH_MODE: |
+ dtRule = new DateTimeRule(startMonth, startDay, startDayOfWeek, startTime, timeRuleType); |
+ break; |
+ case DOW_GE_DOM_MODE: |
+ dtRule = new DateTimeRule(startMonth, startDay, startDayOfWeek, true, startTime, timeRuleType); |
+ break; |
+ case DOW_LE_DOM_MODE: |
+ dtRule = new DateTimeRule(startMonth, startDay, startDayOfWeek, false, startTime, timeRuleType); |
+ break; |
+ default: |
+ status = U_INVALID_STATE_ERROR; |
+ return; |
+ } |
+ // Check for Null pointer |
+ if (dtRule == NULL) { |
+ status = U_MEMORY_ALLOCATION_ERROR; |
+ return; |
+ } |
+ // For now, use ID + "(DST)" as the name |
+ dstRule = new AnnualTimeZoneRule(tzid+DST_STR, getRawOffset(), getDSTSavings(), |
+ dtRule, startYear, AnnualTimeZoneRule::MAX_YEAR); |
+ |
+ // Check for Null pointer |
+ if (dstRule == NULL) { |
+ status = U_MEMORY_ALLOCATION_ERROR; |
+ deleteTransitionRules(); |
+ return; |
+ } |
+ |
+ // Calculate the first DST start time |
+ dstRule->getFirstStart(getRawOffset(), 0, firstDstStart); |
+ |
+ // Create a TimeZoneRule for standard time |
+ timeRuleType = (endTimeMode == STANDARD_TIME) ? DateTimeRule::STANDARD_TIME : |
+ ((endTimeMode == UTC_TIME) ? DateTimeRule::UTC_TIME : DateTimeRule::WALL_TIME); |
+ switch (endMode) { |
+ case DOM_MODE: |
+ dtRule = new DateTimeRule(endMonth, endDay, endTime, timeRuleType); |
+ break; |
+ case DOW_IN_MONTH_MODE: |
+ dtRule = new DateTimeRule(endMonth, endDay, endDayOfWeek, endTime, timeRuleType); |
+ break; |
+ case DOW_GE_DOM_MODE: |
+ dtRule = new DateTimeRule(endMonth, endDay, endDayOfWeek, true, endTime, timeRuleType); |
+ break; |
+ case DOW_LE_DOM_MODE: |
+ dtRule = new DateTimeRule(endMonth, endDay, endDayOfWeek, false, endTime, timeRuleType); |
+ break; |
+ } |
+ |
+ // Check for Null pointer |
+ if (dtRule == NULL) { |
+ status = U_MEMORY_ALLOCATION_ERROR; |
+ deleteTransitionRules(); |
+ return; |
+ } |
+ // For now, use ID + "(STD)" as the name |
+ stdRule = new AnnualTimeZoneRule(tzid+STD_STR, getRawOffset(), 0, |
+ dtRule, startYear, AnnualTimeZoneRule::MAX_YEAR); |
+ |
+ //Check for Null pointer |
+ if (stdRule == NULL) { |
+ status = U_MEMORY_ALLOCATION_ERROR; |
+ deleteTransitionRules(); |
+ return; |
+ } |
+ |
+ // Calculate the first STD start time |
+ stdRule->getFirstStart(getRawOffset(), dstRule->getDSTSavings(), firstStdStart); |
+ |
+ // Create a TimeZoneRule for initial time |
+ if (firstStdStart < firstDstStart) { |
+ initialRule = new InitialTimeZoneRule(tzid+DST_STR, getRawOffset(), dstRule->getDSTSavings()); |
+ firstTransition = new TimeZoneTransition(firstStdStart, *initialRule, *stdRule); |
+ } else { |
+ initialRule = new InitialTimeZoneRule(tzid+STD_STR, getRawOffset(), 0); |
+ firstTransition = new TimeZoneTransition(firstDstStart, *initialRule, *dstRule); |
+ } |
+ // Check for null pointers. |
+ if (initialRule == NULL || firstTransition == NULL) { |
+ status = U_MEMORY_ALLOCATION_ERROR; |
+ deleteTransitionRules(); |
+ return; |
+ } |
+ |
+ } else { |
+ // Create a TimeZoneRule for initial time |
+ initialRule = new InitialTimeZoneRule(tzid, getRawOffset(), 0); |
+ // Check for null pointer. |
+ if (initialRule == NULL) { |
+ status = U_MEMORY_ALLOCATION_ERROR; |
+ deleteTransitionRules(); |
+ return; |
+ } |
+ } |
+ |
+ transitionRulesInitialized = true; |
+} |
+ |
+int32_t |
+SimpleTimeZone::countTransitionRules(UErrorCode& /*status*/) /*const*/ { |
+ return (useDaylight) ? 2 : 0; |
+} |
+ |
+void |
+SimpleTimeZone::getTimeZoneRules(const InitialTimeZoneRule*& initial, |
+ const TimeZoneRule* trsrules[], |
+ int32_t& trscount, |
+ UErrorCode& status) /*const*/ { |
+ if (U_FAILURE(status)) { |
+ return; |
+ } |
+ initTransitionRules(status); |
+ if (U_FAILURE(status)) { |
+ return; |
+ } |
+ initial = initialRule; |
+ int32_t cnt = 0; |
+ if (stdRule != NULL) { |
+ if (cnt < trscount) { |
+ trsrules[cnt++] = stdRule; |
+ } |
+ if (cnt < trscount) { |
+ trsrules[cnt++] = dstRule; |
+ } |
+ } |
+ trscount = cnt; |
+} |
+ |
+ |
+U_NAMESPACE_END |
+ |
+#endif /* #if !UCONFIG_NO_FORMATTING */ |
+ |
+//eof |
Property changes on: icu46/source/i18n/simpletz.cpp |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |