1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *******************************************************************************
38393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius * Copyright (C) 1997-2013, International Business Machines Corporation and
427f654740f2a26ad62a5c155af9199af9e69b889claireho * others. All Rights Reserved.
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *******************************************************************************
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * File SIMPLETZ.H
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Modification History:
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *   Date        Name        Description
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *   12/05/96    clhuang     Creation.
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *   04/21/97    aliu        Fixed miscellaneous bugs found by inspection and
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *                           testing.
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *   07/29/97    aliu        Ported source bodies back from Java version with
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *                           numerous feature enhancements and bug fixes.
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *   08/10/98    stephen     JDK 1.2 sync.
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *   09/17/98    stephen     Fixed getOffset() for last hour of year and DST
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *   12/02/99    aliu        Added TimeMode and constructor and setStart/EndRule
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *                           methods that take TimeMode. Whitespace cleanup.
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ********************************************************************************
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#include "utypeinfo.h"  // for 'typeid' to work
2527f654740f2a26ad62a5c155af9199af9e69b889claireho
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h"
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING
29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/simpletz.h"
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/gregocal.h"
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/smpdtfmt.h"
33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "gregoimp.h"
358393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#include "umutex.h"
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_BEGIN
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(SimpleTimeZone)
40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Use only for decodeStartRule() and decodeEndRule() where the year is not
42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// available. Set February to 29 days to accomodate rules with that date
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// and day-of-week-on-or-before-that-date mode (DOW_LE_DOM_MODE).
44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// The compareToRule() method adjusts to February 28 in non-leap years.
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// For actual getOffset() calculations, use Grego::monthLength() and
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Grego::previousMonthLength() which take leap years into account.
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// We handle leap years assuming always
49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Gregorian, since we know they didn't have daylight time when
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Gregorian calendar started.
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int8_t SimpleTimeZone::STATICMONTHLENGTH[] = {31,29,31,30,31,30,31,31,30,31,30,31};
52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar DST_STR[] = {0x0028,0x0044,0x0053,0x0054,0x0029,0}; // "(DST)"
54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar STD_STR[] = {0x0028,0x0053,0x0054,0x0044,0x0029,0}; // "(STD)"
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// *****************************************************************************
58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// class SimpleTimeZone
59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// *****************************************************************************
60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::SimpleTimeZone(int32_t rawOffsetGMT, const UnicodeString& ID)
63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru:   BasicTimeZone(ID),
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    startMonth(0),
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    startDay(0),
66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    startDayOfWeek(0),
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    startTime(0),
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    startTimeMode(WALL_TIME),
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    endTimeMode(WALL_TIME),
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    endMonth(0),
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    endDay(0),
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    endDayOfWeek(0),
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    endTime(0),
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    startYear(0),
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    rawOffset(rawOffsetGMT),
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    useDaylight(FALSE),
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    startMode(DOM_MODE),
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    endMode(DOM_MODE),
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    dstSavings(U_MILLIS_PER_HOUR)
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    clearTransitionRules();
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::SimpleTimeZone(int32_t rawOffsetGMT, const UnicodeString& ID,
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int8_t savingsStartMonth, int8_t savingsStartDay,
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int8_t savingsStartDayOfWeek, int32_t savingsStartTime,
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int8_t savingsEndMonth, int8_t savingsEndDay,
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int8_t savingsEndDayOfWeek, int32_t savingsEndTime,
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode& status)
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru:   BasicTimeZone(ID)
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    clearTransitionRules();
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    construct(rawOffsetGMT,
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              savingsStartMonth, savingsStartDay, savingsStartDayOfWeek,
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              savingsStartTime, WALL_TIME,
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              savingsEndMonth, savingsEndDay, savingsEndDayOfWeek,
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              savingsEndTime, WALL_TIME,
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              U_MILLIS_PER_HOUR, status);
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::SimpleTimeZone(int32_t rawOffsetGMT, const UnicodeString& ID,
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int8_t savingsStartMonth, int8_t savingsStartDay,
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int8_t savingsStartDayOfWeek, int32_t savingsStartTime,
108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int8_t savingsEndMonth, int8_t savingsEndDay,
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int8_t savingsEndDayOfWeek, int32_t savingsEndTime,
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t savingsDST, UErrorCode& status)
111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru:   BasicTimeZone(ID)
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    clearTransitionRules();
114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    construct(rawOffsetGMT,
115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              savingsStartMonth, savingsStartDay, savingsStartDayOfWeek,
116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              savingsStartTime, WALL_TIME,
117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              savingsEndMonth, savingsEndDay, savingsEndDayOfWeek,
118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              savingsEndTime, WALL_TIME,
119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              savingsDST, status);
120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::SimpleTimeZone(int32_t rawOffsetGMT, const UnicodeString& ID,
125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int8_t savingsStartMonth, int8_t savingsStartDay,
126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int8_t savingsStartDayOfWeek, int32_t savingsStartTime,
127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TimeMode savingsStartTimeMode,
128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int8_t savingsEndMonth, int8_t savingsEndDay,
129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int8_t savingsEndDayOfWeek, int32_t savingsEndTime,
130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TimeMode savingsEndTimeMode,
131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t savingsDST, UErrorCode& status)
132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru:   BasicTimeZone(ID)
133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    clearTransitionRules();
135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    construct(rawOffsetGMT,
136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              savingsStartMonth, savingsStartDay, savingsStartDayOfWeek,
137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              savingsStartTime, savingsStartTimeMode,
138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              savingsEndMonth, savingsEndDay, savingsEndDayOfWeek,
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              savingsEndTime, savingsEndTimeMode,
140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              savingsDST, status);
141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Internal construction method.
145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid SimpleTimeZone::construct(int32_t rawOffsetGMT,
147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                               int8_t savingsStartMonth,
148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                               int8_t savingsStartDay,
149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                               int8_t savingsStartDayOfWeek,
150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                               int32_t savingsStartTime,
151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                               TimeMode savingsStartTimeMode,
152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                               int8_t savingsEndMonth,
153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                               int8_t savingsEndDay,
154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                               int8_t savingsEndDayOfWeek,
155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                               int32_t savingsEndTime,
156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                               TimeMode savingsEndTimeMode,
157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                               int32_t savingsDST,
158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                               UErrorCode& status)
159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    this->rawOffset      = rawOffsetGMT;
161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    this->startMonth     = savingsStartMonth;
162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    this->startDay       = savingsStartDay;
163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    this->startDayOfWeek = savingsStartDayOfWeek;
164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    this->startTime      = savingsStartTime;
165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    this->startTimeMode  = savingsStartTimeMode;
166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    this->endMonth       = savingsEndMonth;
167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    this->endDay         = savingsEndDay;
168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    this->endDayOfWeek   = savingsEndDayOfWeek;
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    this->endTime        = savingsEndTime;
170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    this->endTimeMode    = savingsEndTimeMode;
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    this->dstSavings     = savingsDST;
172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    this->startYear      = 0;
173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    this->startMode      = DOM_MODE;
174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    this->endMode        = DOM_MODE;
175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    decodeRules(status);
177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (savingsDST <= 0) {
179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        status = U_ILLEGAL_ARGUMENT_ERROR;
180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::~SimpleTimeZone()
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    deleteTransitionRules();
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Called by TimeZone::createDefault(), then clone() inside a Mutex - be careful.
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::SimpleTimeZone(const SimpleTimeZone &source)
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru:   BasicTimeZone(source)
195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *this = source;
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Called by TimeZone::createDefault(), then clone() inside a Mutex - be careful.
202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone &
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::operator=(const SimpleTimeZone &right)
204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (this != &right)
206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        TimeZone::operator=(right);
208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        rawOffset      = right.rawOffset;
209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        startMonth     = right.startMonth;
210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        startDay       = right.startDay;
211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        startDayOfWeek = right.startDayOfWeek;
212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        startTime      = right.startTime;
213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        startTimeMode  = right.startTimeMode;
214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        startMode      = right.startMode;
215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        endMonth       = right.endMonth;
216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        endDay         = right.endDay;
217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        endDayOfWeek   = right.endDayOfWeek;
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        endTime        = right.endTime;
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        endTimeMode    = right.endTimeMode;
220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        endMode        = right.endMode;
221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        startYear      = right.startYear;
222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        dstSavings     = right.dstSavings;
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        useDaylight    = right.useDaylight;
224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        clearTransitionRules();
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::operator==(const TimeZone& that) const
233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return ((this == &that) ||
23527f654740f2a26ad62a5c155af9199af9e69b889claireho            (typeid(*this) == typeid(that) &&
236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            TimeZone::operator==(that) &&
237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            hasSameRules(that)));
238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Called by TimeZone::createDefault() inside a Mutex - be careful.
243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone*
244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::clone() const
245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return new SimpleTimeZone(*this);
247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Sets the daylight savings starting year, that is, the year this time zone began
253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * observing its specified daylight savings time rules.  The time zone is considered
254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * not to observe daylight savings time prior to that year; SimpleTimeZone doesn't
255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * support historical daylight-savings-time rules.
256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param year the daylight savings starting year.
257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::setStartYear(int32_t year)
260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    startYear = year;
262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    transitionRulesInitialized = FALSE;
263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Sets the daylight savings starting rule. For example, in the U.S., Daylight Savings
269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Time starts at the first Sunday in April, at 2 AM in standard time.
270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Therefore, you can set the start rule by calling:
271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * setStartRule(TimeFields.APRIL, 1, TimeFields.SUNDAY, 2*60*60*1000);
272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * The dayOfWeekInMonth and dayOfWeek parameters together specify how to calculate
273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * the exact starting date.  Their exact meaning depend on their respective signs,
274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * allowing various types of rules to be constructed, as follows:<ul>
275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *   <li>If both dayOfWeekInMonth and dayOfWeek are positive, they specify the
276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *       day of week in the month (e.g., (2, WEDNESDAY) is the second Wednesday
277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *       of the month).
278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *   <li>If dayOfWeek is positive and dayOfWeekInMonth is negative, they specify
279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *       the day of week in the month counting backward from the end of the month.
280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *       (e.g., (-1, MONDAY) is the last Monday in the month)
281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *   <li>If dayOfWeek is zero and dayOfWeekInMonth is positive, dayOfWeekInMonth
282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *       specifies the day of the month, regardless of what day of the week it is.
283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *       (e.g., (10, 0) is the tenth day of the month)
284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *   <li>If dayOfWeek is zero and dayOfWeekInMonth is negative, dayOfWeekInMonth
285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *       specifies the day of the month counting backward from the end of the
286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *       month, regardless of what day of the week it is (e.g., (-2, 0) is the
287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *       next-to-last day of the month).
288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *   <li>If dayOfWeek is negative and dayOfWeekInMonth is positive, they specify the
289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *       first specified day of the week on or after the specfied day of the month.
290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *       (e.g., (15, -SUNDAY) is the first Sunday after the 15th of the month
291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *       [or the 15th itself if the 15th is a Sunday].)
292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *   <li>If dayOfWeek and DayOfWeekInMonth are both negative, they specify the
293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *       last specified day of the week on or before the specified day of the month.
294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *       (e.g., (-20, -TUESDAY) is the last Tuesday before the 20th of the month
295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *       [or the 20th itself if the 20th is a Tuesday].)</ul>
296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param month the daylight savings starting month. Month is 0-based.
297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * eg, 0 for January.
298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param dayOfWeekInMonth the daylight savings starting
299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * day-of-week-in-month. Please see the member description for an example.
300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param dayOfWeek the daylight savings starting day-of-week. Please see
301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * the member description for an example.
302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param time the daylight savings starting time. Please see the member
303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * description for an example.
304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::setStartRule(int32_t month, int32_t dayOfWeekInMonth, int32_t dayOfWeek,
308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t time, TimeMode mode, UErrorCode& status)
309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    startMonth     = (int8_t)month;
311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    startDay       = (int8_t)dayOfWeekInMonth;
312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    startDayOfWeek = (int8_t)dayOfWeek;
313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    startTime      = time;
314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    startTimeMode  = mode;
315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    decodeStartRule(status);
316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    transitionRulesInitialized = FALSE;
317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::setStartRule(int32_t month, int32_t dayOfMonth,
323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t time, TimeMode mode, UErrorCode& status)
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setStartRule(month, dayOfMonth, 0, time, mode, status);
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::setStartRule(int32_t month, int32_t dayOfMonth, int32_t dayOfWeek,
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t time, TimeMode mode, UBool after, UErrorCode& status)
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setStartRule(month, after ? dayOfMonth : -dayOfMonth,
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 -dayOfWeek, time, mode, status);
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Sets the daylight savings ending rule. For example, in the U.S., Daylight
342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Savings Time ends at the last (-1) Sunday in October, at 2 AM in standard time.
343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Therefore, you can set the end rule by calling:
344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * setEndRule(TimeFields.OCTOBER, -1, TimeFields.SUNDAY, 2*60*60*1000);
345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Various other types of rules can be specified by manipulating the dayOfWeek
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * and dayOfWeekInMonth parameters.  For complete details, see the documentation
347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * for setStartRule().
348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param month the daylight savings ending month. Month is 0-based.
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * eg, 0 for January.
350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param dayOfWeekInMonth the daylight savings ending
351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * day-of-week-in-month. See setStartRule() for a complete explanation.
352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param dayOfWeek the daylight savings ending day-of-week. See setStartRule()
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * for a complete explanation.
354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param time the daylight savings ending time. Please see the member
355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * description for an example.
356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::setEndRule(int32_t month, int32_t dayOfWeekInMonth, int32_t dayOfWeek,
360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                           int32_t time, TimeMode mode, UErrorCode& status)
361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    endMonth     = (int8_t)month;
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    endDay       = (int8_t)dayOfWeekInMonth;
364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    endDayOfWeek = (int8_t)dayOfWeek;
365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    endTime      = time;
366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    endTimeMode  = mode;
367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    decodeEndRule(status);
368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    transitionRulesInitialized = FALSE;
369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::setEndRule(int32_t month, int32_t dayOfMonth,
375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                           int32_t time, TimeMode mode, UErrorCode& status)
376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setEndRule(month, dayOfMonth, 0, time, mode, status);
378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::setEndRule(int32_t month, int32_t dayOfMonth, int32_t dayOfWeek,
384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                           int32_t time, TimeMode mode, UBool after, UErrorCode& status)
385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setEndRule(month, after ? dayOfMonth : -dayOfMonth,
387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               -dayOfWeek, time, mode, status);
388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::getOffset(uint8_t era, int32_t year, int32_t month, int32_t day,
394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                          uint8_t dayOfWeek, int32_t millis, UErrorCode& status) const
395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Check the month before calling Grego::monthLength(). This
397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // duplicates the test that occurs in the 7-argument getOffset(),
398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // however, this is unavoidable. We don't mind because this method, in
399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // fact, should not be called; internal code should always call the
400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // 7-argument getOffset(), and outside code should use Calendar.get(int
401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // field) with fields ZONE_OFFSET and DST_OFFSET. We can't get rid of
402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // this method because it's public API. - liu 8/10/98
403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(month < UCAL_JANUARY || month > UCAL_DECEMBER) {
404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        status = U_ILLEGAL_ARGUMENT_ERROR;
405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return getOffset(era, year, month, day, dayOfWeek, millis, Grego::monthLength(year, month), status);
409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::getOffset(uint8_t era, int32_t year, int32_t month, int32_t day,
413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                          uint8_t dayOfWeek, int32_t millis,
414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                          int32_t /*monthLength*/, UErrorCode& status) const
415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Check the month before calling Grego::monthLength(). This
417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // duplicates a test that occurs in the 9-argument getOffset(),
418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // however, this is unavoidable. We don't mind because this method, in
419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // fact, should not be called; internal code should always call the
420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // 9-argument getOffset(), and outside code should use Calendar.get(int
421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // field) with fields ZONE_OFFSET and DST_OFFSET. We can't get rid of
422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // this method because it's public API. - liu 8/10/98
423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (month < UCAL_JANUARY
424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        || month > UCAL_DECEMBER) {
425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        status = U_ILLEGAL_ARGUMENT_ERROR;
426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return -1;
427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // We ignore monthLength because it can be derived from year and month.
430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // This is so that February in leap years is calculated correctly.
431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // We keep this argument in this function for backwards compatibility.
432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return getOffset(era, year, month, day, dayOfWeek, millis,
433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     Grego::monthLength(year, month),
434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     Grego::previousMonthLength(year, month),
435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     status);
436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::getOffset(uint8_t era, int32_t year, int32_t month, int32_t day,
440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                          uint8_t dayOfWeek, int32_t millis,
441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                          int32_t monthLength, int32_t prevMonthLength,
442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                          UErrorCode& status) const
443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(status)) return 0;
445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ((era != GregorianCalendar::AD && era != GregorianCalendar::BC)
447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        || month < UCAL_JANUARY
448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        || month > UCAL_DECEMBER
449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        || day < 1
450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        || day > monthLength
451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        || dayOfWeek < UCAL_SUNDAY
452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        || dayOfWeek > UCAL_SATURDAY
453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        || millis < 0
454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        || millis >= U_MILLIS_PER_DAY
455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        || monthLength < 28
456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        || monthLength > 31
457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        || prevMonthLength < 28
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        || prevMonthLength > 31) {
459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        status = U_ILLEGAL_ARGUMENT_ERROR;
460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return -1;
461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t result = rawOffset;
464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Bail out if we are before the onset of daylight savings time
466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(!useDaylight || year < startYear || era != GregorianCalendar::AD)
467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return result;
468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Check for southern hemisphere.  We assume that the start and end
470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // month are different.
471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool southern = (startMonth > endMonth);
472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Compare the date to the starting and ending rules.+1 = date>rule, -1
474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // = date<rule, 0 = date==rule.
475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t startCompare = compareToRule((int8_t)month, (int8_t)monthLength, (int8_t)prevMonthLength,
476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                         (int8_t)day, (int8_t)dayOfWeek, millis,
477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                         startTimeMode == UTC_TIME ? -rawOffset : 0,
478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                         startMode, (int8_t)startMonth, (int8_t)startDayOfWeek,
479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                         (int8_t)startDay, startTime);
480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t endCompare = 0;
481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* We don't always have to compute endCompare.  For many instances,
483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * startCompare is enough to determine if we are in DST or not.  In the
484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * northern hemisphere, if we are before the start rule, we can't have
485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * DST.  In the southern hemisphere, if we are after the start rule, we
486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * must have DST.  This is reflected in the way the next if statement
487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * (not the one immediately following) short circuits. */
488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(southern != (startCompare >= 0)) {
489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        endCompare = compareToRule((int8_t)month, (int8_t)monthLength, (int8_t)prevMonthLength,
490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   (int8_t)day, (int8_t)dayOfWeek, millis,
491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   endTimeMode == WALL_TIME ? dstSavings :
492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                    (endTimeMode == UTC_TIME ? -rawOffset : 0),
493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   endMode, (int8_t)endMonth, (int8_t)endDayOfWeek,
494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   (int8_t)endDay, endTime);
495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Check for both the northern and southern hemisphere cases.  We
498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // assume that in the northern hemisphere, the start rule is before the
499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // end rule within the calendar year, and vice versa for the southern
500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // hemisphere.
501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ((!southern && (startCompare >= 0 && endCompare < 0)) ||
502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        (southern && (startCompare >= 0 || endCompare < 0)))
503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result += dstSavings;
504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt,
5108393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                   int32_t& rawOffsetGMT, int32_t& savingsDST, UErrorCode& status) const {
511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    rawOffsetGMT = getRawOffset();
516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t year, month, dom, dow;
517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    double day = uprv_floor(date / U_MILLIS_PER_DAY);
518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t millis = (int32_t) (date - day * U_MILLIS_PER_DAY);
519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Grego::dayToFields(day, year, month, dom, dow);
521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    savingsDST = getOffset(GregorianCalendar::AD, year, month, dom,
523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                          (uint8_t) dow, millis,
524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                          Grego::monthLength(year, month),
525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                          status) - rawOffsetGMT;
526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool recalc = FALSE;
531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Now we need some adjustment
533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (savingsDST > 0) {
534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ((nonExistingTimeOpt & kStdDstMask) == kStandard
53527f654740f2a26ad62a5c155af9199af9e69b889claireho            || ((nonExistingTimeOpt & kStdDstMask) != kDaylight && (nonExistingTimeOpt & kFormerLatterMask) != kLatter)) {
536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            date -= getDSTSavings();
537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            recalc = TRUE;
538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ((duplicatedTimeOpt & kStdDstMask) == kDaylight
54127f654740f2a26ad62a5c155af9199af9e69b889claireho                || ((duplicatedTimeOpt & kStdDstMask) != kStandard && (duplicatedTimeOpt & kFormerLatterMask) == kFormer)) {
542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            date -= getDSTSavings();
543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            recalc = TRUE;
544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (recalc) {
547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        day = uprv_floor(date / U_MILLIS_PER_DAY);
548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        millis = (int32_t) (date - day * U_MILLIS_PER_DAY);
549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Grego::dayToFields(day, year, month, dom, dow);
550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        savingsDST = getOffset(GregorianCalendar::AD, year, month, dom,
551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                          (uint8_t) dow, millis,
552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                          Grego::monthLength(year, month),
553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                          status) - rawOffsetGMT;
554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Compare a given date in the year to a rule. Return 1, 0, or -1, depending
561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * on whether the date is after, equal to, or before the rule date. The
562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * millis are compared directly against the ruleMillis, so any
563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * standard-daylight adjustments must be handled by the caller.
564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @return  1 if the date is after the rule date, -1 if the date is before
566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *          the rule date, or 0 if the date is equal to the rule date.
567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::compareToRule(int8_t month, int8_t monthLen, int8_t prevMonthLen,
570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                              int8_t dayOfMonth,
571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                              int8_t dayOfWeek, int32_t millis, int32_t millisDelta,
572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                              EMode ruleMode, int8_t ruleMonth, int8_t ruleDayOfWeek,
573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                              int8_t ruleDay, int32_t ruleMillis)
574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Make adjustments for startTimeMode and endTimeMode
576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    millis += millisDelta;
577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (millis >= U_MILLIS_PER_DAY) {
578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        millis -= U_MILLIS_PER_DAY;
579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ++dayOfMonth;
580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        dayOfWeek = (int8_t)(1 + (dayOfWeek % 7)); // dayOfWeek is one-based
581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (dayOfMonth > monthLen) {
582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            dayOfMonth = 1;
583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* When incrementing the month, it is desirible to overflow
584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * from DECEMBER to DECEMBER+1, since we use the result to
585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * compare against a real month. Wraparound of the value
586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * leads to bug 4173604. */
587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ++month;
588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (millis < 0) {
591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        millis += U_MILLIS_PER_DAY;
592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        --dayOfMonth;
593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        dayOfWeek = (int8_t)(1 + ((dayOfWeek+5) % 7)); // dayOfWeek is one-based
594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (dayOfMonth < 1) {
595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            dayOfMonth = prevMonthLen;
596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            --month;
597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // first compare months.  If they're different, we don't have to worry about days
601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // and times
602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (month < ruleMonth) return -1;
603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else if (month > ruleMonth) return 1;
604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // calculate the actual day of month for the rule
606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t ruleDayOfMonth = 0;
607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Adjust the ruleDay to the monthLen, for non-leap year February 29 rule days.
609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (ruleDay > monthLen) {
610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ruleDay = monthLen;
611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    switch (ruleMode)
614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // if the mode is day-of-month, the day of month is given
616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case DOM_MODE:
617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ruleDayOfMonth = ruleDay;
618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // if the mode is day-of-week-in-month, calculate the day-of-month from it
621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case DOW_IN_MONTH_MODE:
622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // In this case ruleDay is the day-of-week-in-month (this code is using
623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // the dayOfWeek and dayOfMonth parameters to figure out the day-of-week
624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // of the first day of the month, so it's trusting that they're really
625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // consistent with each other)
626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (ruleDay > 0)
627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ruleDayOfMonth = 1 + (ruleDay - 1) * 7 +
628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                (7 + ruleDayOfWeek - (dayOfWeek - dayOfMonth + 1)) % 7;
629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // if ruleDay is negative (we assume it's not zero here), we have to do
631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // the same calculation figuring backward from the last day of the month.
632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else
633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // (again, this code is trusting that dayOfWeek and dayOfMonth are
635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // consistent with each other here, since we're using them to figure
636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // the day of week of the first of the month)
637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ruleDayOfMonth = monthLen + (ruleDay + 1) * 7 -
638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                (7 + (dayOfWeek + monthLen - dayOfMonth) - ruleDayOfWeek) % 7;
639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case DOW_GE_DOM_MODE:
643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ruleDayOfMonth = ruleDay +
644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            (49 + ruleDayOfWeek - ruleDay - dayOfWeek + dayOfMonth) % 7;
645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case DOW_LE_DOM_MODE:
648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ruleDayOfMonth = ruleDay -
649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            (49 - ruleDayOfWeek + ruleDay + dayOfWeek - dayOfMonth) % 7;
650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Note at this point ruleDayOfMonth may be <1, although it will
651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // be >=1 for well-formed rules.
652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // now that we have a real day-in-month for the rule, we can compare days...
656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (dayOfMonth < ruleDayOfMonth) return -1;
657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else if (dayOfMonth > ruleDayOfMonth) return 1;
658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // ...and if they're equal, we compare times
660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (millis < ruleMillis) return -1;
661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else if (millis > ruleMillis) return 1;
662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else return 0;
663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::getRawOffset() const
669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return rawOffset;
671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::setRawOffset(int32_t offsetMillis)
677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    rawOffset = offsetMillis;
679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    transitionRulesInitialized = FALSE;
680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::setDSTSavings(int32_t millisSavedDuringDST, UErrorCode& status)
686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (millisSavedDuringDST <= 0) {
688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        status = U_ILLEGAL_ARGUMENT_ERROR;
689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else {
691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        dstSavings = millisSavedDuringDST;
692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    transitionRulesInitialized = FALSE;
694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::getDSTSavings() const
700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return dstSavings;
702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::useDaylightTime() const
708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return useDaylight;
710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Overrides TimeZone
716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Queries if the given date is in Daylight Savings Time.
717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool SimpleTimeZone::inDaylightTime(UDate date, UErrorCode& status) const
719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // This method is wasteful since it creates a new GregorianCalendar and
721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // deletes it each time it is called.  However, this is a deprecated method
722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // and provided only for Java compatibility as of 8/6/97 [LIU].
723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) return FALSE;
724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    GregorianCalendar *gc = new GregorianCalendar(*this, status);
725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* test for NULL */
726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (gc == 0) {
727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        status = U_MEMORY_ALLOCATION_ERROR;
728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    gc->setTime(date, status);
731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool result = gc->inDaylightTime(status);
732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete gc;
733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Return true if this zone has the same rules and offset as another zone.
740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param other the TimeZone object to be compared with
741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @return true if the given zone has the same rules and offset as this one
742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::hasSameRules(const TimeZone& other) const
745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (this == &other) return TRUE;
74727f654740f2a26ad62a5c155af9199af9e69b889claireho    if (typeid(*this) != typeid(other)) return FALSE;
748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SimpleTimeZone *that = (SimpleTimeZone*)&other;
749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return rawOffset     == that->rawOffset &&
750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        useDaylight     == that->useDaylight &&
751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        (!useDaylight
752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         // Only check rules if using DST
753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         || (dstSavings     == that->dstSavings &&
754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             startMode      == that->startMode &&
755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             startMonth     == that->startMonth &&
756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             startDay       == that->startDay &&
757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             startDayOfWeek == that->startDayOfWeek &&
758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             startTime      == that->startTime &&
759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             startTimeMode  == that->startTimeMode &&
760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             endMode        == that->endMode &&
761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             endMonth       == that->endMonth &&
762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             endDay         == that->endDay &&
763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             endDayOfWeek   == that->endDayOfWeek &&
764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             endTime        == that->endTime &&
765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             endTimeMode    == that->endTimeMode &&
766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             startYear      == that->startYear));
767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//----------------------------------------------------------------------
772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Rule representation
773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// We represent the following flavors of rules:
775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//       5        the fifth of the month
776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//       lastSun  the last Sunday in the month
777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//       lastMon  the last Monday in the month
778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//       Sun>=8   first Sunday on or after the eighth
779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//       Sun<=25  last Sunday on or before the 25th
780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// This is further complicated by the fact that we need to remain
781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// backward compatible with the 1.1 FCS.  Finally, we need to minimize
782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// API changes.  In order to satisfy these requirements, we support
783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// three representation systems, and we translate between them.
784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// INTERNAL REPRESENTATION
786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// This is the format SimpleTimeZone objects take after construction or
787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// streaming in is complete.  Rules are represented directly, using an
788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// unencoded format.  We will discuss the start rule only below; the end
789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// rule is analogous.
790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//   startMode      Takes on enumerated values DAY_OF_MONTH,
791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//                  DOW_IN_MONTH, DOW_AFTER_DOM, or DOW_BEFORE_DOM.
792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//   startDay       The day of the month, or for DOW_IN_MONTH mode, a
793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//                  value indicating which DOW, such as +1 for first,
794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//                  +2 for second, -1 for last, etc.
795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//   startDayOfWeek The day of the week.  Ignored for DAY_OF_MONTH.
796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ENCODED REPRESENTATION
798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// This is the format accepted by the constructor and by setStartRule()
799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// and setEndRule().  It uses various combinations of positive, negative,
800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// and zero values to encode the different rules.  This representation
801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// allows us to specify all the different rule flavors without altering
802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// the API.
803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//   MODE              startMonth    startDay    startDayOfWeek
804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//   DOW_IN_MONTH_MODE >=0           !=0         >0
805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//   DOM_MODE          >=0           >0          ==0
806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//   DOW_GE_DOM_MODE   >=0           >0          <0
807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//   DOW_LE_DOM_MODE   >=0           <0          <0
808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//   (no DST)          don't care    ==0         don't care
809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// STREAMED REPRESENTATION
811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// We must retain binary compatibility with the 1.1 FCS.  The 1.1 code only
812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// handles DOW_IN_MONTH_MODE and non-DST mode, the latter indicated by the
813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// flag useDaylight.  When we stream an object out, we translate into an
814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// approximate DOW_IN_MONTH_MODE representation so the object can be parsed
815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// and used by 1.1 code.  Following that, we write out the full
816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// representation separately so that contemporary code can recognize and
817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// parse it.  The full representation is written in a "packed" format,
818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// consisting of a version number, a length, and an array of bytes.  Future
819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// versions of this class may specify different versions.  If they wish to
820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// include additional data, they should do so by storing them after the
821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// packed representation below.
822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//----------------------------------------------------------------------
823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Given a set of encoded rules in startDay and startDayOfMonth, decode
826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * them and set the startMode appropriately.  Do the same for endDay and
827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * endDayOfMonth.  Upon entry, the day of week variables may be zero or
828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * negative, in order to indicate special modes.  The day of month
829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * variables may also be negative.  Upon exit, the mode variables will be
830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * set, and the day of week and day of month variables will be positive.
831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This method also recognizes a startDay or endDay of zero as indicating
832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * no DST.
833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::decodeRules(UErrorCode& status)
836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    decodeStartRule(status);
838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    decodeEndRule(status);
839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Decode the start rule and validate the parameters.  The parameters are
843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * expected to be in encoded form, which represents the various rule modes
844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * by negating or zeroing certain values.  Representation formats are:
845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * <p>
846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * <pre>
847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *            DOW_IN_MONTH  DOM    DOW>=DOM  DOW<=DOM  no DST
848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *            ------------  -----  --------  --------  ----------
849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * month       0..11        same    same      same     don't care
850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * day        -5..5         1..31   1..31    -1..-31   0
851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * dayOfWeek   1..7         0      -1..-7    -1..-7    don't care
852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * time        0..ONEDAY    same    same      same     don't care
853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * </pre>
854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * The range for month does not include UNDECIMBER since this class is
855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * really specific to GregorianCalendar, which does not use that month.
856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * The range for time includes ONEDAY (vs. ending at ONEDAY-1) because the
857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * end rule is an exclusive limit point.  That is, the range of times that
858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * are in DST include those >= the start and < the end.  For this reason,
859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * it should be possible to specify an end of ONEDAY in order to include the
860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * entire day.  Although this is equivalent to time 0 of the following day,
861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * it's not always possible to specify that, for example, on December 31.
862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * While arguably the start range should still be 0..ONEDAY-1, we keep
863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * the start and end ranges the same for consistency.
864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::decodeStartRule(UErrorCode& status)
867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(status)) return;
869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    useDaylight = (UBool)((startDay != 0) && (endDay != 0) ? TRUE : FALSE);
871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (useDaylight && dstSavings == 0) {
872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        dstSavings = U_MILLIS_PER_HOUR;
873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (startDay != 0) {
875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (startMonth < UCAL_JANUARY || startMonth > UCAL_DECEMBER) {
876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            status = U_ILLEGAL_ARGUMENT_ERROR;
877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (startTime < 0 || startTime > U_MILLIS_PER_DAY ||
880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            startTimeMode < WALL_TIME || startTimeMode > UTC_TIME) {
881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            status = U_ILLEGAL_ARGUMENT_ERROR;
882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (startDayOfWeek == 0) {
885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            startMode = DOM_MODE;
886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (startDayOfWeek > 0) {
888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                startMode = DOW_IN_MONTH_MODE;
889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                startDayOfWeek = (int8_t)-startDayOfWeek;
891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (startDay > 0) {
892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    startMode = DOW_GE_DOM_MODE;
893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else {
894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    startDay = (int8_t)-startDay;
895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    startMode = DOW_LE_DOM_MODE;
896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (startDayOfWeek > UCAL_SATURDAY) {
899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                status = U_ILLEGAL_ARGUMENT_ERROR;
900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return;
901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (startMode == DOW_IN_MONTH_MODE) {
904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (startDay < -5 || startDay > 5) {
905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                status = U_ILLEGAL_ARGUMENT_ERROR;
906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return;
907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else if (startDay<1 || startDay > STATICMONTHLENGTH[startMonth]) {
909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            status = U_ILLEGAL_ARGUMENT_ERROR;
910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Decode the end rule and validate the parameters.  This method is exactly
917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * analogous to decodeStartRule().
918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @see decodeStartRule
919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::decodeEndRule(UErrorCode& status)
922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(status)) return;
924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    useDaylight = (UBool)((startDay != 0) && (endDay != 0) ? TRUE : FALSE);
926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (useDaylight && dstSavings == 0) {
927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        dstSavings = U_MILLIS_PER_HOUR;
928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (endDay != 0) {
930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (endMonth < UCAL_JANUARY || endMonth > UCAL_DECEMBER) {
931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            status = U_ILLEGAL_ARGUMENT_ERROR;
932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (endTime < 0 || endTime > U_MILLIS_PER_DAY ||
935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            endTimeMode < WALL_TIME || endTimeMode > UTC_TIME) {
936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            status = U_ILLEGAL_ARGUMENT_ERROR;
937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (endDayOfWeek == 0) {
940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            endMode = DOM_MODE;
941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (endDayOfWeek > 0) {
943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                endMode = DOW_IN_MONTH_MODE;
944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                endDayOfWeek = (int8_t)-endDayOfWeek;
946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (endDay > 0) {
947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    endMode = DOW_GE_DOM_MODE;
948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else {
949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    endDay = (int8_t)-endDay;
950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    endMode = DOW_LE_DOM_MODE;
951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (endDayOfWeek > UCAL_SATURDAY) {
954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                status = U_ILLEGAL_ARGUMENT_ERROR;
955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return;
956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (endMode == DOW_IN_MONTH_MODE) {
959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (endDay < -5 || endDay > 5) {
960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                status = U_ILLEGAL_ARGUMENT_ERROR;
961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return;
962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else if (endDay<1 || endDay > STATICMONTHLENGTH[endMonth]) {
964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            status = U_ILLEGAL_ARGUMENT_ERROR;
965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
9718393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusSimpleTimeZone::getNextTransition(UDate base, UBool inclusive, TimeZoneTransition& result) const {
97285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (!useDaylight) {
973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
9778393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    checkTransitionRules(status);
978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UDate firstTransitionTime = firstTransition->getTime();
983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (base < firstTransitionTime || (inclusive && base == firstTransitionTime)) {
984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result = *firstTransition;
985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UDate stdDate, dstDate;
987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool stdAvail = stdRule->getNextStart(base, dstRule->getRawOffset(), dstRule->getDSTSavings(), inclusive, stdDate);
988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool dstAvail = dstRule->getNextStart(base, stdRule->getRawOffset(), stdRule->getDSTSavings(), inclusive, dstDate);
989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (stdAvail && (!dstAvail || stdDate < dstDate)) {
990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result.setTime(stdDate);
991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result.setFrom((const TimeZoneRule&)*dstRule);
992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result.setTo((const TimeZoneRule&)*stdRule);
993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (dstAvail && (!stdAvail || dstDate < stdDate)) {
996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result.setTime(dstDate);
997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result.setFrom((const TimeZoneRule&)*stdRule);
998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result.setTo((const TimeZoneRule&)*dstRule);
999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
1000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
1002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
10058393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusSimpleTimeZone::getPreviousTransition(UDate base, UBool inclusive, TimeZoneTransition& result) const {
100685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (!useDaylight) {
1007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
1008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
10118393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    checkTransitionRules(status);
1012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
1013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
1014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UDate firstTransitionTime = firstTransition->getTime();
1017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (base < firstTransitionTime || (!inclusive && base == firstTransitionTime)) {
1018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
1019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UDate stdDate, dstDate;
1021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool stdAvail = stdRule->getPreviousStart(base, dstRule->getRawOffset(), dstRule->getDSTSavings(), inclusive, stdDate);
1022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool dstAvail = dstRule->getPreviousStart(base, stdRule->getRawOffset(), stdRule->getDSTSavings(), inclusive, dstDate);
1023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (stdAvail && (!dstAvail || stdDate > dstDate)) {
1024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result.setTime(stdDate);
1025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result.setFrom((const TimeZoneRule&)*dstRule);
1026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result.setTo((const TimeZoneRule&)*stdRule);
1027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
1028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (dstAvail && (!stdAvail || dstDate > stdDate)) {
1030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result.setTime(dstDate);
1031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result.setFrom((const TimeZoneRule&)*stdRule);
1032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result.setTo((const TimeZoneRule&)*dstRule);
1033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
1034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
1036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::clearTransitionRules(void) {
1040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    initialRule = NULL;
1041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    firstTransition = NULL;
1042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    stdRule = NULL;
1043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    dstRule = NULL;
1044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    transitionRulesInitialized = FALSE;
1045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::deleteTransitionRules(void) {
1049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (initialRule != NULL) {
1050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete initialRule;
1051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (firstTransition != NULL) {
1053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete firstTransition;
1054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (stdRule != NULL) {
1056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete stdRule;
1057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (dstRule != NULL) {
1059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete dstRule;
1060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    clearTransitionRules();
1062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru }
1063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
10648393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius/*
10658393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius * Lazy transition rules initializer
106659d709d503bab6e2b61931737e662dd293b40578ccornelius *
106759d709d503bab6e2b61931737e662dd293b40578ccornelius *    Note On the removal of UMTX_CHECK from checkTransitionRules():
106859d709d503bab6e2b61931737e662dd293b40578ccornelius *
106959d709d503bab6e2b61931737e662dd293b40578ccornelius *         It would be faster to have a UInitOnce as part of a SimpleTimeZone object,
107059d709d503bab6e2b61931737e662dd293b40578ccornelius *         which would avoid needing to lock a mutex to check the initialization state.
107159d709d503bab6e2b61931737e662dd293b40578ccornelius *         But we can't easily because simpletz.h is a public header, and including
107259d709d503bab6e2b61931737e662dd293b40578ccornelius *         a UInitOnce as a member of SimpleTimeZone would publicly expose internal ICU headers.
107359d709d503bab6e2b61931737e662dd293b40578ccornelius *
107459d709d503bab6e2b61931737e662dd293b40578ccornelius *         Alternatively we could have a pointer to a UInitOnce in the SimpleTimeZone object,
107559d709d503bab6e2b61931737e662dd293b40578ccornelius *         allocate it in the constructors. This would be a more intrusive change, but doable
107659d709d503bab6e2b61931737e662dd293b40578ccornelius *         if performance turns out to be an issue.
10778393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius */
10788393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusstatic UMutex gLock = U_MUTEX_INITIALIZER;
10798393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
10808393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusvoid
10818393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusSimpleTimeZone::checkTransitionRules(UErrorCode& status) const {
10828393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    if (U_FAILURE(status)) {
10838393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        return;
10848393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
108559d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_lock(&gLock);
108659d709d503bab6e2b61931737e662dd293b40578ccornelius    if (!transitionRulesInitialized) {
108759d709d503bab6e2b61931737e662dd293b40578ccornelius        SimpleTimeZone *ncThis = const_cast<SimpleTimeZone*>(this);
108859d709d503bab6e2b61931737e662dd293b40578ccornelius        ncThis->initTransitionRules(status);
10898393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
109059d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_unlock(&gLock);
10918393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius}
10928393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
1093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::initTransitionRules(UErrorCode& status) {
1095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
1096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
1097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (transitionRulesInitialized) {
1099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
1100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    deleteTransitionRules();
1102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString tzid;
1103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    getID(tzid);
1104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
110585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (useDaylight) {
1106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        DateTimeRule* dtRule;
1107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        DateTimeRule::TimeRuleType timeRuleType;
1108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UDate firstStdStart, firstDstStart;
1109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Create a TimeZoneRule for daylight saving time
1111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        timeRuleType = (startTimeMode == STANDARD_TIME) ? DateTimeRule::STANDARD_TIME :
1112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ((startTimeMode == UTC_TIME) ? DateTimeRule::UTC_TIME : DateTimeRule::WALL_TIME);
1113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        switch (startMode) {
1114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case DOM_MODE:
1115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            dtRule = new DateTimeRule(startMonth, startDay, startTime, timeRuleType);
1116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
1117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case DOW_IN_MONTH_MODE:
1118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            dtRule = new DateTimeRule(startMonth, startDay, startDayOfWeek, startTime, timeRuleType);
1119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
1120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case DOW_GE_DOM_MODE:
1121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            dtRule = new DateTimeRule(startMonth, startDay, startDayOfWeek, true, startTime, timeRuleType);
1122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
1123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case DOW_LE_DOM_MODE:
1124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            dtRule = new DateTimeRule(startMonth, startDay, startDayOfWeek, false, startTime, timeRuleType);
1125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
1126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        default:
1127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            status = U_INVALID_STATE_ERROR;
1128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
1129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
113085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // Check for Null pointer
113185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (dtRule == NULL) {
11328393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            status = U_MEMORY_ALLOCATION_ERROR;
11338393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            return;
113485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
1135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // For now, use ID + "(DST)" as the name
1136103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        dstRule = new AnnualTimeZoneRule(tzid+UnicodeString(DST_STR), getRawOffset(), getDSTSavings(),
1137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            dtRule, startYear, AnnualTimeZoneRule::MAX_YEAR);
113885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
113985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // Check for Null pointer
114085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (dstRule == NULL) {
11418393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            status = U_MEMORY_ALLOCATION_ERROR;
11428393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            deleteTransitionRules();
11438393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            return;
114485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
1145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Calculate the first DST start time
1147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        dstRule->getFirstStart(getRawOffset(), 0, firstDstStart);
1148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Create a TimeZoneRule for standard time
1150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        timeRuleType = (endTimeMode == STANDARD_TIME) ? DateTimeRule::STANDARD_TIME :
1151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ((endTimeMode == UTC_TIME) ? DateTimeRule::UTC_TIME : DateTimeRule::WALL_TIME);
1152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        switch (endMode) {
1153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case DOM_MODE:
1154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            dtRule = new DateTimeRule(endMonth, endDay, endTime, timeRuleType);
1155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
1156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case DOW_IN_MONTH_MODE:
1157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            dtRule = new DateTimeRule(endMonth, endDay, endDayOfWeek, endTime, timeRuleType);
1158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
1159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case DOW_GE_DOM_MODE:
1160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            dtRule = new DateTimeRule(endMonth, endDay, endDayOfWeek, true, endTime, timeRuleType);
1161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
1162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case DOW_LE_DOM_MODE:
1163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            dtRule = new DateTimeRule(endMonth, endDay, endDayOfWeek, false, endTime, timeRuleType);
1164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
1165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
116685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
116785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // Check for Null pointer
116885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (dtRule == NULL) {
11698393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            status = U_MEMORY_ALLOCATION_ERROR;
11708393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            deleteTransitionRules();
11718393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            return;
117285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
1173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // For now, use ID + "(STD)" as the name
1174103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        stdRule = new AnnualTimeZoneRule(tzid+UnicodeString(STD_STR), getRawOffset(), 0,
1175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            dtRule, startYear, AnnualTimeZoneRule::MAX_YEAR);
117685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
117785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        //Check for Null pointer
117885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (stdRule == NULL) {
11798393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            status = U_MEMORY_ALLOCATION_ERROR;
11808393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            deleteTransitionRules();
11818393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            return;
118285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
1183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Calculate the first STD start time
1185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        stdRule->getFirstStart(getRawOffset(), dstRule->getDSTSavings(), firstStdStart);
1186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Create a TimeZoneRule for initial time
1188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (firstStdStart < firstDstStart) {
1189103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            initialRule = new InitialTimeZoneRule(tzid+UnicodeString(DST_STR), getRawOffset(), dstRule->getDSTSavings());
1190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            firstTransition = new TimeZoneTransition(firstStdStart, *initialRule, *stdRule);
1191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
1192103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            initialRule = new InitialTimeZoneRule(tzid+UnicodeString(STD_STR), getRawOffset(), 0);
1193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            firstTransition = new TimeZoneTransition(firstDstStart, *initialRule, *dstRule);
1194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
119585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // Check for null pointers.
119685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (initialRule == NULL || firstTransition == NULL) {
11978393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            status = U_MEMORY_ALLOCATION_ERROR;
11988393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            deleteTransitionRules();
11998393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            return;
120085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
1201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Create a TimeZoneRule for initial time
1204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        initialRule = new InitialTimeZoneRule(tzid, getRawOffset(), 0);
120585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // Check for null pointer.
120685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (initialRule == NULL) {
12078393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            status = U_MEMORY_ALLOCATION_ERROR;
12088393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            deleteTransitionRules();
12098393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            return;
121085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
1211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
121285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
12138393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    transitionRulesInitialized = TRUE;
1214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
12178393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusSimpleTimeZone::countTransitionRules(UErrorCode& /*status*/) const {
121885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return (useDaylight) ? 2 : 0;
1219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruSimpleTimeZone::getTimeZoneRules(const InitialTimeZoneRule*& initial,
1223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                 const TimeZoneRule* trsrules[],
1224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                 int32_t& trscount,
12258393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                 UErrorCode& status) const {
1226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
1227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
1228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
12298393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    checkTransitionRules(status);
1230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
1231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
1232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    initial = initialRule;
1234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t cnt = 0;
1235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (stdRule != NULL) {
1236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (cnt < trscount) {
1237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            trsrules[cnt++] = stdRule;
1238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (cnt < trscount) {
1240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            trsrules[cnt++] = dstRule;
1241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    trscount = cnt;
1244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_END
1248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */
1250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//eof
1252