KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > ibm > icu > util > SimpleTimeZone


1  /*
2 * Copyright (C) 1996-2006, International Business Machines
3 * Corporation and others. All Rights Reserved.
4 */

5
6 package com.ibm.icu.util;
7 import com.ibm.icu.impl.JDKTimeZone;
8
9 import java.io.IOException JavaDoc;
10 import java.util.Date JavaDoc;
11
12 import com.ibm.icu.impl.OlsonTimeZone;
13 import com.ibm.icu.impl.Utility;
14
15 ///CLOVER:USECLASS
16
/**
17  * <code>SimpleTimeZone</code> is a concrete subclass of <code>TimeZone</code>
18  * that represents a time zone for use with a Gregorian calendar. This
19  * class does not handle historical changes.
20  *
21  * <P>
22  * Use a negative value for <code>dayOfWeekInMonth</code> to indicate that
23  * <code>SimpleTimeZone</code> should count from the end of the month backwards.
24  * For example, Daylight Savings Time ends at the last
25  * (dayOfWeekInMonth = -1) Sunday in October, at 2 AM in standard time.
26  *
27  * @see Calendar
28  * @see GregorianCalendar
29  * @see TimeZone
30  * @author David Goldsmith, Mark Davis, Chen-Lieh Huang, Alan Liu
31  * @stable ICU 2.0
32  */

