1/*
2*******************************************************************************
3* Copyright (C) 2007-2013, International Business Machines Corporation and
4* others. All Rights Reserved.
5*******************************************************************************
6*/
7#ifndef VTZONE_H
8#define VTZONE_H
9
10#include "unicode/utypes.h"
11
12/**
13 * \file
14 * \brief C++ API: RFC2445 VTIMEZONE support
15 */
16
17#if !UCONFIG_NO_FORMATTING
18
19#include "unicode/basictz.h"
20
21U_NAMESPACE_BEGIN
22
23class VTZWriter;
24class VTZReader;
25class UVector;
26
27/**
28 * <code>VTimeZone</code> is a class implementing RFC2445 VTIMEZONE.  You can create a
29 * <code>VTimeZone</code> instance from a time zone ID supported by <code>TimeZone</code>.
30 * With the <code>VTimeZone</code> instance created from the ID, you can write out the rule
31 * in RFC2445 VTIMEZONE format.  Also, you can create a <code>VTimeZone</code> instance
32 * from RFC2445 VTIMEZONE data stream, which allows you to calculate time
33 * zone offset by the rules defined by the data. Or, you can create a
34 * <code>VTimeZone</code> from any other ICU <code>BasicTimeZone</code>.
35 * <br><br>
36 * Note: The consumer of this class reading or writing VTIMEZONE data is responsible to
37 * decode or encode Non-ASCII text.  Methods reading/writing VTIMEZONE data in this class
38 * do nothing with MIME encoding.
39 * @stable ICU 3.8
40 */
41class U_I18N_API VTimeZone : public BasicTimeZone {
42public:
43    /**
44     * Copy constructor.
45     * @param source    The <code>VTimeZone</code> object to be copied.
46     * @stable ICU 3.8
47     */
48    VTimeZone(const VTimeZone& source);
49
50    /**
51     * Destructor.
52     * @stable ICU 3.8
53     */
54    virtual ~VTimeZone();
55
56    /**
57     * Assignment operator.
58     * @param right The object to be copied.
59     * @stable ICU 3.8
60     */
61    VTimeZone& operator=(const VTimeZone& right);
62
63    /**
64     * Return true if the given <code>TimeZone</code> objects are
65     * semantically equal. Objects of different subclasses are considered unequal.
66     * @param that  The object to be compared with.
67     * @return  true if the given <code>TimeZone</code> objects are
68      *semantically equal.
69     * @stable ICU 3.8
70     */
71    virtual UBool operator==(const TimeZone& that) const;
72
73    /**
74     * Return true if the given <code>TimeZone</code> objects are
75     * semantically unequal. Objects of different subclasses are considered unequal.
76     * @param that  The object to be compared with.
77     * @return  true if the given <code>TimeZone</code> objects are
78     * semantically unequal.
79     * @stable ICU 3.8
80     */
81    virtual UBool operator!=(const TimeZone& that) const;
82
83    /**
84     * Create a <code>VTimeZone</code> instance by the time zone ID.
85     * @param ID The time zone ID, such as America/New_York
86     * @return A <code>VTimeZone</code> object initialized by the time zone ID,
87     * or NULL when the ID is unknown.
88     * @stable ICU 3.8
89     */
90    static VTimeZone* createVTimeZoneByID(const UnicodeString& ID);
91
92    /**
93     * Create a <code>VTimeZone</code> instance using a basic time zone.
94     * @param basicTZ The basic time zone instance
95     * @param status Output param to filled in with a success or an error.
96     * @return A <code>VTimeZone</code> object initialized by the basic time zone.
97     * @stable ICU 4.6
98     */
99    static VTimeZone* createVTimeZoneFromBasicTimeZone(const BasicTimeZone& basicTZ,
100                                                       UErrorCode &status);
101
102    /**
103     * Create a <code>VTimeZone</code> instance by RFC2445 VTIMEZONE data
104     *
105     * @param vtzdata The string including VTIMEZONE data block
106     * @param status Output param to filled in with a success or an error.
107     * @return A <code>VTimeZone</code> initialized by the VTIMEZONE data or
108     * NULL if failed to load the rule from the VTIMEZONE data.
109     * @stable ICU 3.8
110     */
111    static VTimeZone* createVTimeZone(const UnicodeString& vtzdata, UErrorCode& status);
112
113    /**
114     * Gets the RFC2445 TZURL property value.  When a <code>VTimeZone</code> instance was
115     * created from VTIMEZONE data, the initial value is set by the TZURL property value
116     * in the data.  Otherwise, the initial value is not set.
117     * @param url Receives the RFC2445 TZURL property value.
118     * @return TRUE if TZURL attribute is available and value is set.
119     * @stable ICU 3.8
120     */
121    UBool getTZURL(UnicodeString& url) const;
122
123    /**
124     * Sets the RFC2445 TZURL property value.
125     * @param url The TZURL property value.
126     * @stable ICU 3.8
127     */
128    void setTZURL(const UnicodeString& url);
129
130    /**
131     * Gets the RFC2445 LAST-MODIFIED property value.  When a <code>VTimeZone</code> instance
132     * was created from VTIMEZONE data, the initial value is set by the LAST-MODIFIED property
133     * value in the data.  Otherwise, the initial value is not set.
134     * @param lastModified Receives the last modified date.
135     * @return TRUE if lastModified attribute is available and value is set.
136     * @stable ICU 3.8
137     */
138    UBool getLastModified(UDate& lastModified) const;
139
140    /**
141     * Sets the RFC2445 LAST-MODIFIED property value.
142     * @param lastModified The LAST-MODIFIED date.
143     * @stable ICU 3.8
144     */
145    void setLastModified(UDate lastModified);
146
147    /**
148     * Writes RFC2445 VTIMEZONE data for this time zone
149     * @param result Output param to filled in with the VTIMEZONE data.
150     * @param status Output param to filled in with a success or an error.
151     * @stable ICU 3.8
152     */
153    void write(UnicodeString& result, UErrorCode& status) const;
154
155    /**
156     * Writes RFC2445 VTIMEZONE data for this time zone applicalbe
157     * for dates after the specified start time.
158     * @param start The start date.
159     * @param result Output param to filled in with the VTIMEZONE data.
160     * @param status Output param to filled in with a success or an error.
161     * @stable ICU 3.8
162     */
163    void write(UDate start, UnicodeString& result, UErrorCode& status) const;
164
165    /**
166     * Writes RFC2445 VTIMEZONE data applicalbe for the specified date.
167     * Some common iCalendar implementations can only handle a single time
168     * zone property or a pair of standard and daylight time properties using
169     * BYDAY rule with day of week (such as BYDAY=1SUN).  This method produce
170     * the VTIMEZONE data which can be handled these implementations.  The rules
171     * produced by this method can be used only for calculating time zone offset
172     * around the specified date.
173     * @param time The date used for rule extraction.
174     * @param result Output param to filled in with the VTIMEZONE data.
175     * @param status Output param to filled in with a success or an error.
176     * @stable ICU 3.8
177     */
178    void writeSimple(UDate time, UnicodeString& result, UErrorCode& status) const;
179
180    /**
181     * Clones TimeZone objects polymorphically. Clients are responsible for deleting
182     * the TimeZone object cloned.
183     * @return   A new copy of this TimeZone object.
184     * @stable ICU 3.8
185     */
186    virtual TimeZone* clone(void) const;
187
188    /**
189     * Returns the TimeZone's adjusted GMT offset (i.e., the number of milliseconds to add
190     * to GMT to get local time in this time zone, taking daylight savings time into
191     * account) as of a particular reference date.  The reference date is used to determine
192     * whether daylight savings time is in effect and needs to be figured into the offset
193     * that is returned (in other words, what is the adjusted GMT offset in this time zone
194     * at this particular date and time?).  For the time zones produced by createTimeZone(),
195     * the reference data is specified according to the Gregorian calendar, and the date
196     * and time fields are local standard time.
197     *
198     * <p>Note: Don't call this method. Instead, call the getOffset(UDate...) overload,
199     * which returns both the raw and the DST offset for a given time. This method
200     * is retained only for backward compatibility.
201     *
202     * @param era        The reference date's era
203     * @param year       The reference date's year
204     * @param month      The reference date's month (0-based; 0 is January)
205     * @param day        The reference date's day-in-month (1-based)
206     * @param dayOfWeek  The reference date's day-of-week (1-based; 1 is Sunday)
207     * @param millis     The reference date's milliseconds in day, local standard time
208     * @param status     Output param to filled in with a success or an error.
209     * @return           The offset in milliseconds to add to GMT to get local time.
210     * @stable ICU 3.8
211     */
212    virtual int32_t getOffset(uint8_t era, int32_t year, int32_t month, int32_t day,
213                              uint8_t dayOfWeek, int32_t millis, UErrorCode& status) const;
214
215    /**
216     * Gets the time zone offset, for current date, modified in case of
217     * daylight savings. This is the offset to add *to* UTC to get local time.
218     *
219     * <p>Note: Don't call this method. Instead, call the getOffset(UDate...) overload,
220     * which returns both the raw and the DST offset for a given time. This method
221     * is retained only for backward compatibility.
222     *
223     * @param era        The reference date's era
224     * @param year       The reference date's year
225     * @param month      The reference date's month (0-based; 0 is January)
226     * @param day        The reference date's day-in-month (1-based)
227     * @param dayOfWeek  The reference date's day-of-week (1-based; 1 is Sunday)
228     * @param millis     The reference date's milliseconds in day, local standard time
229     * @param monthLength The length of the given month in days.
230     * @param status     Output param to filled in with a success or an error.
231     * @return           The offset in milliseconds to add to GMT to get local time.
232     * @stable ICU 3.8
233     */
234    virtual int32_t getOffset(uint8_t era, int32_t year, int32_t month, int32_t day,
235                           uint8_t dayOfWeek, int32_t millis,
236                           int32_t monthLength, UErrorCode& status) const;
237
238    /**
239     * Returns the time zone raw and GMT offset for the given moment
240     * in time.  Upon return, local-millis = GMT-millis + rawOffset +
241     * dstOffset.  All computations are performed in the proleptic
242     * Gregorian calendar.  The default implementation in the TimeZone
243     * class delegates to the 8-argument getOffset().
244     *
245     * @param date moment in time for which to return offsets, in
246     * units of milliseconds from January 1, 1970 0:00 GMT, either GMT
247     * time or local wall time, depending on `local'.
248     * @param local if true, `date' is local wall time; otherwise it
249     * is in GMT time.
250     * @param rawOffset output parameter to receive the raw offset, that
251     * is, the offset not including DST adjustments
252     * @param dstOffset output parameter to receive the DST offset,
253     * that is, the offset to be added to `rawOffset' to obtain the
254     * total offset between local and GMT time. If DST is not in
255     * effect, this value is zero; otherwise it is a positive value,
256     * typically one hour.
257     * @param ec input-output error code
258     * @stable ICU 3.8
259     */
260    virtual void getOffset(UDate date, UBool local, int32_t& rawOffset,
261                           int32_t& dstOffset, UErrorCode& ec) const;
262
263    /**
264     * Sets the TimeZone's raw GMT offset (i.e., the number of milliseconds to add
265     * to GMT to get local time, before taking daylight savings time into account).
266     *
267     * @param offsetMillis  The new raw GMT offset for this time zone.
268     * @stable ICU 3.8
269     */
270    virtual void setRawOffset(int32_t offsetMillis);
271
272    /**
273     * Returns the TimeZone's raw GMT offset (i.e., the number of milliseconds to add
274     * to GMT to get local time, before taking daylight savings time into account).
275     *
276     * @return   The TimeZone's raw GMT offset.
277     * @stable ICU 3.8
278     */
279    virtual int32_t getRawOffset(void) const;
280
281    /**
282     * Queries if this time zone uses daylight savings time.
283     * @return true if this time zone uses daylight savings time,
284     * false, otherwise.
285     * @stable ICU 3.8
286     */
287    virtual UBool useDaylightTime(void) const;
288
289    /**
290     * Queries if the given date is in daylight savings time in
291     * this time zone.
292     * This method is wasteful since it creates a new GregorianCalendar and
293     * deletes it each time it is called. This is a deprecated method
294     * and provided only for Java compatibility.
295     *
296     * @param date the given UDate.
297     * @param status Output param filled in with success/error code.
298     * @return true if the given date is in daylight savings time,
299     * false, otherwise.
300     * @deprecated ICU 2.4. Use Calendar::inDaylightTime() instead.
301     */
302    virtual UBool inDaylightTime(UDate date, UErrorCode& status) const;
303
304    /**
305     * Returns true if this zone has the same rule and offset as another zone.
306     * That is, if this zone differs only in ID, if at all.
307     * @param other the <code>TimeZone</code> object to be compared with
308     * @return true if the given zone is the same as this one,
309     * with the possible exception of the ID
310     * @stable ICU 3.8
311     */
312    virtual UBool hasSameRules(const TimeZone& other) const;
313
314    /**
315     * Gets the first time zone transition after the base time.
316     * @param base      The base time.
317     * @param inclusive Whether the base time is inclusive or not.
318     * @param result    Receives the first transition after the base time.
319     * @return  TRUE if the transition is found.
320     * @stable ICU 3.8
321     */
322    virtual UBool getNextTransition(UDate base, UBool inclusive, TimeZoneTransition& result) const;
323
324    /**
325     * Gets the most recent time zone transition before the base time.
326     * @param base      The base time.
327     * @param inclusive Whether the base time is inclusive or not.
328     * @param result    Receives the most recent transition before the base time.
329     * @return  TRUE if the transition is found.
330     * @stable ICU 3.8
331     */
332    virtual UBool getPreviousTransition(UDate base, UBool inclusive, TimeZoneTransition& result) const;
333
334    /**
335     * Returns the number of <code>TimeZoneRule</code>s which represents time transitions,
336     * for this time zone, that is, all <code>TimeZoneRule</code>s for this time zone except
337     * <code>InitialTimeZoneRule</code>.  The return value range is 0 or any positive value.
338     * @param status    Receives error status code.
339     * @return The number of <code>TimeZoneRule</code>s representing time transitions.
340     * @stable ICU 3.8
341     */
342    virtual int32_t countTransitionRules(UErrorCode& status) const;
343
344    /**
345     * Gets the <code>InitialTimeZoneRule</code> and the set of <code>TimeZoneRule</code>
346     * which represent time transitions for this time zone.  On successful return,
347     * the argument initial points to non-NULL <code>InitialTimeZoneRule</code> and
348     * the array trsrules is filled with 0 or multiple <code>TimeZoneRule</code>
349     * instances up to the size specified by trscount.  The results are referencing the
350     * rule instance held by this time zone instance.  Therefore, after this time zone
351     * is destructed, they are no longer available.
352     * @param initial       Receives the initial timezone rule
353     * @param trsrules      Receives the timezone transition rules
354     * @param trscount      On input, specify the size of the array 'transitions' receiving
355     *                      the timezone transition rules.  On output, actual number of
356     *                      rules filled in the array will be set.
357     * @param status        Receives error status code.
358     * @stable ICU 3.8
359     */
360    virtual void getTimeZoneRules(const InitialTimeZoneRule*& initial,
361        const TimeZoneRule* trsrules[], int32_t& trscount, UErrorCode& status) const;
362
363private:
364    enum { DEFAULT_VTIMEZONE_LINES = 100 };
365
366    /**
367     * Default constructor.
368     */
369    VTimeZone();
370    static VTimeZone* createVTimeZone(VTZReader* reader);
371    void write(VTZWriter& writer, UErrorCode& status) const;
372    void write(UDate start, VTZWriter& writer, UErrorCode& status) const;
373    void writeSimple(UDate time, VTZWriter& writer, UErrorCode& status) const;
374    void load(VTZReader& reader, UErrorCode& status);
375    void parse(UErrorCode& status);
376
377    void writeZone(VTZWriter& w, BasicTimeZone& basictz, UVector* customProps,
378        UErrorCode& status) const;
379
380    void writeHeaders(VTZWriter& w, UErrorCode& status) const;
381    void writeFooter(VTZWriter& writer, UErrorCode& status) const;
382
383    void writeZonePropsByTime(VTZWriter& writer, UBool isDst, const UnicodeString& zonename,
384                              int32_t fromOffset, int32_t toOffset, UDate time, UBool withRDATE,
385                              UErrorCode& status) const;
386    void writeZonePropsByDOM(VTZWriter& writer, UBool isDst, const UnicodeString& zonename,
387                             int32_t fromOffset, int32_t toOffset,
388                             int32_t month, int32_t dayOfMonth, UDate startTime, UDate untilTime,
389                             UErrorCode& status) const;
390    void writeZonePropsByDOW(VTZWriter& writer, UBool isDst, const UnicodeString& zonename,
391                             int32_t fromOffset, int32_t toOffset,
392                             int32_t month, int32_t weekInMonth, int32_t dayOfWeek,
393                             UDate startTime, UDate untilTime, UErrorCode& status) const;
394    void writeZonePropsByDOW_GEQ_DOM(VTZWriter& writer, UBool isDst, const UnicodeString& zonename,
395                                     int32_t fromOffset, int32_t toOffset,
396                                     int32_t month, int32_t dayOfMonth, int32_t dayOfWeek,
397                                     UDate startTime, UDate untilTime, UErrorCode& status) const;
398    void writeZonePropsByDOW_GEQ_DOM_sub(VTZWriter& writer, int32_t month, int32_t dayOfMonth,
399                                         int32_t dayOfWeek, int32_t numDays,
400                                         UDate untilTime, int32_t fromOffset, UErrorCode& status) const;
401    void writeZonePropsByDOW_LEQ_DOM(VTZWriter& writer, UBool isDst, const UnicodeString& zonename,
402                                     int32_t fromOffset, int32_t toOffset,
403                                     int32_t month, int32_t dayOfMonth, int32_t dayOfWeek,
404                                     UDate startTime, UDate untilTime, UErrorCode& status) const;
405    void writeFinalRule(VTZWriter& writer, UBool isDst, const AnnualTimeZoneRule* rule,
406                        int32_t fromRawOffset, int32_t fromDSTSavings,
407                        UDate startTime, UErrorCode& status) const;
408
409    void beginZoneProps(VTZWriter& writer, UBool isDst, const UnicodeString& zonename,
410                        int32_t fromOffset, int32_t toOffset, UDate startTime, UErrorCode& status) const;
411    void endZoneProps(VTZWriter& writer, UBool isDst, UErrorCode& status) const;
412    void beginRRULE(VTZWriter& writer, int32_t month, UErrorCode& status) const;
413    void appendUNTIL(VTZWriter& writer, const UnicodeString& until, UErrorCode& status) const;
414
415    BasicTimeZone   *tz;
416    UVector         *vtzlines;
417    UnicodeString   tzurl;
418    UDate           lastmod;
419    UnicodeString   olsonzid;
420    UnicodeString   icutzver;
421
422public:
423    /**
424     * Return the class ID for this class. This is useful only for comparing to
425     * a return value from getDynamicClassID(). For example:
426     * <pre>
427     * .   Base* polymorphic_pointer = createPolymorphicObject();
428     * .   if (polymorphic_pointer->getDynamicClassID() ==
429     * .       erived::getStaticClassID()) ...
430     * </pre>
431     * @return          The class ID for all objects of this class.
432     * @stable ICU 3.8
433     */
434    static UClassID U_EXPORT2 getStaticClassID(void);
435
436    /**
437     * Returns a unique class ID POLYMORPHICALLY. Pure virtual override. This
438     * method is to implement a simple version of RTTI, since not all C++
439     * compilers support genuine RTTI. Polymorphic operator==() and clone()
440     * methods call this method.
441     *
442     * @return          The class ID for this object. All objects of a
443     *                  given class have the same class ID.  Objects of
444     *                  other classes have different class IDs.
445     * @stable ICU 3.8
446     */
447    virtual UClassID getDynamicClassID(void) const;
448};
449
450U_NAMESPACE_END
451
452#endif /* #if !UCONFIG_NO_FORMATTING */
453
454#endif // VTZONE_H
455//eof
456