2 * Copyright (C) 1996-2010, International Business Machines
\r
3 * Corporation and others. All Rights Reserved.
\r
6 package com.ibm.icu.util;
\r
8 import java.io.IOException;
\r
9 import java.util.Date;
\r
11 import com.ibm.icu.impl.Grego;
\r
14 * {@icuenhanced java.util.SimpleTimeZone}.{@icu _usage_}
\r
16 * <p><code>SimpleTimeZone</code> is a concrete subclass of <code>TimeZone</code>
\r
17 * that represents a time zone for use with a Gregorian calendar. This
\r
18 * class does not handle historical changes.
\r
20 * <p>Use a negative value for <code>dayOfWeekInMonth</code> to indicate that
\r
21 * <code>SimpleTimeZone</code> should count from the end of the month backwards. For
\r
22 * example, if Daylight Savings Time starts or ends at the last Sunday in a month, use
\r
23 * <code>dayOfWeekInMonth = -1</code> along with <code>dayOfWeek = Calendar.SUNDAY</code>
\r
24 * to specify the rule.
\r
27 * @see GregorianCalendar
\r
29 * @author David Goldsmith, Mark Davis, Chen-Lieh Huang, Alan Liu
\r
32 public class SimpleTimeZone extends BasicTimeZone {
\r
33 private static final long serialVersionUID = -7034676239311322769L;
\r
36 * Constant for a mode of start or end time specified as local wall time.
\r
39 public static final int WALL_TIME = 0;
\r
42 * Constant for a mode of start or end time specified as local standard time.
\r
45 public static final int STANDARD_TIME = 1;
\r
48 * Constant for a mode of start or end time specified as UTC.
\r
51 public static final int UTC_TIME = 2;
\r
54 * Constructs a SimpleTimeZone with the given base time zone offset from GMT
\r
55 * and time zone ID. Timezone IDs can be obtained from
\r
56 * TimeZone.getAvailableIDs. Normally you should use TimeZone.getDefault to
\r
57 * construct a TimeZone.
\r
59 * @param rawOffset The given base time zone offset to GMT.
\r
60 * @param ID The time zone ID which is obtained from
\r
61 * TimeZone.getAvailableIDs.
\r
64 public SimpleTimeZone(int rawOffset, String ID) {
\r
65 construct(rawOffset, 0, 0, 0,
\r
69 Grego.MILLIS_PER_HOUR);
\r
74 * Constructs a SimpleTimeZone with the given base time zone offset from
\r
75 * GMT, time zone ID, time to start and end the daylight time. Timezone IDs
\r
76 * can be obtained from TimeZone.getAvailableIDs. Normally you should use
\r
77 * TimeZone.getDefault to create a TimeZone. For a time zone that does not
\r
78 * use daylight saving time, do not use this constructor; instead you should
\r
79 * use SimpleTimeZone(rawOffset, ID).
\r
81 * By default, this constructor specifies day-of-week-in-month rules. That
\r
82 * is, if the startDay is 1, and the startDayOfWeek is SUNDAY, then this
\r
83 * indicates the first Sunday in the startMonth. A startDay of -1 likewise
\r
84 * indicates the last Sunday. However, by using negative or zero values for
\r
85 * certain parameters, other types of rules can be specified.
\r
87 * Day of month. To specify an exact day of the month, such as March 1, set
\r
88 * startDayOfWeek to zero.
\r
90 * Day of week after day of month. To specify the first day of the week
\r
91 * occurring on or after an exact day of the month, make the day of the week
\r
92 * negative. For example, if startDay is 5 and startDayOfWeek is -MONDAY,
\r
93 * this indicates the first Monday on or after the 5th day of the
\r
96 * Day of week before day of month. To specify the last day of the week
\r
97 * occurring on or before an exact day of the month, make the day of the
\r
98 * week and the day of the month negative. For example, if startDay is -21
\r
99 * and startDayOfWeek is -WEDNESDAY, this indicates the last Wednesday on or
\r
100 * before the 21st of the startMonth.
\r
102 * The above examples refer to the startMonth, startDay, and startDayOfWeek;
\r
103 * the same applies for the endMonth, endDay, and endDayOfWeek.
\r
105 * @param rawOffset The given base time zone offset to GMT.
\r
106 * @param ID The time zone ID which is obtained from
\r
107 * TimeZone.getAvailableIDs.
\r
108 * @param startMonth The daylight savings starting month. Month is
\r
109 * 0-based. eg, 0 for January.
\r
110 * @param startDay The daylight savings starting
\r
111 * day-of-week-in-month. Please see the member
\r
112 * description for an example.
\r
113 * @param startDayOfWeek The daylight savings starting day-of-week. Please
\r
114 * see the member description for an example.
\r
115 * @param startTime The daylight savings starting time in local wall
\r
116 * time, which is standard time in this case. Please see the
\r
117 * member description for an example.
\r
118 * @param endMonth The daylight savings ending month. Month is
\r
119 * 0-based. eg, 0 for January.
\r
120 * @param endDay The daylight savings ending day-of-week-in-month.
\r
121 * Please see the member description for an example.
\r
122 * @param endDayOfWeek The daylight savings ending day-of-week. Please
\r
123 * see the member description for an example.
\r
124 * @param endTime The daylight savings ending time in local wall time,
\r
125 * which is daylight time in this case. Please see the
\r
126 * member description for an example.
\r
127 * @throws IllegalArgumentException the month, day, dayOfWeek, or time
\r
128 * parameters are out of range for the start or end rule
\r
131 public SimpleTimeZone(int rawOffset, String ID,
\r
132 int startMonth, int startDay, int startDayOfWeek, int startTime,
\r
133 int endMonth, int endDay, int endDayOfWeek, int endTime) {
\r
134 construct(rawOffset,
\r
135 startMonth, startDay, startDayOfWeek,
\r
136 startTime, WALL_TIME,
\r
137 endMonth, endDay, endDayOfWeek,
\r
138 endTime, WALL_TIME,
\r
139 Grego.MILLIS_PER_HOUR);
\r
144 * Constructs a SimpleTimeZone with the given base time zone offset from
\r
145 * GMT, time zone ID, time and its mode to start and end the daylight time.
\r
146 * The mode specifies either {@link #WALL_TIME} or {@link #STANDARD_TIME}
\r
147 * or {@link #UTC_TIME}.
\r
149 * @param rawOffset The given base time zone offset to GMT.
\r
150 * @param ID The time zone ID which is obtained from
\r
151 * TimeZone.getAvailableIDs.
\r
152 * @param startMonth The daylight savings starting month. Month is
\r
153 * 0-based. eg, 0 for January.
\r
154 * @param startDay The daylight savings starting
\r
155 * day-of-week-in-month. Please see the member
\r
156 * description for an example.
\r
157 * @param startDayOfWeek The daylight savings starting day-of-week. Please
\r
158 * see the member description for an example.
\r
159 * @param startTime The daylight savings starting time in local wall
\r
160 * time, which is standard time in this case. Please see the
\r
161 * member description for an example.
\r
162 * @param startTimeMode The mode of the start time specified by startTime.
\r
163 * @param endMonth The daylight savings ending month. Month is
\r
164 * 0-based. eg, 0 for January.
\r
165 * @param endDay The daylight savings ending day-of-week-in-month.
\r
166 * Please see the member description for an example.
\r
167 * @param endDayOfWeek The daylight savings ending day-of-week. Please
\r
168 * see the member description for an example.
\r
169 * @param endTime The daylight savings ending time in local wall time,
\r
170 * which is daylight time in this case. Please see the
\r
171 * member description for an example.
\r
172 * @param endTimeMode The mode of the end time specified by endTime.
\r
173 * @param dstSavings The amount of time in ms saved during DST.
\r
174 * @throws IllegalArgumentException the month, day, dayOfWeek, or time
\r
175 * parameters are out of range for the start or end rule
\r
178 public SimpleTimeZone(int rawOffset, String ID,
\r
179 int startMonth, int startDay,
\r
180 int startDayOfWeek, int startTime,
\r
182 int endMonth, int endDay,
\r
183 int endDayOfWeek, int endTime,
\r
184 int endTimeMode,int dstSavings){
\r
185 construct(rawOffset,
\r
186 startMonth, startDay, startDayOfWeek,
\r
187 startTime, startTimeMode,
\r
188 endMonth, endDay, endDayOfWeek,
\r
189 endTime, endTimeMode,
\r
195 * Constructor. This constructor is identical to the 10-argument
\r
196 * constructor, but also takes a dstSavings parameter.
\r
197 * @param rawOffset The given base time zone offset to GMT.
\r
198 * @param ID The time zone ID which is obtained from
\r
199 * TimeZone.getAvailableIDs.
\r
200 * @param startMonth The daylight savings starting month. Month is
\r
201 * 0-based. eg, 0 for January.
\r
202 * @param startDay The daylight savings starting
\r
203 * day-of-week-in-month. Please see the member
\r
204 * description for an example.
\r
205 * @param startDayOfWeek The daylight savings starting day-of-week. Please
\r
206 * see the member description for an example.
\r
207 * @param startTime The daylight savings starting time in local wall
\r
208 * time, which is standard time in this case. Please see the
\r
209 * member description for an example.
\r
210 * @param endMonth The daylight savings ending month. Month is
\r
211 * 0-based. eg, 0 for January.
\r
212 * @param endDay The daylight savings ending day-of-week-in-month.
\r
213 * Please see the member description for an example.
\r
214 * @param endDayOfWeek The daylight savings ending day-of-week. Please
\r
215 * see the member description for an example.
\r
216 * @param endTime The daylight savings ending time in local wall time,
\r
217 * which is daylight time in this case. Please see the
\r
218 * member description for an example.
\r
219 * @param dstSavings The amount of time in ms saved during DST.
\r
220 * @throws IllegalArgumentException the month, day, dayOfWeek, or time
\r
221 * parameters are out of range for the start or end rule
\r
224 public SimpleTimeZone(int rawOffset, String ID,
\r
225 int startMonth, int startDay, int startDayOfWeek, int startTime,
\r
226 int endMonth, int endDay, int endDayOfWeek, int endTime,
\r
228 construct(rawOffset,
\r
229 startMonth, startDay, startDayOfWeek,
\r
230 startTime, WALL_TIME,
\r
231 endMonth, endDay, endDayOfWeek,
\r
232 endTime, WALL_TIME,
\r
242 public void setID(String ID) {
\r
245 transitionRulesInitialized = false;
\r
249 * Overrides TimeZone
\r
250 * Sets the base time zone offset to GMT.
\r
251 * This is the offset to add "to" UTC to get local time.
\r
252 * @param offsetMillis the raw offset of the time zone
\r
255 public void setRawOffset(int offsetMillis) {
\r
256 raw = offsetMillis;
\r
258 transitionRulesInitialized = false;
\r
262 * Overrides TimeZone
\r
263 * Gets the GMT offset for this time zone.
\r
264 * @return the raw offset
\r
267 public int getRawOffset() {
\r
272 * Sets the daylight savings starting year.
\r
274 * @param year The daylight savings starting year.
\r
277 public void setStartYear(int year) {
\r
278 //unwrapSTZ().setStartYear(year);
\r
280 getSTZInfo().sy = year;
\r
281 this.startYear = year;
\r
283 transitionRulesInitialized = false;
\r
287 * Sets the daylight savings starting rule. For example, Daylight Savings
\r
288 * Time starts at the second Sunday in March, at 2 AM in standard time.
\r
289 * Therefore, you can set the start rule by calling:
\r
290 * setStartRule(Calendar.MARCH, 2, Calendar.SUNDAY, 2*60*60*1000);
\r
292 * @param month The daylight savings starting month. Month is
\r
293 * 0-based. eg, 0 for January.
\r
294 * @param dayOfWeekInMonth The daylight savings starting
\r
295 * day-of-week-in-month. Please see the member
\r
296 * description for an example.
\r
297 * @param dayOfWeek The daylight savings starting day-of-week.
\r
298 * Please see the member description for an
\r
300 * @param time The daylight savings starting time in local wall
\r
301 * time, which is standard time in this case. Please see
\r
302 * the member description for an example.
\r
303 * @throws IllegalArgumentException the month, dayOfWeekInMonth,
\r
304 * dayOfWeek, or time parameters are out of range
\r
307 public void setStartRule(int month, int dayOfWeekInMonth, int dayOfWeek,
\r
309 getSTZInfo().setStart(month, dayOfWeekInMonth, dayOfWeek, time, -1, false);
\r
310 setStartRule(month, dayOfWeekInMonth, dayOfWeek, time, WALL_TIME);
\r
314 * Sets the daylight savings starting rule. For example, in the U.S., Daylight Savings
\r
315 * Time starts at the second Sunday in March, at 2 AM in standard time.
\r
316 * Therefore, you can set the start rule by calling:
\r
317 * <code>setStartRule(Calendar.MARCH, 2, Calendar.SUNDAY, 2*60*60*1000);</code>
\r
318 * The dayOfWeekInMonth and dayOfWeek parameters together specify how to calculate
\r
319 * the exact starting date. Their exact meaning depend on their respective signs,
\r
320 * allowing various types of rules to be constructed, as follows:<ul>
\r
321 * <li>If both dayOfWeekInMonth and dayOfWeek are positive, they specify the
\r
322 * day of week in the month (e.g., (2, WEDNESDAY) is the second Wednesday
\r
324 * <li>If dayOfWeek is positive and dayOfWeekInMonth is negative, they specify
\r
325 * the day of week in the month counting backward from the end of the month.
\r
326 * (e.g., (-1, MONDAY) is the last Monday in the month)
\r
327 * <li>If dayOfWeek is zero and dayOfWeekInMonth is positive, dayOfWeekInMonth
\r
328 * specifies the day of the month, regardless of what day of the week it is.
\r
329 * (e.g., (10, 0) is the tenth day of the month)
\r
330 * <li>If dayOfWeek is zero and dayOfWeekInMonth is negative, dayOfWeekInMonth
\r
331 * specifies the day of the month counting backward from the end of the
\r
332 * month, regardless of what day of the week it is (e.g., (-2, 0) is the
\r
333 * next-to-last day of the month).
\r
334 * <li>If dayOfWeek is negative and dayOfWeekInMonth is positive, they specify the
\r
335 * first specified day of the week on or after the specfied day of the month.
\r
336 * (e.g., (15, -SUNDAY) is the first Sunday after the 15th of the month
\r
337 * [or the 15th itself if the 15th is a Sunday].)
\r
338 * <li>If dayOfWeek and DayOfWeekInMonth are both negative, they specify the
\r
339 * last specified day of the week on or before the specified day of the month.
\r
340 * (e.g., (-20, -TUESDAY) is the last Tuesday before the 20th of the month
\r
341 * [or the 20th itself if the 20th is a Tuesday].)</ul>
\r
342 * @param month the daylight savings starting month. Month is 0-based.
\r
343 * eg, 0 for January.
\r
344 * @param dayOfWeekInMonth the daylight savings starting
\r
345 * day-of-week-in-month. Please see the member description for an example.
\r
346 * @param dayOfWeek the daylight savings starting day-of-week. Please see
\r
347 * the member description for an example.
\r
348 * @param time the daylight savings starting time. Please see the member
\r
349 * description for an example.
\r
351 private void setStartRule(int month, int dayOfWeekInMonth, int dayOfWeek, int time, int mode) {
\r
352 startMonth = month;
\r
353 startDay = dayOfWeekInMonth;
\r
354 startDayOfWeek = dayOfWeek;
\r
356 startTimeMode = mode;
\r
359 transitionRulesInitialized = false;
\r
363 * Sets the DST start rule to a fixed date within a month.
\r
365 * @param month The month in which this rule occurs (0-based).
\r
366 * @param dayOfMonth The date in that month (1-based).
\r
367 * @param time The time of that day (number of millis after midnight)
\r
368 * when DST takes effect in local wall time, which is
\r
369 * standard time in this case.
\r
370 * @throws IllegalArgumentException the month,
\r
371 * dayOfMonth, or time parameters are out of range
\r
374 public void setStartRule(int month, int dayOfMonth, int time) {
\r
375 // unwrapSTZ().setStartRule(month, dayOfMonth, time);
\r
377 getSTZInfo().setStart(month, -1, -1, time, dayOfMonth, false);
\r
378 setStartRule(month, dayOfMonth, 0, time, WALL_TIME);
\r
382 * Sets the DST start rule to a weekday before or after a give date within
\r
383 * a month, e.g., the first Monday on or after the 8th.
\r
385 * @param month The month in which this rule occurs (0-based).
\r
386 * @param dayOfMonth A date within that month (1-based).
\r
387 * @param dayOfWeek The day of the week on which this rule occurs.
\r
388 * @param time The time of that day (number of millis after midnight)
\r
389 * when DST takes effect in local wall time, which is
\r
390 * standard time in this case.
\r
391 * @param after If true, this rule selects the first dayOfWeek on
\r
392 * or after dayOfMonth. If false, this rule selects
\r
393 * the last dayOfWeek on or before dayOfMonth.
\r
394 * @throws IllegalArgumentException the month, dayOfMonth,
\r
395 * dayOfWeek, or time parameters are out of range
\r
398 public void setStartRule(int month, int dayOfMonth, int dayOfWeek, int time, boolean after) {
\r
399 getSTZInfo().setStart(month, -1, dayOfWeek, time, dayOfMonth, after);
\r
400 setStartRule(month, after ? dayOfMonth : -dayOfMonth,
\r
401 -dayOfWeek, time, WALL_TIME);
\r
405 * Sets the daylight savings ending rule. For example, if Daylight Savings Time
\r
406 * ends at the last (-1) Sunday in October, at 2 AM in standard time,
\r
407 * you can set the end rule by calling:
\r
408 * <code>setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*60*60*1000);</code>
\r
410 * @param month The daylight savings ending month. Month is
\r
411 * 0-based. eg, 0 for January.
\r
412 * @param dayOfWeekInMonth The daylight savings ending
\r
413 * day-of-week-in-month. Please see the member
\r
414 * description for an example.
\r
415 * @param dayOfWeek The daylight savings ending day-of-week. Please
\r
416 * see the member description for an example.
\r
417 * @param time The daylight savings ending time in local wall time,
\r
418 * which is daylight time in this case. Please see the
\r
419 * member description for an example.
\r
420 * @throws IllegalArgumentException the month, dayOfWeekInMonth,
\r
421 * dayOfWeek, or time parameters are out of range
\r
424 public void setEndRule(int month, int dayOfWeekInMonth, int dayOfWeek, int time) {
\r
425 getSTZInfo().setEnd(month, dayOfWeekInMonth, dayOfWeek, time, -1, false);
\r
426 setEndRule(month, dayOfWeekInMonth, dayOfWeek, time, WALL_TIME);
\r
430 * Sets the DST end rule to a fixed date within a month.
\r
432 * @param month The month in which this rule occurs (0-based).
\r
433 * @param dayOfMonth The date in that month (1-based).
\r
434 * @param time The time of that day (number of millis after midnight)
\r
435 * when DST ends in local wall time, which is daylight
\r
436 * time in this case.
\r
437 * @throws IllegalArgumentException the month,
\r
438 * dayOfMonth, or time parameters are out of range
\r
441 public void setEndRule(int month, int dayOfMonth, int time) {
\r
442 getSTZInfo().setEnd(month, -1, -1, time, dayOfMonth, false);
\r
443 setEndRule(month, dayOfMonth, WALL_TIME, time);
\r
447 * Sets the DST end rule to a weekday before or after a give date within
\r
448 * a month, e.g., the first Monday on or after the 8th.
\r
450 * @param month The month in which this rule occurs (0-based).
\r
451 * @param dayOfMonth A date within that month (1-based).
\r
452 * @param dayOfWeek The day of the week on which this rule occurs.
\r
453 * @param time The time of that day (number of millis after midnight)
\r
454 * when DST ends in local wall time, which is daylight
\r
455 * time in this case.
\r
456 * @param after If true, this rule selects the first dayOfWeek on
\r
457 * or after dayOfMonth. If false, this rule selects
\r
458 * the last dayOfWeek on or before dayOfMonth.
\r
459 * @throws IllegalArgumentException the month, dayOfMonth,
\r
460 * dayOfWeek, or time parameters are out of range
\r
463 public void setEndRule(int month, int dayOfMonth, int dayOfWeek, int time, boolean after) {
\r
464 getSTZInfo().setEnd(month, -1, dayOfWeek, time, dayOfMonth, after);
\r
465 setEndRule(month, dayOfMonth, dayOfWeek, time, WALL_TIME, after);
\r
468 private void setEndRule(int month, int dayOfMonth, int dayOfWeek,
\r
469 int time, int mode, boolean after){
\r
470 setEndRule(month, after ? dayOfMonth : -dayOfMonth, -dayOfWeek, time, mode);
\r
474 * Sets the daylight savings ending rule. For example, in the U.S., Daylight
\r
475 * Savings Time ends at the first Sunday in November, at 2 AM in standard time.
\r
476 * Therefore, you can set the end rule by calling:
\r
477 * setEndRule(Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2*60*60*1000);
\r
478 * Various other types of rules can be specified by manipulating the dayOfWeek
\r
479 * and dayOfWeekInMonth parameters. For complete details, see the documentation
\r
480 * for setStartRule().
\r
481 * @param month the daylight savings ending month. Month is 0-based.
\r
482 * eg, 0 for January.
\r
483 * @param dayOfWeekInMonth the daylight savings ending
\r
484 * day-of-week-in-month. See setStartRule() for a complete explanation.
\r
485 * @param dayOfWeek the daylight savings ending day-of-week. See setStartRule()
\r
486 * for a complete explanation.
\r
487 * @param time the daylight savings ending time. Please see the member
\r
488 * description for an example.
\r
490 private void setEndRule(int month, int dayOfWeekInMonth, int dayOfWeek, int time, int mode){
\r
492 endDay = dayOfWeekInMonth;
\r
493 endDayOfWeek = dayOfWeek;
\r
495 endTimeMode = mode;
\r
498 transitionRulesInitialized = false;
\r
502 * Sets the amount of time in ms that the clock is advanced during DST.
\r
503 * @param millisSavedDuringDST the number of milliseconds the time is
\r
504 * advanced with respect to standard time when the daylight savings rules
\r
505 * are in effect. A positive number, typically one hour (3600000).
\r
508 public void setDSTSavings(int millisSavedDuringDST) {
\r
509 if (millisSavedDuringDST <= 0) {
\r
510 throw new IllegalArgumentException();
\r
512 dst = millisSavedDuringDST;
\r
514 transitionRulesInitialized = false;
\r
518 * Returns the amount of time in ms that the clock is advanced during DST.
\r
519 * @return the number of milliseconds the time is
\r
520 * advanced with respect to standard time when the daylight savings rules
\r
521 * are in effect. A positive number, typically one hour (3600000).
\r
524 public int getDSTSavings() {
\r
529 * Returns the java.util.SimpleTimeZone that this class wraps.
\r
531 java.util.SimpleTimeZone unwrapSTZ() {
\r
532 return (java.util.SimpleTimeZone) unwrap();
\r
536 // on JDK 1.4 and later, can't deserialize a SimpleTimeZone as a SimpleTimeZone...
\r
537 private void readObject(java.io.ObjectInputStream in) throws IOException,
\r
538 ClassNotFoundException {
\r
539 in.defaultReadObject();
\r
541 String id = getID();
\r
542 if (id!=null && !(zone instanceof java.util.SimpleTimeZone && zone.getID().equals(id))) {
\r
543 // System.out.println("*** readjust " + zone.getClass().getName() +
\r
544 // " " + zone.getID() + " ***");
\r
545 java.util.SimpleTimeZone stz =
\r
546 new java.util.SimpleTimeZone(raw, id);
\r
548 stz.setDSTSavings(dst);
\r
549 // if it is 0, then there shouldn't be start/end rules and the default
\r
550 // behavior should be no dst
\r
553 if (xinfo != null) {
\r
554 xinfo.applyTo(stz);
\r
559 /* set all instance variables in this object
\r
560 * to the values in zone
\r
562 if (xinfo != null) {
\r
563 xinfo.applyTo(this);
\r
568 * Returns a string representation of this object.
\r
569 * @return a string representation of this object
\r
572 public String toString() {
\r
573 return "SimpleTimeZone: " + getID();
\r
576 private STZInfo getSTZInfo() {
\r
577 if (xinfo == null) {
\r
578 xinfo = new STZInfo();
\r
583 // Use only for decodeStartRule() and decodeEndRule() where the year is not
\r
584 // available. Set February to 29 days to accomodate rules with that date
\r
585 // and day-of-week-on-or-before-that-date mode (DOW_LE_DOM_MODE).
\r
586 // The compareToRule() method adjusts to February 28 in non-leap years.
\r
588 // For actual getOffset() calculations, use TimeZone::monthLength() and
\r
589 // TimeZone::previousMonthLength() which take leap years into account.
\r
590 // We handle leap years assuming always
\r
591 // Gregorian, since we know they didn't have daylight time when
\r
592 // Gregorian calendar started.
\r
593 private final static byte staticMonthLength[] = {31,29,31,30,31,30,31,31,30,31,30,31};
\r
599 public int getOffset(int era, int year, int month, int day,
\r
600 int dayOfWeek, int millis)
\r
602 // Check the month before calling Grego.monthLength(). This
\r
603 // duplicates the test that occurs in the 7-argument getOffset(),
\r
604 // however, this is unavoidable. We don't mind because this method, in
\r
605 // fact, should not be called; internal code should always call the
\r
606 // 7-argument getOffset(), and outside code should use Calendar.get(int
\r
607 // field) with fields ZONE_OFFSET and DST_OFFSET. We can't get rid of
\r
608 // this method because it's public API. - liu 8/10/98
\r
609 if(month < Calendar.JANUARY || month > Calendar.DECEMBER) {
\r
610 throw new IllegalArgumentException();
\r
613 return getOffset(era, year, month, day, dayOfWeek, millis, Grego.monthLength(year, month));
\r
618 * @deprecated This API is ICU internal only.
\r
620 public int getOffset(int era, int year, int month, int day,
\r
621 int dayOfWeek, int millis,
\r
623 // Check the month before calling Grego.monthLength(). This
\r
624 // duplicates a test that occurs in the 9-argument getOffset(),
\r
625 // however, this is unavoidable. We don't mind because this method, in
\r
626 // fact, should not be called; internal code should always call the
\r
627 // 9-argument getOffset(), and outside code should use Calendar.get(int
\r
628 // field) with fields ZONE_OFFSET and DST_OFFSET. We can't get rid of
\r
629 // this method because it's public API. - liu 8/10/98
\r
630 if(month < Calendar.JANUARY || month > Calendar.DECEMBER) {
\r
631 throw new IllegalArgumentException();
\r
634 return getOffset(era, year, month, day, dayOfWeek, millis,
\r
635 Grego.monthLength(year, month), Grego.previousMonthLength(year, month));
\r
638 int getOffset(int era, int year, int month, int day,
\r
639 int dayOfWeek, int millis,
\r
640 int monthLength, int prevMonthLength ){
\r
643 /* Use this parameter checking code for normal operation. Only one
\r
644 * of these two blocks should actually get compiled into the class
\r
646 if ((era != GregorianCalendar.AD && era != GregorianCalendar.BC)
\r
647 || month < Calendar.JANUARY
\r
648 || month > Calendar.DECEMBER
\r
650 || day > monthLength
\r
651 || dayOfWeek < Calendar.SUNDAY
\r
652 || dayOfWeek > Calendar.SATURDAY
\r
654 || millis >= Grego.MILLIS_PER_DAY
\r
655 || monthLength < 28
\r
656 || monthLength > 31
\r
657 || prevMonthLength < 28
\r
658 || prevMonthLength > 31) {
\r
659 throw new IllegalArgumentException();
\r
662 //Eclipse stated the following is "dead code"
\r
664 // This parameter checking code is better for debugging, but
\r
665 // overkill for normal operation. Only one of these two blocks
\r
666 // should actually get compiled into the class file.
\r
667 if (era != GregorianCalendar.AD && era != GregorianCalendar.BC) {
\r
668 throw new IllegalArgumentException("Illegal era " + era);
\r
670 if (month < Calendar.JANUARY
\r
671 || month > Calendar.DECEMBER) {
\r
672 throw new IllegalArgumentException("Illegal month " + month);
\r
675 || day > monthLength) {
\r
676 throw new IllegalArgumentException("Illegal day " + day+" max month len: "+monthLength);
\r
678 if (dayOfWeek < Calendar.SUNDAY
\r
679 || dayOfWeek > Calendar.SATURDAY) {
\r
680 throw new IllegalArgumentException("Illegal day of week " + dayOfWeek);
\r
683 || millis >= Grego.MILLIS_PER_DAY) {
\r
684 throw new IllegalArgumentException("Illegal millis " + millis);
\r
686 if (monthLength < 28
\r
687 || monthLength > 31) {
\r
688 throw new IllegalArgumentException("Illegal month length " + monthLength);
\r
690 if (prevMonthLength < 28
\r
691 || prevMonthLength > 31) {
\r
692 throw new IllegalArgumentException("Illegal previous month length " + prevMonthLength);
\r
698 // Bail out if we are before the onset of daylight savings time
\r
699 if (!useDaylight || year < startYear || era != GregorianCalendar.AD) return result;
\r
701 // Check for southern hemisphere. We assume that the start and end
\r
702 // month are different.
\r
703 boolean southern = (startMonth > endMonth);
\r
705 // Compare the date to the starting and ending rules.+1 = date>rule, -1
\r
706 // = date<rule, 0 = date==rule.
\r
707 int startCompare = compareToRule(month, monthLength, prevMonthLength,
\r
708 day, dayOfWeek, millis,
\r
709 startTimeMode == UTC_TIME ? -raw : 0,
\r
710 startMode, startMonth, startDayOfWeek,
\r
711 startDay, startTime);
\r
712 int endCompare = 0;
\r
714 /* We don't always have to compute endCompare. For many instances,
\r
715 * startCompare is enough to determine if we are in DST or not. In the
\r
716 * northern hemisphere, if we are before the start rule, we can't have
\r
717 * DST. In the southern hemisphere, if we are after the start rule, we
\r
718 * must have DST. This is reflected in the way the next if statement
\r
719 * (not the one immediately following) short circuits. */
\r
720 if (southern != (startCompare >= 0)) {
\r
721 /* For the ending rule comparison, we add the dstSavings to the millis
\r
722 * passed in to convert them from standard to wall time. We then must
\r
723 * normalize the millis to the range 0..millisPerDay-1. */
\r
724 endCompare = compareToRule(month, monthLength, prevMonthLength,
\r
725 day, dayOfWeek, millis,
\r
726 endTimeMode == WALL_TIME ? dst :
\r
727 (endTimeMode == UTC_TIME ? -raw : 0),
\r
728 endMode, endMonth, endDayOfWeek,
\r
732 // Check for both the northern and southern hemisphere cases. We
\r
733 // assume that in the northern hemisphere, the start rule is before the
\r
734 // end rule within the calendar year, and vice versa for the southern
\r
736 if ((!southern && (startCompare >= 0 && endCompare < 0)) ||
\r
737 (southern && (startCompare >= 0 || endCompare < 0)))
\r
746 * @deprecated This API is ICU internal only.
\r
748 public void getOffsetFromLocal(long date,
\r
749 int nonExistingTimeOpt, int duplicatedTimeOpt, int[] offsets) {
\r
750 offsets[0] = getRawOffset();
\r
751 int fields[] = new int[6];
\r
752 Grego.timeToFields(date, fields);
\r
753 offsets[1] = getOffset(GregorianCalendar.AD,
\r
754 fields[0], fields[1], fields[2],
\r
755 fields[3], fields[5]) - offsets[0];
\r
757 boolean recalc = false;
\r
759 // Now, we need some adjustment
\r
760 if (offsets[1] > 0) {
\r
761 if ((nonExistingTimeOpt & STD_DST_MASK) == LOCAL_STD
\r
762 || (nonExistingTimeOpt & STD_DST_MASK) != LOCAL_DST
\r
763 && (nonExistingTimeOpt & FORMER_LATTER_MASK) != LOCAL_LATTER) {
\r
764 date -= getDSTSavings();
\r
768 if ((duplicatedTimeOpt & STD_DST_MASK) == LOCAL_DST
\r
769 || (duplicatedTimeOpt & STD_DST_MASK) != LOCAL_STD
\r
770 && (duplicatedTimeOpt & FORMER_LATTER_MASK) == LOCAL_FORMER) {
\r
771 date -= getDSTSavings();
\r
777 Grego.timeToFields(date, fields);
\r
778 offsets[1] = getOffset(GregorianCalendar.AD,
\r
779 fields[0], fields[1], fields[2],
\r
780 fields[3], fields[5]) - offsets[0];
\r
784 private static final int
\r
786 DOW_IN_MONTH_MODE=2,
\r
791 * Compare a given date in the year to a rule. Return 1, 0, or -1, depending
\r
792 * on whether the date is after, equal to, or before the rule date. The
\r
793 * millis are compared directly against the ruleMillis, so any
\r
794 * standard-daylight adjustments must be handled by the caller.
\r
796 * @return 1 if the date is after the rule date, -1 if the date is before
\r
797 * the rule date, or 0 if the date is equal to the rule date.
\r
799 private int compareToRule(int month, int monthLen, int prevMonthLen,
\r
801 int dayOfWeek, int millis, int millisDelta,
\r
802 int ruleMode, int ruleMonth, int ruleDayOfWeek,
\r
803 int ruleDay, int ruleMillis)
\r
805 // Make adjustments for startTimeMode and endTimeMode
\r
807 millis += millisDelta;
\r
809 while (millis >= Grego.MILLIS_PER_DAY) {
\r
810 millis -= Grego.MILLIS_PER_DAY;
\r
812 dayOfWeek = 1 + (dayOfWeek % 7); // dayOfWeek is one-based
\r
813 if (dayOfMonth > monthLen) {
\r
815 /* When incrementing the month, it is desirable to overflow
\r
816 * from DECEMBER to DECEMBER+1, since we use the result to
\r
817 * compare against a real month. Wraparound of the value
\r
818 * leads to bug 4173604. */
\r
823 * For some reasons, Sun Java 6 on Solaris/Linux has a problem with
\r
824 * the while loop below (at least Java 6 up to build 1.6.0_02-b08).
\r
825 * It looks the JRE messes up the variable 'millis' while executing
\r
826 * the code in the while block. The problem is not reproduced with
\r
827 * JVM option -Xint, that is, it is likely a bug of the HotSpot
\r
828 * adaptive compiler. Moving 'millis += Grego.MILLIS_PER_DAY'
\r
829 * to the end of this while block seems to resolve the problem.
\r
830 * See ticket#5887 about the problem in detail.
\r
832 while (millis < 0) {
\r
833 //millis += Grego.MILLIS_PER_DAY;
\r
835 dayOfWeek = 1 + ((dayOfWeek+5) % 7); // dayOfWeek is one-based
\r
836 if (dayOfMonth < 1) {
\r
837 dayOfMonth = prevMonthLen;
\r
840 millis += Grego.MILLIS_PER_DAY;
\r
843 if (month < ruleMonth) return -1;
\r
844 else if (month > ruleMonth) return 1;
\r
846 int ruleDayOfMonth = 0;
\r
848 // Adjust the ruleDay to the monthLen, for non-leap year February 29 rule days.
\r
849 if (ruleDay > monthLen) {
\r
850 ruleDay = monthLen;
\r
856 ruleDayOfMonth = ruleDay;
\r
858 case DOW_IN_MONTH_MODE:
\r
859 // In this case ruleDay is the day-of-week-in-month
\r
861 ruleDayOfMonth = 1 + (ruleDay - 1) * 7 +
\r
862 (7 + ruleDayOfWeek - (dayOfWeek - dayOfMonth + 1)) % 7;
\r
863 else // Assume ruleDay < 0 here
\r
865 ruleDayOfMonth = monthLen + (ruleDay + 1) * 7 -
\r
866 (7 + (dayOfWeek + monthLen - dayOfMonth) - ruleDayOfWeek) % 7;
\r
869 case DOW_GE_DOM_MODE:
\r
870 ruleDayOfMonth = ruleDay +
\r
871 (49 + ruleDayOfWeek - ruleDay - dayOfWeek + dayOfMonth) % 7;
\r
873 case DOW_LE_DOM_MODE:
\r
874 ruleDayOfMonth = ruleDay -
\r
875 (49 - ruleDayOfWeek + ruleDay + dayOfWeek - dayOfMonth) % 7;
\r
876 // Note at this point ruleDayOfMonth may be <1, although it will
\r
877 // be >=1 for well-formed rules.
\r
881 if (dayOfMonth < ruleDayOfMonth) return -1;
\r
882 else if (dayOfMonth > ruleDayOfMonth) return 1;
\r
884 if (millis < ruleMillis){
\r
886 }else if (millis > ruleMillis){
\r
893 // data needed for streaming mutated SimpleTimeZones in JDK14
\r
894 private int raw;// the TimeZone's raw GMT offset
\r
895 private int dst = 3600000;
\r
896 private STZInfo xinfo = null;
\r
897 private int startMonth, startDay, startDayOfWeek; // the month, day, DOW, and time DST starts
\r
898 private int startTime;
\r
899 private int startTimeMode, endTimeMode; // Mode for startTime, endTime; see TimeMode
\r
900 private int endMonth, endDay, endDayOfWeek; // the month, day, DOW, and time DST ends
\r
901 private int endTime;
\r
902 private int startYear; // the year these DST rules took effect
\r
903 private boolean useDaylight; // flag indicating whether this TimeZone uses DST
\r
904 private int startMode, endMode; // flags indicating what kind of rules the DST rules are
\r
907 * Overrides TimeZone
\r
908 * Queries if this time zone uses Daylight Saving Time.
\r
911 public boolean useDaylightTime(){
\r
912 return useDaylight;
\r
916 * Overrides TimeZone
\r
917 * Queries if the give date is in Daylight Saving Time.
\r
920 public boolean inDaylightTime(Date date){
\r
921 GregorianCalendar gc = new GregorianCalendar(this);
\r
923 return gc.inDaylightTime();
\r
927 * Internal construction method.
\r
929 private void construct(int _raw,
\r
932 int _startDayOfWeek,
\r
934 int _startTimeMode,
\r
942 startMonth = _startMonth;
\r
943 startDay = _startDay;
\r
944 startDayOfWeek = _startDayOfWeek;
\r
945 startTime = _startTime;
\r
946 startTimeMode = _startTimeMode;
\r
947 endMonth = _endMonth;
\r
949 endDayOfWeek = _endDayOfWeek;
\r
950 endTime = _endTime;
\r
951 endTimeMode = _endTimeMode;
\r
954 startMode = DOM_MODE;
\r
955 endMode = DOM_MODE;
\r
960 throw new IllegalArgumentException();
\r
963 private void decodeRules(){
\r
969 * Decode the start rule and validate the parameters. The parameters are
\r
970 * expected to be in encoded form, which represents the various rule modes
\r
971 * by negating or zeroing certain values. Representation formats are:
\r
974 * DOW_IN_MONTH DOM DOW>=DOM DOW<=DOM no DST
\r
975 * ------------ ----- -------- -------- ----------
\r
976 * month 0..11 same same same don't care
\r
977 * day -5..5 1..31 1..31 -1..-31 0
\r
978 * dayOfWeek 1..7 0 -1..-7 -1..-7 don't care
\r
979 * time 0..ONEDAY same same same don't care
\r
981 * The range for month does not include UNDECIMBER since this class is
\r
982 * really specific to GregorianCalendar, which does not use that month.
\r
983 * The range for time includes ONEDAY (vs. ending at ONEDAY-1) because the
\r
984 * end rule is an exclusive limit point. That is, the range of times that
\r
985 * are in DST include those >= the start and < the end. For this reason,
\r
986 * it should be possible to specify an end of ONEDAY in order to include the
\r
987 * entire day. Although this is equivalent to time 0 of the following day,
\r
988 * it's not always possible to specify that, for example, on December 31.
\r
989 * While arguably the start range should still be 0..ONEDAY-1, we keep
\r
990 * the start and end ranges the same for consistency.
\r
992 private void decodeStartRule() {
\r
993 useDaylight = (startDay != 0) && (endDay != 0);
\r
994 if (useDaylight && dst == 0) {
\r
995 dst = Grego.MILLIS_PER_DAY;
\r
997 if (startDay != 0) {
\r
998 if (startMonth < Calendar.JANUARY || startMonth > Calendar.DECEMBER) {
\r
999 throw new IllegalArgumentException();
\r
1001 if (startTime < 0 || startTime > Grego.MILLIS_PER_DAY ||
\r
1002 startTimeMode < WALL_TIME || startTimeMode > UTC_TIME) {
\r
1003 throw new IllegalArgumentException();
\r
1005 if (startDayOfWeek == 0) {
\r
1006 startMode = DOM_MODE;
\r
1008 if (startDayOfWeek > 0) {
\r
1009 startMode = DOW_IN_MONTH_MODE;
\r
1011 startDayOfWeek = -startDayOfWeek;
\r
1012 if (startDay > 0) {
\r
1013 startMode = DOW_GE_DOM_MODE;
\r
1015 startDay = -startDay;
\r
1016 startMode = DOW_LE_DOM_MODE;
\r
1019 if (startDayOfWeek > Calendar.SATURDAY) {
\r
1020 throw new IllegalArgumentException();
\r
1023 if (startMode == DOW_IN_MONTH_MODE) {
\r
1024 if (startDay < -5 || startDay > 5) {
\r
1025 throw new IllegalArgumentException();
\r
1027 } else if (startDay < 1 || startDay > staticMonthLength[startMonth]) {
\r
1028 throw new IllegalArgumentException();
\r
1034 * Decode the end rule and validate the parameters. This method is exactly
\r
1035 * analogous to decodeStartRule().
\r
1036 * @see #decodeStartRule
\r
1038 private void decodeEndRule() {
\r
1039 useDaylight = (startDay != 0) && (endDay != 0);
\r
1040 if (useDaylight && dst == 0) {
\r
1041 dst = Grego.MILLIS_PER_DAY;
\r
1043 if (endDay != 0) {
\r
1044 if (endMonth < Calendar.JANUARY || endMonth > Calendar.DECEMBER) {
\r
1045 throw new IllegalArgumentException();
\r
1047 if (endTime < 0 || endTime > Grego.MILLIS_PER_DAY ||
\r
1048 endTimeMode < WALL_TIME || endTimeMode > UTC_TIME) {
\r
1049 throw new IllegalArgumentException();
\r
1051 if (endDayOfWeek == 0) {
\r
1052 endMode = DOM_MODE;
\r
1054 if (endDayOfWeek > 0) {
\r
1055 endMode = DOW_IN_MONTH_MODE;
\r
1057 endDayOfWeek = -endDayOfWeek;
\r
1059 endMode = DOW_GE_DOM_MODE;
\r
1062 endMode = DOW_LE_DOM_MODE;
\r
1065 if (endDayOfWeek > Calendar.SATURDAY) {
\r
1066 throw new IllegalArgumentException();
\r
1069 if (endMode == DOW_IN_MONTH_MODE) {
\r
1070 if (endDay < -5 || endDay > 5) {
\r
1071 throw new IllegalArgumentException();
\r
1073 } else if (endDay<1 || endDay > staticMonthLength[endMonth]) {
\r
1074 throw new IllegalArgumentException();
\r
1080 * Overrides equals.
\r
1081 * @return true if obj is a SimpleTimeZone equivalent to this
\r
1084 public boolean equals(Object obj){
\r
1085 if (this == obj) return true;
\r
1086 if (obj == null || getClass() != obj.getClass()) return false;
\r
1087 SimpleTimeZone that = (SimpleTimeZone) obj;
\r
1088 return raw == that.raw &&
\r
1089 useDaylight == that.useDaylight &&
\r
1090 idEquals(getID(),that.getID()) &&
\r
1092 // Only check rules if using DST
\r
1093 || (dst == that.dst &&
\r
1094 startMode == that.startMode &&
\r
1095 startMonth == that.startMonth &&
\r
1096 startDay == that.startDay &&
\r
1097 startDayOfWeek == that.startDayOfWeek &&
\r
1098 startTime == that.startTime &&
\r
1099 startTimeMode == that.startTimeMode &&
\r
1100 endMode == that.endMode &&
\r
1101 endMonth == that.endMonth &&
\r
1102 endDay == that.endDay &&
\r
1103 endDayOfWeek == that.endDayOfWeek &&
\r
1104 endTime == that.endTime &&
\r
1105 endTimeMode == that.endTimeMode &&
\r
1106 startYear == that.startYear ));
\r
1109 private boolean idEquals(String id1, String id2){
\r
1110 if(id1==null && id2==null){
\r
1113 if(id1!=null && id2!=null){
\r
1114 return id1.equals(id2);
\r
1120 * Overrides hashCode.
\r
1123 public int hashCode(){
\r
1124 int ret = super.hashCode()
\r
1125 + raw ^ (raw >>> 8)
\r
1126 + (useDaylight ? 0 : 1);
\r
1128 ret += dst ^ (dst >>> 10) +
\r
1129 startMode ^ (startMode>>>11) +
\r
1130 startMonth ^ (startMonth>>>12) +
\r
1131 startDay ^ (startDay>>>13) +
\r
1132 startDayOfWeek ^ (startDayOfWeek>>>14) +
\r
1133 startTime ^ (startTime>>>15) +
\r
1134 startTimeMode ^ (startTimeMode>>>16) +
\r
1135 endMode ^ (endMode>>>17) +
\r
1136 endMonth ^ (endMonth>>>18) +
\r
1137 endDay ^ (endDay>>>19) +
\r
1138 endDayOfWeek ^ (endDayOfWeek>>>20) +
\r
1139 endTime ^ (endTime>>>21) +
\r
1140 endTimeMode ^ (endTimeMode>>>22) +
\r
1141 startYear ^ (startYear>>>23);
\r
1147 * Overrides clone.
\r
1150 public Object clone() {
\r
1151 return super.clone();
\r
1155 * Returns true if this zone has the same rules and offset as another zone.
\r
1156 * @param othr the TimeZone object to be compared with
\r
1157 * @return true if the given zone has the same rules and offset as this one
\r
1160 public boolean hasSameRules(TimeZone othr) {
\r
1161 if(!(othr instanceof SimpleTimeZone)){
\r
1164 SimpleTimeZone other = (SimpleTimeZone)othr;
\r
1165 return other != null &&
\r
1166 raw == other.raw &&
\r
1167 useDaylight == other.useDaylight &&
\r
1169 // Only check rules if using DST
\r
1170 || (dst == other.dst &&
\r
1171 startMode == other.startMode &&
\r
1172 startMonth == other.startMonth &&
\r
1173 startDay == other.startDay &&
\r
1174 startDayOfWeek == other.startDayOfWeek &&
\r
1175 startTime == other.startTime &&
\r
1176 startTimeMode == other.startTimeMode &&
\r
1177 endMode == other.endMode &&
\r
1178 endMonth == other.endMonth &&
\r
1179 endDay == other.endDay &&
\r
1180 endDayOfWeek == other.endDayOfWeek &&
\r
1181 endTime == other.endTime &&
\r
1182 endTimeMode == other.endTimeMode &&
\r
1183 startYear == other.startYear));
\r
1186 // BasicTimeZone methods
\r
1192 public TimeZoneTransition getNextTransition(long base, boolean inclusive) {
\r
1193 if (!useDaylight) {
\r
1197 initTransitionRules();
\r
1198 long firstTransitionTime = firstTransition.getTime();
\r
1199 if (base < firstTransitionTime || (inclusive && base == firstTransitionTime)) {
\r
1200 return firstTransition;
\r
1202 Date stdDate = stdRule.getNextStart(base, dstRule.getRawOffset(), dstRule.getDSTSavings(),
\r
1204 Date dstDate = dstRule.getNextStart(base, stdRule.getRawOffset(), stdRule.getDSTSavings(),
\r
1206 if (stdDate != null && (dstDate == null || stdDate.before(dstDate))) {
\r
1207 return new TimeZoneTransition(stdDate.getTime(), dstRule, stdRule);
\r
1209 if (dstDate != null && (stdDate == null || dstDate.before(stdDate))) {
\r
1210 return new TimeZoneTransition(dstDate.getTime(), stdRule, dstRule);
\r
1219 public TimeZoneTransition getPreviousTransition(long base, boolean inclusive) {
\r
1220 if (!useDaylight) {
\r
1224 initTransitionRules();
\r
1225 long firstTransitionTime = firstTransition.getTime();
\r
1226 if (base < firstTransitionTime || (!inclusive && base == firstTransitionTime)) {
\r
1229 Date stdDate = stdRule.getPreviousStart(base, dstRule.getRawOffset(),
\r
1230 dstRule.getDSTSavings(), inclusive);
\r
1231 Date dstDate = dstRule.getPreviousStart(base, stdRule.getRawOffset(),
\r
1232 stdRule.getDSTSavings(), inclusive);
\r
1233 if (stdDate != null && (dstDate == null || stdDate.after(dstDate))) {
\r
1234 return new TimeZoneTransition(stdDate.getTime(), dstRule, stdRule);
\r
1236 if (dstDate != null && (stdDate == null || dstDate.after(stdDate))) {
\r
1237 return new TimeZoneTransition(dstDate.getTime(), stdRule, dstRule);
\r
1246 public TimeZoneRule[] getTimeZoneRules() {
\r
1247 initTransitionRules();
\r
1249 int size = useDaylight ? 3 : 1;
\r
1250 TimeZoneRule[] rules = new TimeZoneRule[size];
\r
1251 rules[0] = initialRule;
\r
1252 if (useDaylight) {
\r
1253 rules[1] = stdRule;
\r
1254 rules[2] = dstRule;
\r
1259 private transient boolean transitionRulesInitialized;
\r
1260 private transient InitialTimeZoneRule initialRule;
\r
1261 private transient TimeZoneTransition firstTransition;
\r
1262 private transient AnnualTimeZoneRule stdRule;
\r
1263 private transient AnnualTimeZoneRule dstRule;
\r
1265 private synchronized void initTransitionRules() {
\r
1266 if (transitionRulesInitialized) {
\r
1269 if (useDaylight) {
\r
1270 DateTimeRule dtRule = null;
\r
1272 long firstStdStart, firstDstStart;
\r
1274 // Create a TimeZoneRule for daylight saving time
\r
1275 timeRuleType = (startTimeMode == STANDARD_TIME) ? DateTimeRule.STANDARD_TIME :
\r
1276 ((startTimeMode == UTC_TIME) ? DateTimeRule.UTC_TIME : DateTimeRule.WALL_TIME);
\r
1277 switch (startMode) {
\r
1279 dtRule = new DateTimeRule(startMonth, startDay, startTime, timeRuleType);
\r
1281 case DOW_IN_MONTH_MODE:
\r
1282 dtRule = new DateTimeRule(startMonth, startDay, startDayOfWeek, startTime,
\r
1285 case DOW_GE_DOM_MODE:
\r
1286 dtRule = new DateTimeRule(startMonth, startDay, startDayOfWeek, true, startTime,
\r
1289 case DOW_LE_DOM_MODE:
\r
1290 dtRule = new DateTimeRule(startMonth, startDay, startDayOfWeek, false, startTime,
\r
1294 // For now, use ID + "(DST)" as the name
\r
1295 dstRule = new AnnualTimeZoneRule(getID() + "(DST)", getRawOffset(), getDSTSavings(),
\r
1296 dtRule, startYear, AnnualTimeZoneRule.MAX_YEAR);
\r
1298 // Calculate the first DST start time
\r
1299 firstDstStart = dstRule.getFirstStart(getRawOffset(), 0).getTime();
\r
1301 // Create a TimeZoneRule for standard time
\r
1302 timeRuleType = (endTimeMode == STANDARD_TIME) ? DateTimeRule.STANDARD_TIME :
\r
1303 ((endTimeMode == UTC_TIME) ? DateTimeRule.UTC_TIME : DateTimeRule.WALL_TIME);
\r
1304 switch (endMode) {
\r
1306 dtRule = new DateTimeRule(endMonth, endDay, endTime, timeRuleType);
\r
1308 case DOW_IN_MONTH_MODE:
\r
1309 dtRule = new DateTimeRule(endMonth, endDay, endDayOfWeek, endTime, timeRuleType);
\r
1311 case DOW_GE_DOM_MODE:
\r
1312 dtRule = new DateTimeRule(endMonth, endDay, endDayOfWeek, true, endTime,
\r
1315 case DOW_LE_DOM_MODE:
\r
1316 dtRule = new DateTimeRule(endMonth, endDay, endDayOfWeek, false, endTime,
\r
1320 // For now, use ID + "(STD)" as the name
\r
1321 stdRule = new AnnualTimeZoneRule(getID() + "(STD)", getRawOffset(), 0,
\r
1322 dtRule, startYear, AnnualTimeZoneRule.MAX_YEAR);
\r
1324 // Calculate the first STD start time
\r
1325 firstStdStart = stdRule.getFirstStart(getRawOffset(), dstRule.getDSTSavings()).getTime();
\r
1327 // Create a TimeZoneRule for initial time
\r
1328 if (firstStdStart < firstDstStart) {
\r
1329 initialRule = new InitialTimeZoneRule(getID() + "(DST)", getRawOffset(),
\r
1330 dstRule.getDSTSavings());
\r
1331 firstTransition = new TimeZoneTransition(firstStdStart, initialRule, stdRule);
\r
1333 initialRule = new InitialTimeZoneRule(getID() + "(STD)", getRawOffset(), 0);
\r
1334 firstTransition = new TimeZoneTransition(firstDstStart, initialRule, dstRule);
\r
1338 // Create a TimeZoneRule for initial time
\r
1339 initialRule = new InitialTimeZoneRule(getID(), getRawOffset(), 0);
\r
1341 transitionRulesInitialized = true;
\r