33 public class SimpleTimeZone extends JDKTimeZone {
34     private static final long serialVersionUID = -7034676239311322769L;
35
36     /**
37      * Constructs a SimpleTimeZone with the given base time zone offset from GMT
38      * and time zone ID. Timezone IDs can be obtained from
39      * TimeZone.getAvailableIDs. Normally you should use TimeZone.getDefault to
40      * construct a TimeZone.
41      *
42      * @param rawOffset The given base time zone offset to GMT.
43      * @param ID The time zone ID which is obtained from
44      * TimeZone.getAvailableIDs.
45      * @stable ICU 2.0
46      */

47     public SimpleTimeZone(int rawOffset, String JavaDoc ID) {
48         //this(new java.util.SimpleTimeZone(rawOffset, ID), ID);
49
//super(ID);
50
construct(rawOffset, 0, 0, 0,
51                 0, WALL_TIME,
52                 0, 0, 0,
53                 0, WALL_TIME,
54                 MILLIS_PER_HOUR);
55         super.setID(ID);
56     }
57
58     /**
59      * Construct a SimpleTimeZone with the given base time zone offset from
60      * GMT, time zone ID, time to start and end the daylight time. Timezone IDs
61      * can be obtained from TimeZone.getAvailableIDs. Normally you should use
62      * TimeZone.getDefault to create a TimeZone. For a time zone that does not
63      * use daylight saving time, do not use this constructor; instead you should
64      * use SimpleTimeZone(rawOffset, ID).
65      *
66      * By default, this constructor specifies day-of-week-in-month rules. That
67      * is, if the startDay is 1, and the startDayOfWeek is SUNDAY, then this
68      * indicates the first Sunday in the startMonth. A startDay of -1 likewise
69      * indicates the last Sunday. However, by using negative or zero values for
70      * certain parameters, other types of rules can be specified.
71      *
72      * Day of month. To specify an exact day of the month, such as March 1, set
73      * startDayOfWeek to zero.
74      *
75      * Day of week after day of month. To specify the first day of the week
76      * occurring on or after an exact day of the month, make the day of the week
77      * negative. For example, if startDay is 5 and startDayOfWeek is -MONDAY,
78      * this indicates the first Monday on or after the 5th day of the
79      * startMonth.
80      *
81      * Day of week before day of month. To specify the last day of the week
82      * occurring on or before an exact day of the month, make the day of the
83      * week and the day of the month negative. For example, if startDay is -21
84      * and startDayOfWeek is -WEDNESDAY, this indicates the last Wednesday on or
85      * before the 21st of the startMonth.
86      *
87      * The above examples refer to the startMonth, startDay, and startDayOfWeek;
88      * the same applies for the endMonth, endDay, and endDayOfWeek.
89      *
90      * @param rawOffset The given base time zone offset to GMT.
91      * @param ID The time zone ID which is obtained from
92      * TimeZone.getAvailableIDs.
93      * @param startMonth The daylight savings starting month. Month is
94      * 0-based. eg, 0 for January.
95      * @param startDay The daylight savings starting
96      * day-of-week-in-month. Please see the member
97      * description for an example.
98      * @param startDayOfWeek The daylight savings starting day-of-week. Please
99      * see the member description for an example.
100      * @param startTime The daylight savings starting time in local wall
101      * time, which is standard time in this case. Please see the
102      * member description for an example.
103      * @param endMonth The daylight savings ending month. Month is
104      * 0-based. eg, 0 for January.
105      * @param endDay The daylight savings ending day-of-week-in-month.
106      * Please see the member description for an example.
107      * @param endDayOfWeek The daylight savings ending day-of-week. Please
108      * see the member description for an example.
109      * @param endTime The daylight savings ending time in local wall time,
110      * which is daylight time in this case. Please see the
111      * member description for an example.
112      * @exception IllegalArgumentException the month, day, dayOfWeek, or time
113      * parameters are out of range for the start or end rule
114      * @stable ICU 2.0
115      */

116     public SimpleTimeZone(int rawOffset, String JavaDoc ID,
117                           int startMonth, int startDay, int startDayOfWeek, int startTime,
118                           int endMonth, int endDay, int endDayOfWeek, int endTime) {
119 /* this(new java.util.SimpleTimeZone(rawOffset, ID, startMonth, startDay,
120                                           startDayOfWeek, startTime, endMonth,
121                                           endDay, endDayOfWeek, endTime), ID);*/

122        // STZInfo xinfo = getSTZInfo();
123
// xinfo.setStart(startMonth, startDay, startDayOfWeek, startTime, -1, false);
124
// xinfo.setEnd(endMonth, endDay, endDayOfWeek, endTime, -1, false);
125
construct(rawOffset,
126                 startMonth, startDay, startDayOfWeek,
127                 startTime, WALL_TIME,
128                 endMonth, endDay, endDayOfWeek,
129                 endTime, WALL_TIME,
130                 MILLIS_PER_HOUR);
131         super.setID(ID);
132     }
133
134     /**
135      * Constructor. This constructor is identical to the 10-argument
136      * constructor, but also takes a dstSavings parameter.
137      * @param dstSavings The amount of time in ms saved during DST.
138      * @exception IllegalArgumentException the month, day, dayOfWeek, or time
139      * parameters are out of range for the start or end rule
140      * @stable ICU 2.0
141      */

142     public SimpleTimeZone(int rawOffset, String JavaDoc ID,
143                           int startMonth, int startDay, int startDayOfWeek, int startTime,
144                           int endMonth, int endDay, int endDayOfWeek, int endTime,
145                           int dstSavings) {
146         /*this(new java.util.SimpleTimeZone(rawOffset, ID, startMonth, startDay,
147                                           startDayOfWeek, startTime, endMonth,
148                                           endDay, endDayOfWeek, endTime, dstSavings), ID);*/

149         this.raw = rawOffset;
150         this.dst = dstSavings;
151         /*
152         STZInfo xinfo = getSTZInfo();
153         xinfo.setStart(startMonth, startDay, startDayOfWeek, startTime, -1, false);
154         xinfo.setEnd(endMonth, endDay, endDayOfWeek, endTime, -1, false);
155         */

156
157         construct(rawOffset,
158                 startMonth, startDay, startDayOfWeek,
159                 startTime, WALL_TIME,
160                 endMonth, endDay, endDayOfWeek,
161                 endTime, WALL_TIME,
162                 dstSavings);
163         super.setID(ID);
164     }
165     
166
167     /**
168      * Set the raw offset.
169      *
170      * @param offsetMillis the raw offset of the time zone
171      * @draft ICU 3.4
172      * @provisional This API might change or be removed in a future release.
173      */

174     public void setRawOffset(int offsetMillis) {
175         raw = offsetMillis;
176     }
177   
178     /**
179      * get the raw offset.
180      *
181      * @return the raw offset
182      * @internal revisit for ICU 3.6
183      * @deprecated This API is ICU internal only.
184      */

185     public int getRawOffset() {
186         return raw;
187     }
188
189     /**
190      * Sets the daylight savings starting year.
191      *
192      * @param year The daylight savings starting year.
193      * @stable ICU 2.0
194      */

195     public void setStartYear(int year) {
196         //unwrapSTZ().setStartYear(year);
197

198         getSTZInfo().sy = year;
199         this.startYear = year;
200     }
201
202     /**
203      * Sets the daylight savings starting rule. For example, Daylight Savings
204      * Time starts at the first Sunday in April, at 2 AM in standard time.
205      * Therefore, you can set the start rule by calling:
206      * setStartRule(TimeFields.APRIL, 1, TimeFields.SUNDAY, 2*60*60*1000);
207      *
208      * @param month The daylight savings starting month. Month is
209      * 0-based. eg, 0 for January.
210      * @param dayOfWeekInMonth The daylight savings starting
211      * day-of-week-in-month. Please see the member
212      * description for an example.
213      * @param dayOfWeek The daylight savings starting day-of-week.
214      * Please see the member description for an
215      * example.
216      * @param time The daylight savings starting time in local wall
217      * time, which is standard time in this case. Please see
218      * the member description for an example.
219      * @exception IllegalArgumentException the month, dayOfWeekInMonth,
220      * dayOfWeek, or time parameters are out of range
221      * @stable ICU 2.0
222      */

223     public void setStartRule(int month, int dayOfWeekInMonth, int dayOfWeek,
224                              int time) {
225         //unwrapSTZ().setStartRule(month, dayOfWeekInMonth, dayOfWeek, time);
226

227         getSTZInfo().setStart(month, dayOfWeekInMonth, dayOfWeek, time, -1, false);
228         setStartRule(month, dayOfWeekInMonth, dayOfWeek, time, WALL_TIME);
229     }
230     /**
231      * Sets the daylight savings starting rule. For example, in the U.S., Daylight Savings
232      * Time starts at the first Sunday in April, at 2 AM in standard time.
233      * Therefore, you can set the start rule by calling:
234      * setStartRule(TimeFields.APRIL, 1, TimeFields.SUNDAY, 2*60*60*1000);
235      * The dayOfWeekInMonth and dayOfWeek parameters together specify how to calculate
236      * the exact starting date. Their exact meaning depend on their respective signs,
237      * allowing various types of rules to be constructed, as follows:<ul>
238      * <li>If both dayOfWeekInMonth and dayOfWeek are positive, they specify the
239      * day of week in the month (e.g., (2, WEDNESDAY) is the second Wednesday
240      * of the month).
241      * <li>If dayOfWeek is positive and dayOfWeekInMonth is negative, they specify
242      * the day of week in the month counting backward from the end of the month.
243      * (e.g., (-1, MONDAY) is the last Monday in the month)
244      * <li>If dayOfWeek is zero and dayOfWeekInMonth is positive, dayOfWeekInMonth
245      * specifies the day of the month, regardless of what day of the week it is.
246      * (e.g., (10, 0) is the tenth day of the month)
247      * <li>If dayOfWeek is zero and dayOfWeekInMonth is negative, dayOfWeekInMonth
248      * specifies the day of the month counting backward from the end of the
249      * month, regardless of what day of the week it is (e.g., (-2, 0) is the
250      * next-to-last day of the month).
251      * <li>If dayOfWeek is negative and dayOfWeekInMonth is positive, they specify the
252      * first specified day of the week on or after the specfied day of the month.
253      * (e.g., (15, -SUNDAY) is the first Sunday after the 15th of the month
254      * [or the 15th itself if the 15th is a Sunday].)
255      * <li>If dayOfWeek and DayOfWeekInMonth are both negative, they specify the
256      * last specified day of the week on or before the specified day of the month.
257      * (e.g., (-20, -TUESDAY) is the last Tuesday before the 20th of the month
258      * [or the 20th itself if the 20th is a Tuesday].)</ul>
259      * @param month the daylight savings starting month. Month is 0-based.
260      * eg, 0 for January.
261      * @param dayOfWeekInMonth the daylight savings starting
262      * day-of-week-in-month. Please see the member description for an example.
263      * @param dayOfWeek the daylight savings starting day-of-week. Please see
264      * the member description for an example.
265      * @param time the daylight savings starting time. Please see the member
266      * description for an example.
267      */

268      
269     private void setStartRule(int month, int dayOfWeekInMonth, int dayOfWeek, int time, int mode)
270     {
271         startMonth = month;
272         startDay = dayOfWeekInMonth;
273         startDayOfWeek = dayOfWeek;
274         startTime = time;
275         startTimeMode = mode;
276         decodeStartRule();
277     }
278     /**
279      * Sets the DST start rule to a fixed date within a month.
280      *
281      * @param month The month in which this rule occurs (0-based).
282      * @param dayOfMonth The date in that month (1-based).
283      * @param time The time of that day (number of millis after midnight)
284      * when DST takes effect in local wall time, which is
285      * standard time in this case.
286      * @exception IllegalArgumentException the month,
287      * dayOfMonth, or time parameters are out of range
288      * @stable ICU 2.0
289      */

290     public void setStartRule(int month, int dayOfMonth, int time) {
291        // unwrapSTZ().setStartRule(month, dayOfMonth, time);
292

293         getSTZInfo().setStart(month, -1, -1, time, dayOfMonth, false);
294         setStartRule(month, dayOfMonth, 0, time, WALL_TIME);
295     }
296
297     /**
298      * Sets the DST start rule to a weekday before or after a give date within
299      * a month, e.g., the first Monday on or after the 8th.
300      *
301      * @param month The month in which this rule occurs (0-based).
302      * @param dayOfMonth A date within that month (1-based).
303      * @param dayOfWeek The day of the week on which this rule occurs.
304      * @param time The time of that day (number of millis after midnight)
305      * when DST takes effect in local wall time, which is
306      * standard time in this case.
307      * @param after If true, this rule selects the first dayOfWeek on
308      * or after dayOfMonth. If false, this rule selects
309      * the last dayOfWeek on or before dayOfMonth.
310      * @exception IllegalArgumentException the month, dayOfMonth,
311      * dayOfWeek, or time parameters are out of range
312      * @stable ICU 2.0
313      */

314     public void setStartRule(int month, int dayOfMonth, int dayOfWeek, int time, boolean after) {
315         //unwrapSTZ().setStartRule(month, dayOfMonth, dayOfWeek, time, after);
316

317         getSTZInfo().setStart(month, -1, dayOfWeek, time, dayOfMonth, after);
318         setStartRule(month, after ? dayOfMonth : -dayOfMonth,
319                 -dayOfWeek, time, WALL_TIME);
320
321     }
322
323     /**
324      * Sets the daylight savings ending rule. For example, Daylight Savings Time
325      * ends at the last (-1) Sunday in October, at 2 AM in standard time.
326      * Therefore, you can set the end rule by calling:
327      * setEndRule(TimeFields.OCTOBER, -1, TimeFields.SUNDAY, 2*60*60*1000);
328      *
329      * @param month The daylight savings ending month. Month is
330      * 0-based. eg, 0 for January.
331      * @param dayOfWeekInMonth The daylight savings ending
332      * day-of-week-in-month. Please see the member
333      * description for an example.
334      * @param dayOfWeek The daylight savings ending day-of-week. Please
335      * see the member description for an example.
336      * @param time The daylight savings ending time in local wall time,
337      * which is daylight time in this case. Please see the
338      * member description for an example.
339      * @exception IllegalArgumentException the month, dayOfWeekInMonth,
340      * dayOfWeek, or time parameters are out of range
341      * @stable ICU 2.0
342      */

343     public void setEndRule(int month, int dayOfWeekInMonth, int dayOfWeek, int time) {
344         //unwrapSTZ().setEndRule(month, dayOfWeekInMonth, dayOfWeek, time);
345

346         getSTZInfo().setEnd(month, dayOfWeekInMonth, dayOfWeek, time, -1, false);
347         setEndRule(month, dayOfWeekInMonth, dayOfWeek, time, WALL_TIME);
348     }
349
350     /**
351      * Sets the DST end rule to a fixed date within a month.
352      *
353      * @param month The month in which this rule occurs (0-based).
354      * @param dayOfMonth The date in that month (1-based).
355      * @param time The time of that day (number of millis after midnight)
356      * when DST ends in local wall time, which is daylight
357      * time in this case.
358      * @exception IllegalArgumentException the month,
359      * dayOfMonth, or time parameters are out of range
360      * @stable ICU 2.0
361      */

362     public void setEndRule(int month, int dayOfMonth, int time) {
363         //unwrapSTZ().setEndRule(month, dayOfMonth, time);
364

365         getSTZInfo().setEnd(month, -1, -1, time, dayOfMonth, false);
366         setEndRule(month, dayOfMonth, WALL_TIME, time);
367     }
368
369     /**
370      * Sets the DST end rule to a weekday before or after a give date within
371      * a month, e.g., the first Monday on or after the 8th.
372      *
373      * @param month The month in which this rule occurs (0-based).
374      * @param dayOfMonth A date within that month (1-based).
375      * @param dayOfWeek The day of the week on which this rule occurs.
376      * @param time The time of that day (number of millis after midnight)
377      * when DST ends in local wall time, which is daylight
378      * time in this case.
379      * @param after If true, this rule selects the first dayOfWeek on
380      * or after dayOfMonth. If false, this rule selects
381      * the last dayOfWeek on or before dayOfMonth.
382      * @exception IllegalArgumentException the month, dayOfMonth,
383      * dayOfWeek, or time parameters are out of range
384      * @stable ICU 2.0
385      */

386     public void setEndRule(int month, int dayOfMonth, int dayOfWeek, int time, boolean after) {
387        // unwrapSTZ().setEndRule(month, dayOfMonth, dayOfWeek, time, after);
388

389         getSTZInfo().setEnd(month, -1, dayOfWeek, time, dayOfMonth, after);
390         setEndRule(month, dayOfMonth, dayOfWeek, time, WALL_TIME, after);
391     }
392     private void setEndRule(int month, int dayOfMonth, int dayOfWeek,
393                                                 int time, int mode, boolean after){
394         setEndRule(month, after ? dayOfMonth : -dayOfMonth, -dayOfWeek, time, mode);
395     }
396     /**
397      * Sets the daylight savings ending rule. For example, in the U.S., Daylight
398      * Savings Time ends at the last (-1) Sunday in October, at 2 AM in standard time.
399      * Therefore, you can set the end rule by calling:
400      * setEndRule(TimeFields.OCTOBER, -1, TimeFields.SUNDAY, 2*60*60*1000);
401      * Various other types of rules can be specified by manipulating the dayOfWeek
402      * and dayOfWeekInMonth parameters. For complete details, see the documentation
403      * for setStartRule().
404      * @param month the daylight savings ending month. Month is 0-based.
405      * eg, 0 for January.
406      * @param dayOfWeekInMonth the daylight savings ending
407      * day-of-week-in-month. See setStartRule() for a complete explanation.
408      * @param dayOfWeek the daylight savings ending day-of-week. See setStartRule()
409      * for a complete explanation.
410      * @param time the daylight savings ending time. Please see the member
411      * description for an example.
412      */

413     private void setEndRule(int month, int dayOfWeekInMonth, int dayOfWeek, int time, int mode){
414         endMonth = month;
415         endDay = dayOfWeekInMonth;
416         endDayOfWeek = dayOfWeek;
417         endTime = time;
418         endTimeMode = mode;
419         decodeEndRule();
420     }
421     /**
422      * Sets the amount of time in ms that the clock is advanced during DST.
423      * @param millisSavedDuringDST the number of milliseconds the time is
424      * advanced with respect to standard time when the daylight savings rules
425      * are in effect. A positive number, typically one hour (3600000).
426      * @stable ICU 2.0
427      */

428     public void setDSTSavings(int millisSavedDuringDST) {
429         //unwrapSTZ().setDSTSavings(millisSavedDuringDST);
430
if (millisSavedDuringDST <= 0) {
431             throw new IllegalArgumentException JavaDoc();
432         }
433         dst = millisSavedDuringDST;
434     }
435
436     /**
437      * Returns the amount of time in ms that the clock is advanced during DST.
438      * @return the number of milliseconds the time is
439      * advanced with respect to standard time when the daylight savings rules
440      * are in effect. A positive number, typically one hour (3600000).
441      * @stable ICU 2.0
442      */

443     public int getDSTSavings() {
444         return dst;
445     }
446
447     /**
448      * Constructs a SimpleTimeZone that wraps the given
449      * java.util.SimpleTimeZone. Do not call; use the TimeZone
450      * API.
451      * @internal
452      * @deprecated This API is ICU internal only.
453      */

454     public SimpleTimeZone(java.util.SimpleTimeZone JavaDoc tz, String JavaDoc ID) {
455         super(tz);
456         super.setID(ID);
457         dst = tz.getDSTSavings();
458         raw = tz.getRawOffset();
459     }
460     
461     /**
462      * Returns the java.util.SimpleTimeZone that this class wraps.
463      *
464     java.util.SimpleTimeZone unwrapSTZ() {
465         return (java.util.SimpleTimeZone) unwrap();
466     }
467     */

468     // on JDK 1.4 and later, can't deserialize a SimpleTimeZone as a SimpleTimeZone...
469
private void readObject(java.io.ObjectInputStream JavaDoc in) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
470         in.defaultReadObject();
471         String JavaDoc id = getID();
472         /*
473         if (id!=null && !(zone instanceof java.util.SimpleTimeZone && zone.getID().equals(id))) {
474             // System.out.println("*** readjust " + zone.getClass().getName() + " " + zone.getID() + " ***");
475             java.util.SimpleTimeZone stz =
476                 new java.util.SimpleTimeZone(raw, id);
477             if (dst != 0) {
478                 stz.setDSTSavings(dst);
479                 // if it is 0, then there shouldn't be start/end rules and the default
480                 // behavior should be no dst
481             }
482
483             if (xinfo != null) {
484                 xinfo.applyTo(stz);
485             }
486             zoneJDK = stz;
487         }
488         */

489         /* set all instance variables in this object
490          * to the values in zone
491          */

492          if (xinfo != null) {
493              xinfo.applyTo(this);
494          }
495         
496     }
497     /**
498      * Returns a string representation of this object.
499      * @return a string representation of this object
500      * @draft ICU 3.4.2
501      * @provisional This API might change or be removed in a future release.
502      */

