2 * Copyright (C) 1996-2009, 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 * <code>SimpleTimeZone</code> is a concrete subclass of <code>TimeZone</code>
\r
15 * that represents a time zone for use with a Gregorian calendar. This
\r
16 * class does not handle historical changes.
\r
19 * Use a negative value for <code>dayOfWeekInMonth</code> to indicate that
\r
20 * <code>SimpleTimeZone</code> should count from the end of the month backwards.
\r
21 * For example, if Daylight Savings Time starts or ends at the last Sunday in a month,
\r
22 * use <code>dayOfWeekInMonth = -1</code> along with <code>dayOfWeek = Calendar.SUNDAY</code>
\r
23 * to specify the rule.
\r
26 * @see GregorianCalendar
\r
28 * @author David Goldsmith, Mark Davis, Chen-Lieh Huang, Alan Liu
\r
31 public class SimpleTimeZone extends BasicTimeZone {
\r
32 private static final long serialVersionUID = -7034676239311322769L;
\r
35 * Constant for a mode of start or end time specified as local wall time.
\r
38 public static final int WALL_TIME = 0;
\r
41 * Constant for a mode of start or end time specified as local standard time.
\r
44 public static final int STANDARD_TIME = 1;
\r
47 * Constant for a mode of start or end time specified as UTC.
\r
50 public static final int UTC_TIME = 2;
\r
53 * Constructs a SimpleTimeZone with the given base time zone offset from GMT
\r
54 * and time zone ID. Timezone IDs can be obtained from
\r
55 * TimeZone.getAvailableIDs. Normally you should use TimeZone.getDefault to
\r
56 * construct a TimeZone.
\r
58 * @param rawOffset The given base time zone offset to GMT.
\r
59 * @param ID The time zone ID which is obtained from
\r
60 * TimeZone.getAvailableIDs.
\r
63 public SimpleTimeZone(int rawOffset, String ID) {
\r
64 construct(rawOffset, 0, 0, 0,
\r
68 Grego.MILLIS_PER_HOUR);
\r
73 * Construct a SimpleTimeZone with the given base time zone offset from
\r
74 * GMT, time zone ID, time to start and end the daylight time. Timezone IDs
\r
75 * can be obtained from TimeZone.getAvailableIDs. Normally you should use
\r
76 * TimeZone.getDefault to create a TimeZone. For a time zone that does not
\r
77 * use daylight saving time, do not use this constructor; instead you should
\r
78 * use SimpleTimeZone(rawOffset, ID).
\r
80 * By default, this constructor specifies day-of-week-in-month rules. That
\r
81 * is, if the startDay is 1, and the startDayOfWeek is SUNDAY, then this
\r
82 * indicates the first Sunday in the startMonth. A startDay of -1 likewise
\r
83 * indicates the last Sunday. However, by using negative or zero values for
\r
84 * certain parameters, other types of rules can be specified.
\r
86 * Day of month. To specify an exact day of the month, such as March 1, set
\r
87 * startDayOfWeek to zero.
\r
89 * Day of week after day of month. To specify the first day of the week
\r
90 * occurring on or after an exact day of the month, make the day of the week
\r
91 * negative. For example, if startDay is 5 and startDayOfWeek is -MONDAY,
\r
92 * this indicates the first Monday on or after the 5th day of the
\r
95 * Day of week before day of month. To specify the last day of the week
\r
96 * occurring on or before an exact day of the month, make the day of the
\r
97 * week and the day of the month negative. For example, if startDay is -21
\r
98 * and startDayOfWeek is -WEDNESDAY, this indicates the last Wednesday on or
\r
99 * before the 21st of the startMonth.
\r
101 * The above examples refer to the startMonth, startDay, and startDayOfWeek;
\r
102 * the same applies for the endMonth, endDay, and endDayOfWeek.
\r
104 * @param rawOffset The given base time zone offset to GMT.
\r
105 * @param ID The time zone ID which is obtained from
\r
106 * TimeZone.getAvailableIDs.
\r
107 * @param startMonth The daylight savings starting month. Month is
\r
108 * 0-based. eg, 0 for January.
\r
109 * @param startDay The daylight savings starting
\r
110 * day-of-week-in-month. Please see the member
\r
111 * description for an example.
\r
112 * @param startDayOfWeek The daylight savings starting day-of-week. Please
\r
113 * see the member description for an example.
\r
114 * @param startTime The daylight savings starting time in local wall
\r
115 * time, which is standard time in this case. Please see the
\r
116 * member description for an example.
\r
117 * @param endMonth The daylight savings ending month. Month is
\r
118 * 0-based. eg, 0 for January.
\r
119 * @param endDay The daylight savings ending day-of-week-in-month.
\r
120 * Please see the member description for an example.
\r
121 * @param endDayOfWeek The daylight savings ending day-of-week. Please
\r
122 * see the member description for an example.
\r
123 * @param endTime The daylight savings ending time in local wall time,
\r
124 * which is daylight time in this case. Please see the
\r
125 * member description for an example.
\r
126 * @exception IllegalArgumentException the month, day, dayOfWeek, or time
\r
127 * parameters are out of range for the start or end rule
\r
130 public SimpleTimeZone(int rawOffset, String ID,
\r
131 int startMonth, int startDay, int startDayOfWeek, int startTime,
\r
132 int endMonth, int endDay, int endDayOfWeek, int endTime) {
\r
133 construct(rawOffset,
\r
134 startMonth, startDay, startDayOfWeek,
\r
135 startTime, WALL_TIME,
\r
136 endMonth, endDay, endDayOfWeek,
\r
137 endTime, WALL_TIME,
\r
138 Grego.MILLIS_PER_HOUR);
\r
143 * Construct a SimpleTimeZone with the given base time zone offset from
\r
144 * GMT, time zone ID, time and its mode to start and end the daylight time.
\r
145 * The mode specifies either {@link #WALL_TIME} or {@link #STANDARD_TIME}
\r
146 * or {@link #UTC_TIME}.
\r
148 * @param rawOffset The given base time zone offset to GMT.
\r
149 * @param ID The time zone ID which is obtained from
\r
150 * TimeZone.getAvailableIDs.
\r
151 * @param startMonth The daylight savings starting month. Month is
\r
152 * 0-based. eg, 0 for January.
\r
153 * @param startDay The daylight savings starting
\r
154 * day-of-week-in-month. Please see the member
\r
155 * description for an example.
\r
156 * @param startDayOfWeek The daylight savings starting day-of-week. Please
\r
157 * see the member description for an example.
\r
158 * @param startTime The daylight savings starting time in local wall
\r
159 * time, which is standard time in this case. Please see the
\r
160 * member description for an example.
\r
161 * @param startTimeMode The mode of the start time specified by startTime.
\r
162 * @param endMonth The daylight savings ending month. Month is
\r
163 * 0-based. eg, 0 for January.
\r
164 * @param endDay The daylight savings ending day-of-week-in-month.
\r
165 * Please see the member description for an example.
\r
166 * @param endDayOfWeek The daylight savings ending day-of-week. Please
\r
167 * see the member description for an example.
\r
168 * @param endTime The daylight savings ending time in local wall time,
\r
169 * which is daylight time in this case. Please see the
\r
170 * member description for an example.
\r
171 * @param endTimeMode The mode of the end time specified by endTime.
\r
172 * @param dstSavings The amount of time in ms saved during DST.
\r
173 * @exception IllegalArgumentException the month, day, dayOfWeek, or time
\r
174 * parameters are out of range for the start or end rule
\r
177 public SimpleTimeZone(int rawOffset, String ID,
\r
178 int startMonth, int startDay,
\r
179 int startDayOfWeek, int startTime,
\r
181 int endMonth, int endDay,
\r
182 int endDayOfWeek, int endTime,
\r
183 int endTimeMode,int dstSavings){
\r
184 construct(rawOffset,
\r
185 startMonth, startDay, startDayOfWeek,
\r
186 startTime, startTimeMode,
\r
187 endMonth, endDay, endDayOfWeek,
\r
188 endTime, endTimeMode,
\r
194 * Constructor. This constructor is identical to the 10-argument
\r
195 * constructor, but also takes a dstSavings parameter.
\r
196 * @param rawOffset The given base time zone offset to GMT.
\r
197 * @param ID The time zone ID which is obtained from
\r
198 * TimeZone.getAvailableIDs.
\r
199 * @param startMonth The daylight savings starting month. Month is
\r
200 * 0-based. eg, 0 for January.
\r
201 * @param startDay The daylight savings starting
\r
202 * day-of-week-in-month. Please see the member
\r
203 * description for an example.
\r
204 * @param startDayOfWeek The daylight savings starting day-of-week. Please
\r
205 * see the member description for an example.
\r
206 * @param startTime The daylight savings starting time in local wall
\r
207 * time, which is standard time in this case. Please see the
\r
208 * member description for an example.
\r
209 * @param endMonth The daylight savings ending month. Month is
\r
210 * 0-based. eg, 0 for January.
\r
211 * @param endDay The daylight savings ending day-of-week-in-month.
\r
212 * Please see the member description for an example.
\r
213 * @param endDayOfWeek The daylight savings ending day-of-week. Please
\r
214 * see the member description for an example.
\r
215 * @param endTime The daylight savings ending time in local wall time,
\r
216 * which is daylight time in this case. Please see the
\r
217 * member description for an example.
\r
218 * @param dstSavings The amount of time in ms saved during DST.
\r
219 * @exception IllegalArgumentException the month, day, dayOfWeek, or time
\r
220 * parameters are out of range for the start or end rule
\r
223 public SimpleTimeZone(int rawOffset, String ID,
\r
224 int startMonth, int startDay, int startDayOfWeek, int startTime,
\r
225 int endMonth, int endDay, int endDayOfWeek, int endTime,
\r
227 construct(rawOffset,
\r
228 startMonth, startDay, startDayOfWeek,
\r
229 startTime, WALL_TIME,
\r
230 endMonth, endDay, endDayOfWeek,
\r
231 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 * @exception 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
313 * Sets the daylight savings starting rule. For example, in the U.S., Daylight Savings
\r
314 * Time starts at the second Sunday in March, at 2 AM in standard time.
\r
315 * Therefore, you can set the start rule by calling:
\r
316 * setStartRule(Calendar.MARCH, 2, Calendar.SUNDAY, 2*60*60*1000);
\r
317 * The dayOfWeekInMonth and dayOfWeek parameters together specify how to calculate
\r
318 * the exact starting date. Their exact meaning depend on their respective signs,
\r
319 * allowing various types of rules to be constructed, as follows:<ul>
\r
320 * <li>If both dayOfWeekInMonth and dayOfWeek are positive, they specify the
\r
321 * day of week in the month (e.g., (2, WEDNESDAY) is the second Wednesday
\r
323 * <li>If dayOfWeek is positive and dayOfWeekInMonth is negative, they specify
\r
324 * the day of week in the month counting backward from the end of the month.
\r
325 * (e.g., (-1, MONDAY) is the last Monday in the month)
\r
326 * <li>If dayOfWeek is zero and dayOfWeekInMonth is positive, dayOfWeekInMonth
\r
327 * specifies the day of the month, regardless of what day of the week it is.
\r
328 * (e.g., (10, 0) is the tenth day of the month)
\r
329 * <li>If dayOfWeek is zero and dayOfWeekInMonth is negative, dayOfWeekInMonth
\r
330 * specifies the day of the month counting backward from the end of the
\r
331 * month, regardless of what day of the week it is (e.g., (-2, 0) is the
\r
332 * next-to-last day of the month).
\r
333 * <li>If dayOfWeek is negative and dayOfWeekInMonth is positive, they specify the
\r
334 * first specified day of the week on or after the specfied day of the month.
\r
335 * (e.g., (15, -SUNDAY) is the first Sunday after the 15th of the month
\r
336 * [or the 15th itself if the 15th is a Sunday].)
\r
337 * <li>If dayOfWeek and DayOfWeekInMonth are both negative, they specify the
\r
338 * last specified day of the week on or before the specified day of the month.
\r
339 * (e.g., (-20, -TUESDAY) is the last Tuesday before the 20th of the month
\r
340 * [or the 20th itself if the 20th is a Tuesday].)</ul>
\r
341 * @param month the daylight savings starting month. Month is 0-based.
\r
342 * eg, 0 for January.
\r
343 * @param dayOfWeekInMonth the daylight savings starting
\r
344 * day-of-week-in-month. Please see the member description for an example.
\r
345 * @param dayOfWeek the daylight savings starting day-of-week. Please see
\r
346 * the member description for an example.
\r
347 * @param time the daylight savings starting time. Please see the member
\r
348 * description for an example.
\r
351 private void setStartRule(int month, int dayOfWeekInMonth, int dayOfWeek, int time, int mode)
\r
353 startMonth = month;
\r
354 startDay = dayOfWeekInMonth;
\r
355 startDayOfWeek = dayOfWeek;
\r
357 startTimeMode = mode;
\r
360 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 * @exception 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 * @exception 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 * @exception 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 * @exception 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 * @exception 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
467 private void setEndRule(int month, int dayOfMonth, int dayOfWeek,
\r
468 int time, int mode, boolean after){
\r
469 setEndRule(month, after ? dayOfMonth : -dayOfMonth, -dayOfWeek, time, mode);
\r
472 * Sets the daylight savings ending rule. For example, in the U.S., Daylight
\r
473 * Savings Time ends at the first Sunday in November, at 2 AM in standard time.
\r
474 * Therefore, you can set the end rule by calling:
\r
475 * setEndRule(Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2*60*60*1000);
\r
476 * Various other types of rules can be specified by manipulating the dayOfWeek
\r
477 * and dayOfWeekInMonth parameters. For complete details, see the documentation
\r
478 * for setStartRule().
\r
479 * @param month the daylight savings ending month. Month is 0-based.
\r
480 * eg, 0 for January.
\r
481 * @param dayOfWeekInMonth the daylight savings ending
\r
482 * day-of-week-in-month. See setStartRule() for a complete explanation.
\r
483 * @param dayOfWeek the daylight savings ending day-of-week. See setStartRule()
\r
484 * for a complete explanation.
\r
485 * @param time the daylight savings ending time. Please see the member
\r
486 * description for an example.
\r
488 private void setEndRule(int month, int dayOfWeekInMonth, int dayOfWeek, int time, int mode){
\r
490 endDay = dayOfWeekInMonth;
\r
491 endDayOfWeek = dayOfWeek;
\r
493 endTimeMode = mode;
\r
496 transitionRulesInitialized = false;
\r
499 * Sets the amount of time in ms that the clock is advanced during DST.
\r
500 * @param millisSavedDuringDST the number of milliseconds the time is
\r
501 * advanced with respect to standard time when the daylight savings rules
\r
502 * are in effect. A positive number, typically one hour (3600000).
\r
505 public void setDSTSavings(int millisSavedDuringDST) {
\r
506 if (millisSavedDuringDST <= 0) {
\r
507 throw new IllegalArgumentException();
\r
509 dst = millisSavedDuringDST;
\r
511 transitionRulesInitialized = false;
\r
515 * Returns the amount of time in ms that the clock is advanced during DST.
\r
516 * @return the number of milliseconds the time is
\r
517 * advanced with respect to standard time when the daylight savings rules
\r
518 * are in effect. A positive number, typically one hour (3600000).
\r
521 public int getDSTSavings() {
\r
526 * Returns the java.util.SimpleTimeZone that this class wraps.
\r
528 java.util.SimpleTimeZone unwrapSTZ() {
\r
529 return (java.util.SimpleTimeZone) unwrap();
\r
532 // on JDK 1.4 and later, can't deserialize a SimpleTimeZone as a SimpleTimeZone...
\r
533 private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
\r
534 in.defaultReadObject();
\r
536 String id = getID();
\r
537 if (id!=null && !(zone instanceof java.util.SimpleTimeZone && zone.getID().equals(id))) {
\r
538 // System.out.println("*** readjust " + zone.getClass().getName() + " " + zone.getID() + " ***");
\r
539 java.util.SimpleTimeZone stz =
\r
540 new java.util.SimpleTimeZone(raw, id);
\r
542 stz.setDSTSavings(dst);
\r
543 // if it is 0, then there shouldn't be start/end rules and the default
\r
544 // behavior should be no dst
\r
547 if (xinfo != null) {
\r
548 xinfo.applyTo(stz);
\r
553 /* set all instance variables in this object
\r
554 * to the values in zone
\r
556 if (xinfo != null) {
\r
557 xinfo.applyTo(this);
\r
562 * Returns a string representation of this object.
\r
563 * @return a string representation of this object
\r
566 public String toString() {
\r
567 return "SimpleTimeZone: " + getID();
\r
570 private STZInfo getSTZInfo() {
\r
571 if (xinfo == null) {
\r
572 xinfo = new STZInfo();
\r
577 // Use only for decodeStartRule() and decodeEndRule() where the year is not
\r
578 // available. Set February to 29 days to accomodate rules with that date
\r
579 // and day-of-week-on-or-before-that-date mode (DOW_LE_DOM_MODE).
\r
580 // The compareToRule() method adjusts to February 28 in non-leap years.
\r
582 // For actual getOffset() calculations, use TimeZone::monthLength() and
\r
583 // TimeZone::previousMonthLength() which take leap years into account.
\r
584 // We handle leap years assuming always
\r
585 // Gregorian, since we know they didn't have daylight time when
\r
586 // Gregorian calendar started.
\r
587 private final static byte staticMonthLength[] = {31,29,31,30,31,30,31,31,30,31,30,31};
\r
593 public int getOffset(int era, int year, int month, int day,
\r
594 int dayOfWeek, int millis)
\r
596 // Check the month before calling Grego.monthLength(). This
\r
597 // duplicates the test that occurs in the 7-argument getOffset(),
\r
598 // however, this is unavoidable. We don't mind because this method, in
\r
599 // fact, should not be called; internal code should always call the
\r
600 // 7-argument getOffset(), and outside code should use Calendar.get(int
\r
601 // field) with fields ZONE_OFFSET and DST_OFFSET. We can't get rid of
\r
602 // this method because it's public API. - liu 8/10/98
\r
603 if(month < Calendar.JANUARY || month > Calendar.DECEMBER) {
\r
604 throw new IllegalArgumentException();
\r
607 return getOffset(era, year, month, day, dayOfWeek, millis, Grego.monthLength(year, month));
\r
612 * @deprecated This API is ICU internal only.
\r
614 public int getOffset(int era, int year, int month, int day,
\r
615 int dayOfWeek, int millis,
\r
617 // Check the month before calling Grego.monthLength(). This
\r
618 // duplicates a test that occurs in the 9-argument getOffset(),
\r
619 // however, this is unavoidable. We don't mind because this method, in
\r
620 // fact, should not be called; internal code should always call the
\r
621 // 9-argument getOffset(), and outside code should use Calendar.get(int
\r
622 // field) with fields ZONE_OFFSET and DST_OFFSET. We can't get rid of
\r
623 // this method because it's public API. - liu 8/10/98
\r
624 if(month < Calendar.JANUARY || month > Calendar.DECEMBER) {
\r
625 throw new IllegalArgumentException();
\r
628 return getOffset(era, year, month, day, dayOfWeek, millis,
\r
629 Grego.monthLength(year, month), Grego.previousMonthLength(year, month));
\r
632 int getOffset(int era, int year, int month, int day,
\r
633 int dayOfWeek, int millis,
\r
634 int monthLength, int prevMonthLength ){
\r
637 /* Use this parameter checking code for normal operation. Only one
\r
638 * of these two blocks should actually get compiled into the class
\r
640 if ((era != GregorianCalendar.AD && era != GregorianCalendar.BC)
\r
641 || month < Calendar.JANUARY
\r
642 || month > Calendar.DECEMBER
\r
644 || day > monthLength
\r
645 || dayOfWeek < Calendar.SUNDAY
\r
646 || dayOfWeek > Calendar.SATURDAY
\r
648 || millis >= Grego.MILLIS_PER_DAY
\r
649 || monthLength < 28
\r
650 || monthLength > 31
\r
651 || prevMonthLength < 28
\r
652 || prevMonthLength > 31) {
\r
653 throw new IllegalArgumentException();
\r
656 /* This parameter checking code is better for debugging, but
\r
657 * overkill for normal operation. Only one of these two blocks
\r
658 * should actually get compiled into the class file. */
\r
659 if (era != GregorianCalendar.AD && era != GregorianCalendar.BC) {
\r
660 throw new IllegalArgumentException("Illegal era " + era);
\r
662 if (month < Calendar.JANUARY
\r
663 || month > Calendar.DECEMBER) {
\r
664 throw new IllegalArgumentException("Illegal month " + month);
\r
667 || day > monthLength) {
\r
668 throw new IllegalArgumentException("Illegal day " + day+" max month len: "+monthLength);
\r
670 if (dayOfWeek < Calendar.SUNDAY
\r
671 || dayOfWeek > Calendar.SATURDAY) {
\r
672 throw new IllegalArgumentException("Illegal day of week " + dayOfWeek);
\r
675 || millis >= Grego.MILLIS_PER_DAY) {
\r
676 throw new IllegalArgumentException("Illegal millis " + millis);
\r
678 if (monthLength < 28
\r
679 || monthLength > 31) {
\r
680 throw new IllegalArgumentException("Illegal month length " + monthLength);
\r
682 if (prevMonthLength < 28
\r
683 || prevMonthLength > 31) {
\r
684 throw new IllegalArgumentException("Illegal previous month length " + prevMonthLength);
\r
690 // Bail out if we are before the onset of daylight savings time
\r
691 if (!useDaylight || year < startYear || era != GregorianCalendar.AD) return result;
\r
693 // Check for southern hemisphere. We assume that the start and end
\r
694 // month are different.
\r
695 boolean southern = (startMonth > endMonth);
\r
697 // Compare the date to the starting and ending rules.+1 = date>rule, -1
\r
698 // = date<rule, 0 = date==rule.
\r
699 int startCompare = compareToRule(month, monthLength, prevMonthLength,
\r
700 day, dayOfWeek, millis,
\r
701 startTimeMode == UTC_TIME ? -raw : 0,
\r
702 startMode, startMonth, startDayOfWeek,
\r
703 startDay, startTime);
\r
704 int endCompare = 0;
\r
706 /* We don't always have to compute endCompare. For many instances,
\r
707 * startCompare is enough to determine if we are in DST or not. In the
\r
708 * northern hemisphere, if we are before the start rule, we can't have
\r
709 * DST. In the southern hemisphere, if we are after the start rule, we
\r
710 * must have DST. This is reflected in the way the next if statement
\r
711 * (not the one immediately following) short circuits. */
\r
712 if (southern != (startCompare >= 0)) {
\r
713 /* For the ending rule comparison, we add the dstSavings to the millis
\r
714 * passed in to convert them from standard to wall time. We then must
\r
715 * normalize the millis to the range 0..millisPerDay-1. */
\r
716 endCompare = compareToRule(month, monthLength, prevMonthLength,
\r
717 day, dayOfWeek, millis,
\r
718 endTimeMode == WALL_TIME ? dst :
\r
719 (endTimeMode == UTC_TIME ? -raw : 0),
\r
720 endMode, endMonth, endDayOfWeek,
\r
724 // Check for both the northern and southern hemisphere cases. We
\r
725 // assume that in the northern hemisphere, the start rule is before the
\r
726 // end rule within the calendar year, and vice versa for the southern
\r
728 if ((!southern && (startCompare >= 0 && endCompare < 0)) ||
\r
729 (southern && (startCompare >= 0 || endCompare < 0)))
\r
738 * @deprecated This API is ICU internal only.
\r
740 public void getOffsetFromLocal(long date,
\r
741 int nonExistingTimeOpt, int duplicatedTimeOpt, int[] offsets) {
\r
742 offsets[0] = getRawOffset();
\r
743 int fields[] = new int[6];
\r
744 Grego.timeToFields(date, fields);
\r
745 offsets[1] = getOffset(GregorianCalendar.AD,
\r
746 fields[0], fields[1], fields[2],
\r
747 fields[3], fields[5]) - offsets[0];
\r
749 boolean recalc = false;
\r
751 // Now, we need some adjustment
\r
752 if (offsets[1] > 0) {
\r
753 if ((nonExistingTimeOpt & STD_DST_MASK) == LOCAL_STD
\r
754 || (nonExistingTimeOpt & STD_DST_MASK) != LOCAL_DST && (nonExistingTimeOpt & FORMER_LATTER_MASK) != LOCAL_LATTER) {
\r
755 date -= getDSTSavings();
\r
759 if ((duplicatedTimeOpt & STD_DST_MASK) == LOCAL_DST
\r
760 || (duplicatedTimeOpt & STD_DST_MASK) != LOCAL_STD && (duplicatedTimeOpt & FORMER_LATTER_MASK) == LOCAL_FORMER) {
\r
761 date -= getDSTSavings();
\r
767 Grego.timeToFields(date, fields);
\r
768 offsets[1] = getOffset(GregorianCalendar.AD,
\r
769 fields[0], fields[1], fields[2],
\r
770 fields[3], fields[5]) - offsets[0];
\r
774 private static final int
\r
776 DOW_IN_MONTH_MODE=2,
\r
781 * Compare a given date in the year to a rule. Return 1, 0, or -1, depending
\r
782 * on whether the date is after, equal to, or before the rule date. The
\r
783 * millis are compared directly against the ruleMillis, so any
\r
784 * standard-daylight adjustments must be handled by the caller.
\r
786 * @return 1 if the date is after the rule date, -1 if the date is before
\r
787 * the rule date, or 0 if the date is equal to the rule date.
\r
789 private int compareToRule(int month, int monthLen, int prevMonthLen,
\r
791 int dayOfWeek, int millis, int millisDelta,
\r
792 int ruleMode, int ruleMonth, int ruleDayOfWeek,
\r
793 int ruleDay, int ruleMillis)
\r
795 // Make adjustments for startTimeMode and endTimeMode
\r
797 millis += millisDelta;
\r
799 while (millis >= Grego.MILLIS_PER_DAY) {
\r
800 millis -= Grego.MILLIS_PER_DAY;
\r
802 dayOfWeek = 1 + (dayOfWeek % 7); // dayOfWeek is one-based
\r
803 if (dayOfMonth > monthLen) {
\r
805 /* When incrementing the month, it is desirable to overflow
\r
806 * from DECEMBER to DECEMBER+1, since we use the result to
\r
807 * compare against a real month. Wraparound of the value
\r
808 * leads to bug 4173604. */
\r
813 * For some reasons, Sun Java 6 on Solaris/Linux has a problem with
\r
814 * the while loop below (at least Java 6 up to build 1.6.0_02-b08).
\r
815 * It looks the JRE messes up the variable 'millis' while executing
\r
816 * the code in the while block. The problem is not reproduced with
\r
817 * JVM option -Xint, that is, it is likely a bug of the HotSpot
\r
818 * adaptive compiler. Moving 'millis += Grego.MILLIS_PER_DAY'
\r
819 * to the end of this while block seems to resolve the problem.
\r
820 * See ticket#5887 about the problem in detail.
\r
822 while (millis < 0) {
\r
823 //millis += Grego.MILLIS_PER_DAY;
\r
825 dayOfWeek = 1 + ((dayOfWeek+5) % 7); // dayOfWeek is one-based
\r
826 if (dayOfMonth < 1) {
\r
827 dayOfMonth = prevMonthLen;
\r
830 millis += Grego.MILLIS_PER_DAY;
\r
833 if (month < ruleMonth) return -1;
\r
834 else if (month > ruleMonth) return 1;
\r
836 int ruleDayOfMonth = 0;
\r
838 // Adjust the ruleDay to the monthLen, for non-leap year February 29 rule days.
\r
839 if (ruleDay > monthLen) {
\r
840 ruleDay = monthLen;
\r
846 ruleDayOfMonth = ruleDay;
\r
848 case DOW_IN_MONTH_MODE:
\r
849 // In this case ruleDay is the day-of-week-in-month
\r
851 ruleDayOfMonth = 1 + (ruleDay - 1) * 7 +
\r
852 (7 + ruleDayOfWeek - (dayOfWeek - dayOfMonth + 1)) % 7;
\r
853 else // Assume ruleDay < 0 here
\r
855 ruleDayOfMonth = monthLen + (ruleDay + 1) * 7 -
\r
856 (7 + (dayOfWeek + monthLen - dayOfMonth) - ruleDayOfWeek) % 7;
\r
859 case DOW_GE_DOM_MODE:
\r
860 ruleDayOfMonth = ruleDay +
\r
861 (49 + ruleDayOfWeek - ruleDay - dayOfWeek + dayOfMonth) % 7;
\r
863 case DOW_LE_DOM_MODE:
\r
864 ruleDayOfMonth = ruleDay -
\r
865 (49 - ruleDayOfWeek + ruleDay + dayOfWeek - dayOfMonth) % 7;
\r
866 // Note at this point ruleDayOfMonth may be <1, although it will
\r
867 // be >=1 for well-formed rules.
\r
871 if (dayOfMonth < ruleDayOfMonth) return -1;
\r
872 else if (dayOfMonth > ruleDayOfMonth) return 1;
\r
874 if (millis < ruleMillis){
\r
876 }else if (millis > ruleMillis){
\r
883 // data needed for streaming mutated SimpleTimeZones in JDK14
\r
884 private int raw;// the TimeZone's raw GMT offset
\r
885 private int dst = 3600000;
\r
886 private STZInfo xinfo = null;
\r
887 private int startMonth, startDay, startDayOfWeek; // the month, day, DOW, and time DST starts
\r
888 private int startTime;
\r
889 private int startTimeMode, endTimeMode; // Mode for startTime, endTime; see TimeMode
\r
890 private int endMonth, endDay, endDayOfWeek; // the month, day, DOW, and time DST ends
\r
891 private int endTime;
\r
892 private int startYear; // the year these DST rules took effect
\r
893 private boolean useDaylight; // flag indicating whether this TimeZone uses DST
\r
894 private int startMode, endMode; // flags indicating what kind of rules the DST rules are
\r
897 * Overrides TimeZone
\r
898 * Queries if this time zone uses Daylight Saving Time.
\r
901 public boolean useDaylightTime(){
\r
902 return useDaylight;
\r
906 * Overrides TimeZone
\r
907 * Queries if the give date is in Daylight Saving Time.
\r
910 public boolean inDaylightTime(Date date){
\r
911 GregorianCalendar gc = new GregorianCalendar(this);
\r
913 return gc.inDaylightTime();
\r
917 * Internal construction method.
\r
919 private void construct(int _raw,
\r
922 int _startDayOfWeek,
\r
924 int _startTimeMode,
\r
932 startMonth = _startMonth;
\r
933 startDay = _startDay;
\r
934 startDayOfWeek = _startDayOfWeek;
\r
935 startTime = _startTime;
\r
936 startTimeMode = _startTimeMode;
\r
937 endMonth = _endMonth;
\r
939 endDayOfWeek = _endDayOfWeek;
\r
940 endTime = _endTime;
\r
941 endTimeMode = _endTimeMode;
\r
944 startMode = DOM_MODE;
\r
945 endMode = DOM_MODE;
\r
950 throw new IllegalArgumentException();
\r
953 private void decodeRules(){
\r
959 * Decode the start rule and validate the parameters. The parameters are
\r
960 * expected to be in encoded form, which represents the various rule modes
\r
961 * by negating or zeroing certain values. Representation formats are:
\r
964 * DOW_IN_MONTH DOM DOW>=DOM DOW<=DOM no DST
\r
965 * ------------ ----- -------- -------- ----------
\r
966 * month 0..11 same same same don't care
\r
967 * day -5..5 1..31 1..31 -1..-31 0
\r
968 * dayOfWeek 1..7 0 -1..-7 -1..-7 don't care
\r
969 * time 0..ONEDAY same same same don't care
\r
971 * The range for month does not include UNDECIMBER since this class is
\r
972 * really specific to GregorianCalendar, which does not use that month.
\r
973 * The range for time includes ONEDAY (vs. ending at ONEDAY-1) because the
\r
974 * end rule is an exclusive limit point. That is, the range of times that
\r
975 * are in DST include those >= the start and < the end. For this reason,
\r
976 * it should be possible to specify an end of ONEDAY in order to include the
\r
977 * entire day. Although this is equivalent to time 0 of the following day,
\r
978 * it's not always possible to specify that, for example, on December 31.
\r
979 * While arguably the start range should still be 0..ONEDAY-1, we keep
\r
980 * the start and end ranges the same for consistency.
\r
982 private void decodeStartRule() {
\r
984 useDaylight = (boolean)((startDay != 0) && (endDay != 0) ? true : false );
\r
985 if (useDaylight && dst == 0) {
\r
986 dst = Grego.MILLIS_PER_DAY;
\r
988 if (startDay != 0) {
\r
989 if (startMonth < Calendar.JANUARY || startMonth > Calendar.DECEMBER) {
\r
990 throw new IllegalArgumentException();
\r
992 if (startTime < 0 || startTime > Grego.MILLIS_PER_DAY ||
\r
993 startTimeMode < WALL_TIME || startTimeMode > UTC_TIME) {
\r
994 throw new IllegalArgumentException();
\r
996 if (startDayOfWeek == 0) {
\r
997 startMode = DOM_MODE;
\r
999 if (startDayOfWeek > 0) {
\r
1000 startMode = DOW_IN_MONTH_MODE;
\r
1002 startDayOfWeek = (int)-startDayOfWeek;
\r
1003 if (startDay > 0) {
\r
1004 startMode = DOW_GE_DOM_MODE;
\r
1006 startDay = (int)-startDay;
\r
1007 startMode = DOW_LE_DOM_MODE;
\r
1010 if (startDayOfWeek > Calendar.SATURDAY) {
\r
1011 throw new IllegalArgumentException();
\r
1014 if (startMode == DOW_IN_MONTH_MODE) {
\r
1015 if (startDay < -5 || startDay > 5) {
\r
1016 throw new IllegalArgumentException();
\r
1018 } else if (startDay < 1 || startDay > staticMonthLength[startMonth]) {
\r
1019 throw new IllegalArgumentException();
\r
1025 * Decode the end rule and validate the parameters. This method is exactly
\r
1026 * analogous to decodeStartRule().
\r
1027 * @see #decodeStartRule
\r
1029 private void decodeEndRule() {
\r
1030 useDaylight = (boolean)((startDay != 0) && (endDay != 0) ? true : false);
\r
1031 if (useDaylight && dst == 0) {
\r
1032 dst = Grego.MILLIS_PER_DAY;
\r
1034 if (endDay != 0) {
\r
1035 if (endMonth < Calendar.JANUARY || endMonth > Calendar.DECEMBER) {
\r
1036 throw new IllegalArgumentException();
\r
1038 if (endTime < 0 || endTime > Grego.MILLIS_PER_DAY ||
\r
1039 endTimeMode < WALL_TIME || endTimeMode > UTC_TIME) {
\r
1040 throw new IllegalArgumentException();
\r
1042 if (endDayOfWeek == 0) {
\r
1043 endMode = DOM_MODE;
\r
1045 if (endDayOfWeek > 0) {
\r
1046 endMode = DOW_IN_MONTH_MODE;
\r
1048 endDayOfWeek = (int)-endDayOfWeek;
\r
1050 endMode = DOW_GE_DOM_MODE;
\r
1052 endDay = (int)-endDay;
\r
1053 endMode = DOW_LE_DOM_MODE;
\r
1056 if (endDayOfWeek > Calendar.SATURDAY) {
\r
1057 throw new IllegalArgumentException();
\r
1060 if (endMode == DOW_IN_MONTH_MODE) {
\r
1061 if (endDay < -5 || endDay > 5) {
\r
1062 throw new IllegalArgumentException();
\r
1064 } else if (endDay<1 || endDay > staticMonthLength[endMonth]) {
\r
1065 throw new IllegalArgumentException();
\r
1071 * Return true if obj is a SimpleTimeZone equivalent to this.
\r
1072 * @return true if obj is a SimpleTimeZone equivalent to this
\r
1075 public boolean equals(Object obj){
\r
1076 if (this == obj) return true;
\r
1077 if (obj == null || getClass() != obj.getClass()) return false;
\r
1078 SimpleTimeZone that = (SimpleTimeZone) obj;
\r
1079 return raw == that.raw &&
\r
1080 useDaylight == that.useDaylight &&
\r
1081 idEquals(getID(),that.getID()) &&
\r
1083 // Only check rules if using DST
\r
1084 || (dst == that.dst &&
\r
1085 startMode == that.startMode &&
\r
1086 startMonth == that.startMonth &&
\r
1087 startDay == that.startDay &&
\r
1088 startDayOfWeek == that.startDayOfWeek &&
\r
1089 startTime == that.startTime &&
\r
1090 startTimeMode == that.startTimeMode &&
\r
1091 endMode == that.endMode &&
\r
1092 endMonth == that.endMonth &&
\r
1093 endDay == that.endDay &&
\r
1094 endDayOfWeek == that.endDayOfWeek &&
\r
1095 endTime == that.endTime &&
\r
1096 endTimeMode == that.endTimeMode &&
\r
1097 startYear == that.startYear ));
\r
1100 private boolean idEquals(String id1, String id2){
\r
1101 if(id1==null && id2==null){
\r
1104 if(id1!=null && id2!=null){
\r
1105 return id1.equals(id2);
\r
1111 * Return the hash code.
\r
1112 * @return the hash code
\r
1115 public int hashCode(){
\r
1116 int ret = (int)( super.hashCode() +
\r
1118 (useDaylight?0:1));
\r
1120 ret += (int)(dst ^ (dst>>>10) +
\r
1121 startMode ^ (startMode>>>11) +
\r
1122 startMonth ^ (startMonth>>>12) +
\r
1123 startDay ^ (startDay>>>13) +
\r
1124 startDayOfWeek ^ (startDayOfWeek>>>14) +
\r
1125 startTime ^ (startTime>>>15) +
\r
1126 startTimeMode ^ (startTimeMode>>>16) +
\r
1127 endMode ^ (endMode>>>17) +
\r
1128 endMonth ^ (endMonth>>>18) +
\r
1129 endDay ^ (endDay>>>19) +
\r
1130 endDayOfWeek ^ (endDayOfWeek>>>20) +
\r
1131 endTime ^ (endTime>>>21) +
\r
1132 endTimeMode ^ (endTimeMode>>>22) +
\r
1133 startYear ^ (startYear>>>23));
\r
1139 * Return a clone of this time zone.
\r
1140 * @return a clone of this time zone
\r
1143 public Object clone() {
\r
1144 return super.clone();
\r
1148 * Return true if this zone has the same rules and offset as another zone.
\r
1149 * @param othr the TimeZone object to be compared with
\r
1150 * @return true if the given zone has the same rules and offset as this one
\r
1153 public boolean hasSameRules(TimeZone othr) {
\r
1154 if(!(othr instanceof SimpleTimeZone)){
\r
1157 SimpleTimeZone other = (SimpleTimeZone)othr;
\r
1158 return other != null &&
\r
1159 raw == other.raw &&
\r
1160 useDaylight == other.useDaylight &&
\r
1162 // Only check rules if using DST
\r
1163 || (dst == other.dst &&
\r
1164 startMode == other.startMode &&
\r
1165 startMonth == other.startMonth &&
\r
1166 startDay == other.startDay &&
\r
1167 startDayOfWeek == other.startDayOfWeek &&
\r
1168 startTime == other.startTime &&
\r
1169 startTimeMode == other.startTimeMode &&
\r
1170 endMode == other.endMode &&
\r
1171 endMonth == other.endMonth &&
\r
1172 endDay == other.endDay &&
\r
1173 endDayOfWeek == other.endDayOfWeek &&
\r
1174 endTime == other.endTime &&
\r
1175 endTimeMode == other.endTimeMode &&
\r
1176 startYear == other.startYear));
\r
1179 // BasicTimeZone methods
\r
1185 public TimeZoneTransition getNextTransition(long base, boolean inclusive) {
\r
1186 if (!useDaylight) {
\r
1190 initTransitionRules();
\r
1191 long firstTransitionTime = firstTransition.getTime();
\r
1192 if (base < firstTransitionTime || (inclusive && base == firstTransitionTime)) {
\r
1193 return firstTransition;
\r
1195 Date stdDate = stdRule.getNextStart(base, dstRule.getRawOffset(), dstRule.getDSTSavings(), inclusive);
\r
1196 Date dstDate = dstRule.getNextStart(base, stdRule.getRawOffset(), stdRule.getDSTSavings(), inclusive);
\r
1197 if (stdDate != null && (dstDate == null || stdDate.before(dstDate))) {
\r
1198 return new TimeZoneTransition(stdDate.getTime(), dstRule, stdRule);
\r
1200 if (dstDate != null && (stdDate == null || dstDate.before(stdDate))) {
\r
1201 return new TimeZoneTransition(dstDate.getTime(), stdRule, dstRule);
\r
1210 public TimeZoneTransition getPreviousTransition(long base, boolean inclusive) {
\r
1211 if (!useDaylight) {
\r
1215 initTransitionRules();
\r
1216 long firstTransitionTime = firstTransition.getTime();
\r
1217 if (base < firstTransitionTime || (!inclusive && base == firstTransitionTime)) {
\r
1220 Date stdDate = stdRule.getPreviousStart(base, dstRule.getRawOffset(), dstRule.getDSTSavings(), inclusive);
\r
1221 Date dstDate = dstRule.getPreviousStart(base, stdRule.getRawOffset(), stdRule.getDSTSavings(), inclusive);
\r
1222 if (stdDate != null && (dstDate == null || stdDate.after(dstDate))) {
\r
1223 return new TimeZoneTransition(stdDate.getTime(), dstRule, stdRule);
\r
1225 if (dstDate != null && (stdDate == null || dstDate.after(stdDate))) {
\r
1226 return new TimeZoneTransition(dstDate.getTime(), stdRule, dstRule);
\r
1235 public TimeZoneRule[] getTimeZoneRules() {
\r
1236 initTransitionRules();
\r
1238 int size = useDaylight ? 3 : 1;
\r
1239 TimeZoneRule[] rules = new TimeZoneRule[size];
\r
1240 rules[0] = initialRule;
\r
1241 if (useDaylight) {
\r
1242 rules[1] = stdRule;
\r
1243 rules[2] = dstRule;
\r
1248 private transient boolean transitionRulesInitialized;
\r
1249 private transient InitialTimeZoneRule initialRule;
\r
1250 private transient TimeZoneTransition firstTransition;
\r
1251 private transient AnnualTimeZoneRule stdRule;
\r
1252 private transient AnnualTimeZoneRule dstRule;
\r
1254 private synchronized void initTransitionRules() {
\r
1255 if (transitionRulesInitialized) {
\r
1258 if (useDaylight) {
\r
1259 DateTimeRule dtRule = null;
\r
1261 long firstStdStart, firstDstStart;
\r
1263 // Create a TimeZoneRule for daylight saving time
\r
1264 timeRuleType = (startTimeMode == STANDARD_TIME) ? DateTimeRule.STANDARD_TIME :
\r
1265 ((startTimeMode == UTC_TIME) ? DateTimeRule.UTC_TIME : DateTimeRule.WALL_TIME);
\r
1266 switch (startMode) {
\r
1268 dtRule = new DateTimeRule(startMonth, startDay, startTime, timeRuleType);
\r
1270 case DOW_IN_MONTH_MODE:
\r
1271 dtRule = new DateTimeRule(startMonth, startDay, startDayOfWeek, startTime, timeRuleType);
\r
1273 case DOW_GE_DOM_MODE:
\r
1274 dtRule = new DateTimeRule(startMonth, startDay, startDayOfWeek, true, startTime, timeRuleType);
\r
1276 case DOW_LE_DOM_MODE:
\r
1277 dtRule = new DateTimeRule(startMonth, startDay, startDayOfWeek, false, startTime, timeRuleType);
\r
1280 // For now, use ID + "(DST)" as the name
\r
1281 dstRule = new AnnualTimeZoneRule(getID() + "(DST)", getRawOffset(), getDSTSavings(),
\r
1282 dtRule, startYear, AnnualTimeZoneRule.MAX_YEAR);
\r
1284 // Calculate the first DST start time
\r
1285 firstDstStart = dstRule.getFirstStart(getRawOffset(), 0).getTime();
\r
1287 // Create a TimeZoneRule for standard time
\r
1288 timeRuleType = (endTimeMode == STANDARD_TIME) ? DateTimeRule.STANDARD_TIME :
\r
1289 ((endTimeMode == UTC_TIME) ? DateTimeRule.UTC_TIME : DateTimeRule.WALL_TIME);
\r
1290 switch (endMode) {
\r
1292 dtRule = new DateTimeRule(endMonth, endDay, endTime, timeRuleType);
\r
1294 case DOW_IN_MONTH_MODE:
\r
1295 dtRule = new DateTimeRule(endMonth, endDay, endDayOfWeek, endTime, timeRuleType);
\r
1297 case DOW_GE_DOM_MODE:
\r
1298 dtRule = new DateTimeRule(endMonth, endDay, endDayOfWeek, true, endTime, timeRuleType);
\r
1300 case DOW_LE_DOM_MODE:
\r
1301 dtRule = new DateTimeRule(endMonth, endDay, endDayOfWeek, false, endTime, timeRuleType);
\r
1304 // For now, use ID + "(STD)" as the name
\r
1305 stdRule = new AnnualTimeZoneRule(getID() + "(STD)", getRawOffset(), 0,
\r
1306 dtRule, startYear, AnnualTimeZoneRule.MAX_YEAR);
\r
1308 // Calculate the first STD start time
\r
1309 firstStdStart = stdRule.getFirstStart(getRawOffset(), dstRule.getDSTSavings()).getTime();
\r
1311 // Create a TimeZoneRule for initial time
\r
1312 if (firstStdStart < firstDstStart) {
\r
1313 initialRule = new InitialTimeZoneRule(getID() + "(DST)", getRawOffset(), dstRule.getDSTSavings());
\r
1314 firstTransition = new TimeZoneTransition(firstStdStart, initialRule, stdRule);
\r
1316 initialRule = new InitialTimeZoneRule(getID() + "(STD)", getRawOffset(), 0);
\r
1317 firstTransition = new TimeZoneTransition(firstDstStart, initialRule, dstRule);
\r
1321 // Create a TimeZoneRule for initial time
\r
1322 initialRule = new InitialTimeZoneRule(getID(), getRawOffset(), 0);
\r
1324 transitionRulesInitialized = true;
\r