| 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
|
|
|
|
|