503     public String JavaDoc toString() {
504         return "SimpleTimeZone: " + getID();
505     }
506
507     private STZInfo getSTZInfo() {
508         if (xinfo == null) {
509             xinfo = new STZInfo();
510         }
511         return xinfo;
512     }
513 // WARNING: assumes that no rule is measured from the end of February,
514
// since we don't handle leap years. Could handle assuming always
515
// Gregorian, since we know they didn't have daylight time when
516
// Gregorian calendar started.
517
// private static final int[] STATICMONTHLENGTH = new int[]{31,29,31,30,31,30,31,31,30,31,30,31};
518
private final byte monthLength[] = staticMonthLength;
519     private final static byte staticMonthLength[] = {31,29,31,30,31,30,31,31,30,31,30,31};
520     private final static byte staticLeapMonthLength[] = {31,29,31,30,31,30,31,31,30,31,30,31};
521
522 // -------------------------------------
523

524     /**
525      * @internal revisit for ICU 3.6
526      * @deprecated This API is ICU internal only.
527      */

528     public int getOffset(int era, int year, int month, int day,
529                          int dayOfWeek, int millis)
530     {
531         // Check the month before indexing into STATICMONTHLENGTH. This
532
// duplicates the test that occurs in the 7-argument getOffset(),
533
// however, this is unavoidable. We don't mind because this method, in
534
// fact, should not be called; internal code should always call the
535
// 7-argument getOffset(), and outside code should use Calendar.get(int
536
// field) with fields ZONE_OFFSET and DST_OFFSET. We can't get rid of
537
// this method because it's public API. - liu 8/10/98
538
if(month < Calendar.JANUARY || month > Calendar.DECEMBER) {
539             throw new IllegalArgumentException JavaDoc();
540         }
541
542         return getOffset(era, year, month, day, dayOfWeek, millis, staticMonthLength[month]);
543     }
544
545     /**
546      * @internal revisit for ICU 3.6
547      * @deprecated This API is ICU internal only.
548      */

