1/*
2*******************************************************************************
3* Copyright (C) 2007-2013, International Business Machines Corporation and    *
4* others. All Rights Reserved.                                                *
5*******************************************************************************
6*/
7#ifndef RBTZ_H
8#define RBTZ_H
9
10#include "unicode/utypes.h"
11
12/**
13 * \file
14 * \brief C++ API: Rule based customizable time zone
15 */
16
17#if !UCONFIG_NO_FORMATTING
18
19#include "unicode/basictz.h"
20#include "unicode/unistr.h"
21
22U_NAMESPACE_BEGIN
23
24// forward declaration
25class UVector;
26struct Transition;
27
28/**
29 * a BasicTimeZone subclass implemented in terms of InitialTimeZoneRule and TimeZoneRule instances
30 * @see BasicTimeZone
31 * @see InitialTimeZoneRule
32 * @see TimeZoneRule
33 */
34class U_I18N_API RuleBasedTimeZone : public BasicTimeZone {
35public:
36    /**
37     * Constructs a <code>RuleBasedTimeZone</code> object with the ID and the
38     * <code>InitialTimeZoneRule</code>.  The input <code>InitialTimeZoneRule</code>
39     * is adopted by this <code>RuleBasedTimeZone</code>, thus the caller must not
40     * delete it.
41     * @param id                The time zone ID.
42     * @param initialRule       The initial time zone rule.
43     * @stable ICU 3.8
44     */
45    RuleBasedTimeZone(const UnicodeString& id, InitialTimeZoneRule* initialRule);
46
47    /**
48     * Copy constructor.
49     * @param source    The RuleBasedTimeZone object to be copied.
50     * @stable ICU 3.8
51     */
52    RuleBasedTimeZone(const RuleBasedTimeZone& source);
53
54    /**
55     * Destructor.
56     * @stable ICU 3.8
57     */
58    virtual ~RuleBasedTimeZone();
59
60    /**
61     * Assignment operator.
62     * @param right The object to be copied.
63     * @stable ICU 3.8
64     */
65    RuleBasedTimeZone& operator=(const RuleBasedTimeZone& right);
66
67    /**
68     * Return true if the given <code>TimeZone</code> objects are
69     * semantically equal. Objects of different subclasses are considered unequal.
70     * @param that  The object to be compared with.
71     * @return  true if the given <code>TimeZone</code> objects are
72      *semantically equal.
73     * @stable ICU 3.8
74     */
75    virtual UBool operator==(const TimeZone& that) const;
76
77    /**
78     * Return true if the given <code>TimeZone</code> objects are
79     * semantically unequal. Objects of different subclasses are considered unequal.
80     * @param that  The object to be compared with.
81     * @return  true if the given <code>TimeZone</code> objects are
82     * semantically unequal.
83     * @stable ICU 3.8
84     */
85    virtual UBool operator!=(const TimeZone& that) const;
86
87    /**
88     * Adds the <code>TimeZoneRule</code> which represents time transitions.
89     * The <code>TimeZoneRule</code> must have start times, that is, the result
90     * of isTransitionRule() must be true. Otherwise, U_ILLEGAL_ARGUMENT_ERROR
91     * is set to the error code.
92     * The input <code>TimeZoneRule</code> is adopted by this
93     * <code>RuleBasedTimeZone</code> on successful completion of this method,
94     * thus, the caller must not delete it when no error is returned.
95     * After all rules are added, the caller must call complete() method to
96     * make this <code>RuleBasedTimeZone</code> ready to handle common time
97     * zone functions.
98     * @param rule The <code>TimeZoneRule</code>.
99     * @param status Output param to filled in with a success or an error.
100     * @stable ICU 3.8
101     */
102    void addTransitionRule(TimeZoneRule* rule, UErrorCode& status);
103
104    /**
105     * Makes the <code>TimeZoneRule</code> ready to handle actual timezone
106     * calcuation APIs.  This method collects time zone rules specified
107     * by the caller via the constructor and addTransitionRule() and
108     * builds internal structure for making the object ready to support
109     * time zone APIs such as getOffset(), getNextTransition() and others.
110     * @param status Output param to filled in with a success or an error.
111     * @stable ICU 3.8
112     */
113    void complete(UErrorCode& status);
114
115    /**
116     * Clones TimeZone objects polymorphically. Clients are responsible for deleting
117     * the TimeZone object cloned.
118     *
119     * @return   A new copy of this TimeZone object.
120     * @stable ICU 3.8
121     */
122    virtual TimeZone* clone(void) const;
123
124    /**
125     * Returns the TimeZone's adjusted GMT offset (i.e., the number of milliseconds to add
126     * to GMT to get local time in this time zone, taking daylight savings time into
127     * account) as of a particular reference date.  The reference date is used to determine
128     * whether daylight savings time is in effect and needs to be figured into the offset
129     * that is returned (in other words, what is the adjusted GMT offset in this time zone
130     * at this particular date and time?).  For the time zones produced by createTimeZone(),
131     * the reference data is specified according to the Gregorian calendar, and the date
132     * and time fields are local standard time.
133     *
134     * <p>Note: Don't call this method. Instead, call the getOffset(UDate...) overload,
135     * which returns both the raw and the DST offset for a given time. This method
136     * is retained only for backward compatibility.
137     *
138     * @param era        The reference date's era
139     * @param year       The reference date's year
140     * @param month      The reference date's month (0-based; 0 is January)
141     * @param day        The reference date's day-in-month (1-based)
142     * @param dayOfWeek  The reference date's day-of-week (1-based; 1 is Sunday)
143     * @param millis     The reference date's milliseconds in day, local standard time
144     * @param status     Output param to filled in with a success or an error.
145     * @return           The offset in milliseconds to add to GMT to get local time.
146     * @stable ICU 3.8
147     */
148    virtual int32_t getOffset(uint8_t era, int32_t year, int32_t month, int32_t day,
149                              uint8_t dayOfWeek, int32_t millis, UErrorCode& status) const;
150
151    /**
152     * Gets the time zone offset, for current date, modified in case of
153     * daylight savings. This is the offset to add *to* UTC to get local time.
154     *
155     * <p>Note: Don't call this method. Instead, call the getOffset(UDate...) overload,
156     * which returns both the raw and the DST offset for a given time. This method
157     * is retained only for backward compatibility.
158     *
159     * @param era        The reference date's era
160     * @param year       The reference date's year
161     * @param month      The reference date's month (0-based; 0 is January)
162     * @param day        The reference date's day-in-month (1-based)
163     * @param dayOfWeek  The reference date's day-of-week (1-based; 1 is Sunday)
164     * @param millis     The reference date's milliseconds in day, local standard time
165     * @param monthLength The length of the given month in days.
166     * @param status     Output param to filled in with a success or an error.
167     * @return           The offset in milliseconds to add to GMT to get local time.
168     * @stable ICU 3.8
169     */
170    virtual int32_t getOffset(uint8_t era, int32_t year, int32_t month, int32_t day,
171                           uint8_t dayOfWeek, int32_t millis,
172                           int32_t monthLength, UErrorCode& status) const;
173
174    /**
175     * Returns the time zone raw and GMT offset for the given moment
176     * in time.  Upon return, local-millis = GMT-millis + rawOffset +
177     * dstOffset.  All computations are performed in the proleptic
178     * Gregorian calendar.  The default implementation in the TimeZone
179     * class delegates to the 8-argument getOffset().
180     *
181     * @param date moment in time for which to return offsets, in
182     * units of milliseconds from January 1, 1970 0:00 GMT, either GMT
183     * time or local wall time, depending on `local'.
184     * @param local if true, `date' is local wall time; otherwise it
185     * is in GMT time.
186     * @param rawOffset output parameter to receive the raw offset, that
187     * is, the offset not including DST adjustments
188     * @param dstOffset output parameter to receive the DST offset,
189     * that is, the offset to be added to `rawOffset' to obtain the
190     * total offset between local and GMT time. If DST is not in
191     * effect, this value is zero; otherwise it is a positive value,
192     * typically one hour.
193     * @param ec input-output error code
194     * @stable ICU 3.8
195     */
196    virtual void getOffset(UDate date, UBool local, int32_t& rawOffset,
197                           int32_t& dstOffset, UErrorCode& ec) const;
198
199    /**
200     * Sets the TimeZone's raw GMT offset (i.e., the number of milliseconds to add
201     * to GMT to get local time, before taking daylight savings time into account).
202     *
203     * @param offsetMillis  The new raw GMT offset for this time zone.
204     * @stable ICU 3.8
205     */
206    virtual void setRawOffset(int32_t offsetMillis);
207
208    /**
209     * Returns the TimeZone's raw GMT offset (i.e., the number of milliseconds to add
210     * to GMT to get local time, before taking daylight savings time into account).
211     *
212     * @return   The TimeZone's raw GMT offset.
213     * @stable ICU 3.8
214     */
215    virtual int32_t getRawOffset(void) const;
216
217    /**
218     * Queries if this time zone uses daylight savings time.
219     * @return true if this time zone uses daylight savings time,
220     * false, otherwise.
221     * @stable ICU 3.8
222     */
223    virtual UBool useDaylightTime(void) const;
224
225    /**
226     * Queries if the given date is in daylight savings time in
227     * this time zone.
228     * This method is wasteful since it creates a new GregorianCalendar and
229     * deletes it each time it is called. This is a deprecated method
230     * and provided only for Java compatibility.
231     *
232     * @param date the given UDate.
233     * @param status Output param filled in with success/error code.
234     * @return true if the given date is in daylight savings time,
235     * false, otherwise.
236     * @deprecated ICU 2.4. Use Calendar::inDaylightTime() instead.
237     */
238    virtual UBool inDaylightTime(UDate date, UErrorCode& status) const;
239
240    /**
241     * Returns true if this zone has the same rule and offset as another zone.
242     * That is, if this zone differs only in ID, if at all.
243     * @param other the <code>TimeZone</code> object to be compared with
244     * @return true if the given zone is the same as this one,
245     * with the possible exception of the ID
246     * @stable ICU 3.8
247     */
248    virtual UBool hasSameRules(const TimeZone& other) const;
249
250    /**
251     * Gets the first time zone transition after the base time.
252     * @param base      The base time.
253     * @param inclusive Whether the base time is inclusive or not.
254     * @param result    Receives the first transition after the base time.
255     * @return  TRUE if the transition is found.
256     * @stable ICU 3.8
257     */
258    virtual UBool getNextTransition(UDate base, UBool inclusive, TimeZoneTransition& result) const;
259
260    /**
261     * Gets the most recent time zone transition before the base time.
262     * @param base      The base time.
263     * @param inclusive Whether the base time is inclusive or not.
264     * @param result    Receives the most recent transition before the base time.
265     * @return  TRUE if the transition is found.
266     * @stable ICU 3.8
267     */
268    virtual UBool getPreviousTransition(UDate base, UBool inclusive, TimeZoneTransition& result) const;
269
270    /**
271     * Returns the number of <code>TimeZoneRule</code>s which represents time transitions,
272     * for this time zone, that is, all <code>TimeZoneRule</code>s for this time zone except
273     * <code>InitialTimeZoneRule</code>.  The return value range is 0 or any positive value.
274     * @param status    Receives error status code.
275     * @return The number of <code>TimeZoneRule</code>s representing time transitions.
276     * @stable ICU 3.8
277     */
278    virtual int32_t countTransitionRules(UErrorCode& status) const;
279
280    /**
281     * Gets the <code>InitialTimeZoneRule</code> and the set of <code>TimeZoneRule</code>
282     * which represent time transitions for this time zone.  On successful return,
283     * the argument initial points to non-NULL <code>InitialTimeZoneRule</code> and
284     * the array trsrules is filled with 0 or multiple <code>TimeZoneRule</code>
285     * instances up to the size specified by trscount.  The results are referencing the
286     * rule instance held by this time zone instance.  Therefore, after this time zone
287     * is destructed, they are no longer available.
288     * @param initial       Receives the initial timezone rule
289     * @param trsrules      Receives the timezone transition rules
290     * @param trscount      On input, specify the size of the array 'transitions' receiving
291     *                      the timezone transition rules.  On output, actual number of
292     *                      rules filled in the array will be set.
293     * @param status        Receives error status code.
294     * @stable ICU 3.8
295     */
296    virtual void getTimeZoneRules(const InitialTimeZoneRule*& initial,
297        const TimeZoneRule* trsrules[], int32_t& trscount, UErrorCode& status) const;
298
299    /**
300     * Get time zone offsets from local wall time.
301     * @internal
302     */
303    virtual void getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt,
304        int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) const;
305
306private:
307    void deleteRules(void);
308    void deleteTransitions(void);
309    UVector* copyRules(UVector* source);
310    TimeZoneRule* findRuleInFinal(UDate date, UBool local,
311        int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt) const;
312    UBool findNext(UDate base, UBool inclusive, UDate& time, TimeZoneRule*& from, TimeZoneRule*& to) const;
313    UBool findPrev(UDate base, UBool inclusive, UDate& time, TimeZoneRule*& from, TimeZoneRule*& to) const;
314    int32_t getLocalDelta(int32_t rawBefore, int32_t dstBefore, int32_t rawAfter, int32_t dstAfter,
315        int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt) const;
316    UDate getTransitionTime(Transition* transition, UBool local,
317        int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt) const;
318    void getOffsetInternal(UDate date, UBool local, int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt,
319        int32_t& rawOffset, int32_t& dstOffset, UErrorCode& ec) const;
320    void completeConst(UErrorCode &status) const;
321
322    InitialTimeZoneRule *fInitialRule;
323    UVector             *fHistoricRules;
324    UVector             *fFinalRules;
325    UVector             *fHistoricTransitions;
326    UBool               fUpToDate;
327
328public:
329    /**
330     * Return the class ID for this class. This is useful only for comparing to
331     * a return value from getDynamicClassID(). For example:
332     * <pre>
333     * .   Base* polymorphic_pointer = createPolymorphicObject();
334     * .   if (polymorphic_pointer->getDynamicClassID() ==
335     * .       erived::getStaticClassID()) ...
336     * </pre>
337     * @return          The class ID for all objects of this class.
338     * @stable ICU 3.8
339     */
340    static UClassID U_EXPORT2 getStaticClassID(void);
341
342    /**
343     * Returns a unique class ID POLYMORPHICALLY. Pure virtual override. This
344     * method is to implement a simple version of RTTI, since not all C++
345     * compilers support genuine RTTI. Polymorphic operator==() and clone()
346     * methods call this method.
347     *
348     * @return          The class ID for this object. All objects of a
349     *                  given class have the same class ID.  Objects of
350     *                  other classes have different class IDs.
351     * @stable ICU 3.8
352     */
353    virtual UClassID getDynamicClassID(void) const;
354};
355
356U_NAMESPACE_END
357
358#endif /* #if !UCONFIG_NO_FORMATTING */
359
360#endif // RBTZ_H
361
362//eof
363