549     public int getOffset(int era, int year, int month, int day,
550                               int dayOfWeek, int millis,
551                               int monthLength) {
552         // Check the month before indexing into STATICMONTHLENGTH. This
553
// duplicates a test that occurs in the 9-argument getOffset(),
554
// however, this is unavoidable. We don't mind because this method, in
555
// fact, should not be called; internal code should always call the
556
// 9-argument getOffset(), and outside code should use Calendar.get(int
557
// field) with fields ZONE_OFFSET and DST_OFFSET. We can't get rid of
558
// this method because it's public API. - liu 8/10/98
559
if(month < Calendar.JANUARY || month > Calendar.DECEMBER) {
560             throw new IllegalArgumentException JavaDoc();
561         }
562         
563         // TODO FIX We don't handle leap years yet!
564
int prevMonthLength = (month >= 1) ? staticMonthLength[month - 1] : 31;
565
566         return getOffset(era, year, month, day, dayOfWeek, millis,
567                          monthLength, prevMonthLength);
568     }
569
570     int getOffset(int era, int year, int month, int day,
571                   int dayOfWeek, int millis,
572                   int monthLength, int prevMonthLength ){
573
574         if (true) {
575             /* Use this parameter checking code for normal operation. Only one
576              * of these two blocks should actually get compiled into the class
577              * file. */

578             if ((era != GregorianCalendar.AD && era != GregorianCalendar.BC)
579                 || month < Calendar.JANUARY
580                 || month > Calendar.DECEMBER
581                 || day < 1
582                 || day > monthLength
583                 || dayOfWeek < Calendar.SUNDAY
584                 || dayOfWeek > Calendar.SATURDAY
585                 || millis < 0
586                 || millis >= MILLIS_PER_DAY
587                 || monthLength < 28
588                 || monthLength > 31
589                 || prevMonthLength < 28
590                 || prevMonthLength > 31) {
591                 throw new IllegalArgumentException JavaDoc();
592             }
593         } else {
594             /* This parameter checking code is better for debugging, but
595              * overkill for normal operation. Only one of these two blocks
596              * should actually get compiled into the class file. */

597             if (era != GregorianCalendar.AD && era != GregorianCalendar.BC) {
598                 throw new IllegalArgumentException JavaDoc("Illegal era " + era);
599             }
600             if (month < Calendar.JANUARY
601                 || month > Calendar.DECEMBER) {
602                 throw new IllegalArgumentException JavaDoc("Illegal month " + month);
603             }
604             if (day < 1
605                 || day > monthLength) {
606                 throw new IllegalArgumentException JavaDoc("Illegal day " + day+" max month len: "+monthLength);
607             }
608             if (dayOfWeek < Calendar.SUNDAY
609                 || dayOfWeek > Calendar.SATURDAY) {
610                 throw new IllegalArgumentException JavaDoc("Illegal day of week " + dayOfWeek);
611             }
612             if (millis < 0
613                 || millis >= MILLIS_PER_DAY) {
614                 throw new IllegalArgumentException JavaDoc("Illegal millis " + millis);
615             }
616             if (monthLength < 28
617                 || monthLength > 31) {
618                 throw new IllegalArgumentException JavaDoc("Illegal month length " + monthLength);
619             }
620             if (prevMonthLength < 28
621                 || prevMonthLength > 31) {
622                 throw new IllegalArgumentException JavaDoc("Illegal previous month length " + prevMonthLength);
623             }
624         }
625
626         int result = raw;
627
628         // Bail out if we are before the onset of daylight savings time
629
if (!useDaylight || year < startYear || era != GregorianCalendar.AD) return result;
630
631         // Check for southern hemisphere. We assume that the start and end
632
// month are different.
633
boolean southern = (startMonth > endMonth);
634
635         // Compare the date to the starting and ending rules.+1 = date>rule, -1
636
// = date<rule, 0 = date==rule.
637
int startCompare = compareToRule(month, monthLength, prevMonthLength,
638                                          day, dayOfWeek, millis,
639                                          startTimeMode == UTC_TIME ? -raw : 0,
640                                          startMode, startMonth, startDayOfWeek,
641                                          startDay, startTime);
642         int endCompare = 0;
643
644         /* We don't always have to compute endCompare. For many instances,
645          * startCompare is enough to determine if we are in DST or not. In the
646          * northern hemisphere, if we are before the start rule, we can't have
647          * DST. In the southern hemisphere, if we are after the start rule, we
648          * must have DST. This is reflected in the way the next if statement
649          * (not the one immediately following) short circuits. */

650         if (southern != (startCompare >= 0)) {
651             /* For the ending rule comparison, we add the dstSavings to the millis
652              * passed in to convert them from standard to wall time. We then must
653              * normalize the millis to the range 0..millisPerDay-1. */

654             endCompare = compareToRule(month, monthLength, prevMonthLength,
655                                        day, dayOfWeek, millis,
656                                        endTimeMode == WALL_TIME ? dst :
657                                         (endTimeMode == UTC_TIME ? -raw : 0),
658                                        endMode, endMonth, endDayOfWeek,
659                                        endDay, endTime);
660         }
661
662         // Check for both the northern and southern hemisphere cases. We
663
// assume that in the northern hemisphere, the start rule is before the
664
// end rule within the calendar year, and vice versa for the southern
665
// hemisphere.
666
if ((!southern && (startCompare >= 0 && endCompare < 0)) ||
667             (southern && (startCompare >= 0 || endCompare < 0)))
668             result += dst;
669
670         return result;
671     }
672
673 // -------------------------------------
674
private static final int
675         DOM_MODE = 1,
676         DOW_IN_MONTH_MODE=2,
677         DOW_GE_DOM_MODE=3,
678         DOW_LE_DOM_MODE=4;
679
680     /**
681      * TimeMode is used, together with a millisecond offset after
682      * midnight, to specify a rule transition time. Most rules
683      * transition at a local wall time, that is, according to the
684      * current time in effect, either standard, or DST. However, some
685      * rules transition at local standard time, and some at a specific
686      * UTC time. Although it might seem that all times could be
687      * converted to wall time, thus eliminating the need for this
688      * parameter, this is not the case.
689      * @draft ICU 3.6
690      */

691      private static final int WALL_TIME = 0,
692                               STANDARD_TIME = 1,
693                               UTC_TIME = 2;
694
695     /**
696      * Compare a given date in the year to a rule. Return 1, 0, or -1, depending
697      * on whether the date is after, equal to, or before the rule date. The
698      * millis are compared directly against the ruleMillis, so any
699      * standard-daylight adjustments must be handled by the caller.
700      *
701      * @return 1 if the date is after the rule date, -1 if the date is before
702      * the rule date, or 0 if the date is equal to the rule date.
703      */

704     private int compareToRule(int month, int monthLen, int prevMonthLen,
705                                   int dayOfMonth,
706                                   int dayOfWeek, int millis, int millisDelta,
707                                   int ruleMode, int ruleMonth, int ruleDayOfWeek,
708                                   int ruleDay, int ruleMillis)
709     {
710         // Make adjustments for startTimeMode and endTimeMode
711

712         millis += millisDelta;
713         
714         while (millis >= MILLIS_PER_DAY) {
715             millis -= MILLIS_PER_DAY;
716             ++dayOfMonth;
717             dayOfWeek = 1 + (dayOfWeek % 7); // dayOfWeek is one-based
718
if (dayOfMonth > monthLen) {
719                 dayOfMonth = 1;
720                 /* When incrementing the month, it is desirible to overflow
721                  * from DECEMBER to DECEMBER+1, since we use the result to
722                  * compare against a real month. Wraparound of the value
723                  * leads to bug 4173604. */

724                 ++month;
725             }
726         }
727         while (millis < 0) {
728             millis += MILLIS_PER_DAY;
729             --dayOfMonth;
730             dayOfWeek = 1 + ((dayOfWeek+5) % 7); // dayOfWeek is one-based
731
if (dayOfMonth < 1) {
732                 dayOfMonth = prevMonthLen;
733                 --month;
734             }
735         }
736         
737         if (month < ruleMonth) return -1;
738         else if (month > ruleMonth) return 1;
739
740         int ruleDayOfMonth = 0;
741         switch (ruleMode)
742         {
743         case DOM_MODE:
744             ruleDayOfMonth = ruleDay;
745             break;
746         case DOW_IN_MONTH_MODE:
747             // In this case ruleDay is the day-of-week-in-month
748
if (ruleDay > 0)
749                 ruleDayOfMonth = 1 + (ruleDay - 1) * 7 +
750                     (7 + ruleDayOfWeek - (dayOfWeek - dayOfMonth + 1)) % 7;
751             else // Assume ruleDay < 0 here
752
{
753                 ruleDayOfMonth = monthLen + (ruleDay + 1) * 7 -
754                     (7 + (dayOfWeek + monthLen - dayOfMonth) - ruleDayOfWeek) % 7;
755             }
756             break;
757         case DOW_GE_DOM_MODE:
758             ruleDayOfMonth = ruleDay +
759                 (49 + ruleDayOfWeek - ruleDay - dayOfWeek + dayOfMonth) % 7;
760             break;
761         case DOW_LE_DOM_MODE:
762             ruleDayOfMonth = ruleDay -
763                 (49 - ruleDayOfWeek + ruleDay + dayOfWeek - dayOfMonth) % 7;
764             // Note at this point ruleDayOfMonth may be <1, although it will
765
// be >=1 for well-formed rules.
766
break;
767         }
768
769         if (dayOfMonth < ruleDayOfMonth) return -1;
770         else if (dayOfMonth > ruleDayOfMonth) return 1;
771
772         if (millis < ruleMillis){
773                 return -1;
774         }else if (millis > ruleMillis){
775                 return 1;
776         }else{
777                 return 0;
778         }
779     }
780     // data needed for streaming mutated SimpleTimeZones in JDK14
781
private int raw;// the TimeZone's raw GMT offset
782
private int dst = 3600000;
783     private STZInfo xinfo = null;
784     private int startMonth, startDay, startDayOfWeek; // the month, day, DOW, and time DST starts
785
private int startTime;
786     private int startTimeMode, endTimeMode; // Mode for startTime, endTime; see TimeMode
787
private int endMonth, endDay, endDayOfWeek; // the month, day, DOW, and time DST ends
788
private int endTime;
789     private int startYear; // the year these DST rules took effect
790
private boolean useDaylight; // flag indicating whether this TimeZone uses DST
791
private int startMode, endMode; // flags indicating what kind of rules the DST rules are
792

793     /**
794      * @internal revisit for ICU 3.6
795      * @deprecated This API is ICU internal only.
796      */

797     public boolean useDaylightTime(){
798         return useDaylight;
799     }
800     
801     /**
802      * @internal revisit for ICU 3.6
803      * @deprecated This API is ICU internal only.
804      */

805     public boolean inDaylightTime(Date JavaDoc date){
806         GregorianCalendar gc = new GregorianCalendar(this);
807         gc.setTime(date);
808         return gc.inDaylightTime();
809     }
810
811     /**
812      * @internal revisit for ICU 3.6
813      * @deprecated This API is ICU internal only.
814      */

815     public SimpleTimeZone(int raw, String JavaDoc ID,
816                           int startMonth, int startDay,
817                           int startDayOfWeek, int startTime,
818                           int startTimeMode,
819                           int endMonth, int endDay,
820                           int endDayOfWeek, int endTime,
821                           int endTimeMode,int dst){
822         /*this(new java.util.SimpleTimeZone(rawOffsetGMT, ID, savingsStartMonth, savingsStartDay,
823                 savingsStartDayOfWeek, savingsStartTime, savingsEndMonth,
824                 savingsEndDay, savingsEndDayOfWeek, savingsEndTime, savingsDST), ID);*/

825         construct(raw,
826                   startMonth, startDay, startDayOfWeek,
827                   startTime, startTimeMode,
828                   endMonth, endDay, endDayOfWeek,
829                   endTime, endTimeMode,
830                   dst);
831     }
832
833 // -------------------------------------
834
/*
835     SimpleTimeZone(int rawOffsetGMT, String ID,
836         int savingsStartMonth, int savingsStartDay,
837         int savingsStartDayOfWeek, int savingsStartTime,
838         int savingsEndMonth, int savingsEndDay,
839         int savingsEndDayOfWeek, int savingsEndTime)
840     {
841         construct(rawOffsetGMT,
842                   savingsStartMonth, savingsStartDay, savingsStartDayOfWeek,
843                   savingsStartTime, WALL_TIME,
844                   savingsEndMonth, savingsEndDay, savingsEndDayOfWeek,
845                   savingsEndTime, WALL_TIME,
846                   TimeZone.MILLIS_PER_DAY);
847     }
848 */

849 // -------------------------------------
850
/*
851     SimpleTimeZone(int rawOffsetGMT, String ID,
852         int savingsStartMonth, int savingsStartDay,
853         int savingsStartDayOfWeek, int savingsStartTime,
854         int savingsEndMonth, int savingsEndDay,
855         int savingsEndDayOfWeek, int savingsEndTime,
856         int savingsDST)
857     {
858         construct(rawOffsetGMT,
859                   savingsStartMonth, savingsStartDay, savingsStartDayOfWeek,
860                   savingsStartTime, WALL_TIME,
861                   savingsEndMonth, savingsEndDay, savingsEndDayOfWeek,
862                   savingsEndTime, WALL_TIME,
863                   savingsDST);
864     }
865     */

866     /**
867      * Internal construction method.
868      */

869     private void construct(int raw,
870                            int startMonth,
871                            int startDay,
872                            int startDayOfWeek,
873                            int startTime,
874                            int startTimeMode,
875                            int endMonth,
876                            int endDay,
877                            int endDayOfWeek,
878                            int endTime,
879                            int endTimeMode,
880                            int dst) {
881         this.raw = raw;
882         this.startMonth = startMonth;
883         this.startDay = startDay;
884         this.startDayOfWeek = startDayOfWeek;
885         this.startTime = startTime;
886         this.startTimeMode = startTimeMode;
887         this.endMonth = endMonth;
888         this.endDay = endDay;
889         this.endDayOfWeek = endDayOfWeek;
890         this.endTime = endTime;
891         this.endTimeMode = endTimeMode;
892         this.dst = dst;
893         this.startYear = 0;
894         this.startMode = DOM_MODE;
895         this.endMode = DOM_MODE;
896
897         decodeRules();
898
899         if (dst <= 0) {
900             throw new IllegalArgumentException JavaDoc();
901         }
902     }
903     private void decodeRules(){
904         decodeStartRule();
905         decodeEndRule();
906     }
907
908     /**
909      * Decode the start rule and validate the parameters. The parameters are
910      * expected to be in encoded form, which represents the various rule modes
911      * by negating or zeroing certain values. Representation formats are:
912      * <p>
913      * <pre>
914      * DOW_IN_MONTH DOM DOW>=DOM DOW<=DOM no DST
915      * ------------ ----- -------- -------- ----------
916      * month 0..11 same same same don't care
917      * day -5..5 1..31 1..31 -1..-31 0
918      * dayOfWeek 1..7 0 -1..-7 -1..-7 don't care
919      * time 0..ONEDAY same same same don't care
920      * </pre>
921      * The range for month does not include UNDECIMBER since this class is
922      * really specific to GregorianCalendar, which does not use that month.
923      * The range for time includes ONEDAY (vs. ending at ONEDAY-1) because the
924      * end rule is an exclusive limit point. That is, the range of times that
925      * are in DST include those >= the start and < the end. For this reason,
926      * it should be possible to specify an end of ONEDAY in order to include the
927      * entire day. Although this is equivalent to time 0 of the following day,
928      * it's not always possible to specify that, for example, on December 31.
929      * While arguably the start range should still be 0..ONEDAY-1, we keep
930      * the start and end ranges the same for consistency.
931      */

932     private void decodeStartRule() {
933
934         useDaylight = (boolean)((startDay != 0) && (endDay != 0) ? true : false );
935         if (useDaylight && dst == 0) {
936             dst = TimeZone.MILLIS_PER_DAY;
937         }
938         if (startDay != 0) {
939             if (startMonth < Calendar.JANUARY || startMonth > Calendar.DECEMBER) {
940                 throw new IllegalArgumentException JavaDoc();
941             }
942             if (startTime < 0 || startTime >= TimeZone.MILLIS_PER_DAY ||
943                 startTimeMode < WALL_TIME || startTimeMode > UTC_TIME) {
944                 throw new IllegalArgumentException JavaDoc();
945             }
946             if (startDayOfWeek == 0) {
947                 startMode = DOM_MODE;
948             } else {
949                 if (startDayOfWeek > 0) {
950                     startMode = DOW_IN_MONTH_MODE;
951                 } else {
952                     startDayOfWeek = (int)-startDayOfWeek;
953                     if (startDay > 0) {
954                         startMode = DOW_GE_DOM_MODE;
955                     } else {
956                         startDay = (int)-startDay;
957                         startMode = DOW_LE_DOM_MODE;
958                     }
959                 }
960                 if (startDayOfWeek > Calendar.SATURDAY) {
961                     throw new IllegalArgumentException JavaDoc();
962                 }
963             }
964             if (startMode == DOW_IN_MONTH_MODE) {
965                 if (startDay < -5 || startDay > 5) {
966                     throw new IllegalArgumentException JavaDoc();
967                 }
968             } else if (startDay < 1 || startDay > staticMonthLength[startMonth]) {
969                 throw new IllegalArgumentException JavaDoc();
970             }
971         }
972     }
973
974     /**
975      * Decode the end rule and validate the parameters. This method is exactly
976      * analogous to decodeStartRule().
977      * @see #decodeStartRule
978      */

979     private void decodeEndRule() {
980         useDaylight = (boolean)((startDay != 0) && (endDay != 0) ? true : false);
981         if (useDaylight && dst == 0) {
982             dst = TimeZone.MILLIS_PER_DAY;
983         }
984         if (endDay != 0) {
985             if (endMonth < Calendar.JANUARY || endMonth > Calendar.DECEMBER) {
986                 throw new IllegalArgumentException JavaDoc();
987             }
988             if (endTime < 0 || endTime > TimeZone.MILLIS_PER_DAY ||
989                 endTimeMode < WALL_TIME || endTimeMode > UTC_TIME) {
990                 throw new IllegalArgumentException JavaDoc();
991             }
992             if (endDayOfWeek == 0) {
993                 endMode = DOM_MODE;
994             } else {
995                 if (endDayOfWeek > 0) {
996                     endMode = DOW_IN_MONTH_MODE;
997                 } else {
998                     endDayOfWeek = (int)-endDayOfWeek;
999                     if (endDay > 0) {
1000                        endMode = DOW_GE_DOM_MODE;
1001                    } else {
1002                        endDay = (int)-endDay;
1003                        endMode = DOW_LE_DOM_MODE;
1004                    }
1005                }
1006                if (endDayOfWeek > Calendar.SATURDAY) {
1007                    throw new IllegalArgumentException JavaDoc();
1008                }
1009            }
1010            if (endMode == DOW_IN_MONTH_MODE) {
1011                if (endDay < -5 || endDay > 5) {
1012                    throw new IllegalArgumentException JavaDoc();
1013                }
1014            } else if (endDay<1 || endDay > staticMonthLength[endMonth]) {
1015                throw new IllegalArgumentException JavaDoc();
1016            }
1017        }
1018    }
1019
1020    /**
1021     * Return true if obj is a SimpleTimeZone equivalent to this.
1022     * @return true if obj is a SimpleTimeZone equivalent to this
1023     * @draft ICU 3.4.2
1024     * @provisional This API might change or be removed in a future release.
1025     */

1026    public boolean equals(Object JavaDoc obj){
1027        if (this == obj) return true;
1028        if (obj == null || getClass() != obj.getClass()) return false;
1029        SimpleTimeZone that = (SimpleTimeZone) obj;
1030        return raw == that.raw &&
1031            useDaylight == that.useDaylight &&
1032            idEquals(getID(),that.getID()) &&
1033            (!useDaylight
1034             // Only check rules if using DST
1035
|| (dst == that.dst &&
1036                 startMode == that.startMode &&
1037                 startMonth == that.startMonth &&
1038                 startDay == that.startDay &&
1039                 startDayOfWeek == that.startDayOfWeek &&
1040                 startTime == that.startTime &&
1041                 startTimeMode == that.startTimeMode &&
1042                 endMode == that.endMode &&
1043                 endMonth == that.endMonth &&
1044                 endDay == that.endDay &&
1045                 endDayOfWeek == that.endDayOfWeek &&
1046                 endTime == that.endTime &&
1047                 endTimeMode == that.endTimeMode &&
1048                 startYear == that.startYear ));
1049
1050    }
1051    private boolean idEquals(String JavaDoc id1, String JavaDoc id2){
1052        if(id1==null && id2==null){
1053            return true;
1054        }
1055        if(id1!=null && id2!=null){
1056            return id1.equals(id2);
1057        }
1058        return false;
1059    }
1060
1061    /**
1062     * Return the hash code.
1063     * @return the hash code
1064     * @draft ICU 3.4.2
1065     * @provisional This API might change or be removed in a future release.
1066     */

1067    public int hashCode(){
1068        int ret = (int)( super.hashCode() +
1069                                         raw ^ (raw>>>8) +
1070                                         (useDaylight?0:1));
1071        if(!useDaylight){
1072                ret += (int)(dst ^ (dst>>>10) +
1073                                startMode ^ (startMode>>>11) +
1074                                startMonth ^ (startMonth>>>12) +
1075                                startDay ^ (startDay>>>13) +
1076                                startDayOfWeek ^ (startDayOfWeek>>>14) +
1077                                startTime ^ (startTime>>>15) +
1078                                startTimeMode ^ (startTimeMode>>>16) +
1079                                endMode ^ (endMode>>>17) +
1080                                endMonth ^ (endMonth>>>18) +
1081                                endDay ^ (endDay>>>19) +
1082                                endDayOfWeek ^ (endDayOfWeek>>>20) +
1083                                endTime ^ (endTime>>>21) +
1084                                endTimeMode ^ (endTimeMode>>>22) +
1085                                startYear ^ (startYear>>>23));
1086        }
1087                return ret;
1088    }
1089
1090    /**
1091     * Return a clone of this time zone.
1092     * @return a clone of this time zone
1093     * @draft ICU 3.4.2
1094     * @provisional This API might change or be removed in a future release.
1095     */

1096    public Object JavaDoc clone() {
1097        SimpleTimeZone clone = new SimpleTimeZone( raw, getID());
1098        clone.startMonth = startMonth;
1099        clone.startDay = startDay;
1100        clone.startDayOfWeek = startDayOfWeek;
1101        clone.startTime = startTime;
1102        clone.startTimeMode = startTimeMode;
1103        clone.endMonth = endMonth;
1104        clone.endDay = endDay;
1105        clone.endDayOfWeek = endDayOfWeek;
1106        clone.endTime = endTime;
1107        clone.endTimeMode = endTimeMode;
1108        clone.dst = dst;
1109        clone.startYear = startYear;
1110        clone.startMode = startMode;
1111        clone.endMode = endMode;
1112        clone.useDaylight = useDaylight;
1113        return clone;
1114    }
1115
1116    /**
1117     * @internal revisit for ICU 3.6
1118     * @deprecated This API is ICU internal only.
1119     */

1120    public boolean hasSameRules(TimeZone othr) {
1121        if(!(othr instanceof SimpleTimeZone)){
1122                return false;
1123        }
1124        SimpleTimeZone other = (SimpleTimeZone)othr;
1125        return other != null &&
1126        raw == other.raw &&
1127        useDaylight == other.useDaylight &&
1128        (!useDaylight
1129         // Only check rules if using DST
1130
|| (dst == other.dst &&
1131             startMode == other.startMode &&
1132             startMonth == other.startMonth &&
1133             startDay == other.startDay &&
1134             startDayOfWeek == other.startDayOfWeek &&
1135             startTime == other.startTime &&
1136             startTimeMode == other.startTimeMode &&
1137             endMode == other.endMode &&
1138             endMonth == other.endMonth &&
1139             endDay == other.endDay &&
1140             endDayOfWeek == other.endDayOfWeek &&
1141             endTime == other.endTime &&
1142             endTimeMode == other.endTimeMode &&
1143             startYear == other.startYear));
1144    }
1145}
1146
1147
Popular Tags