17935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 27935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* Copyright (C) 1996-2014, International Business Machines 37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* Corporation and others. All Rights Reserved. 47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert*/ 57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.util; 77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.io.IOException; 97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Date; 107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.Grego; 127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/** 147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icuenhanced java.util.SimpleTimeZone}.{@icu _usage_} 157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p><code>SimpleTimeZone</code> is a concrete subclass of <code>TimeZone</code> 177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * that represents a time zone for use with a Gregorian calendar. This 187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * class does not handle historical changes. 197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Use a negative value for <code>dayOfWeekInMonth</code> to indicate that 217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>SimpleTimeZone</code> should count from the end of the month backwards. For 227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * example, if Daylight Savings Time starts or ends at the last Sunday in a month, use 237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>dayOfWeekInMonth = -1</code> along with <code>dayOfWeek = Calendar.SUNDAY</code> 247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * to specify the rule. 257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see Calendar 277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see GregorianCalendar 287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see TimeZone 297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @author David Goldsmith, Mark Davis, Chen-Lieh Huang, Alan Liu 307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpublic class SimpleTimeZone extends BasicTimeZone { 337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final long serialVersionUID = -7034676239311322769L; 347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Constant for a mode of start or end time specified as local wall time. 377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static final int WALL_TIME = 0; 407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Constant for a mode of start or end time specified as local standard time. 437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static final int STANDARD_TIME = 1; 467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Constant for a mode of start or end time specified as UTC. 497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static final int UTC_TIME = 2; 527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Constructs a SimpleTimeZone with the given base time zone offset from GMT 557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and time zone ID. Timezone IDs can be obtained from 567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * TimeZone.getAvailableIDs. Normally you should use TimeZone.getDefault to 577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * construct a TimeZone. 587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param rawOffset The given base time zone offset to GMT. 607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param ID The time zone ID which is obtained from 617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * TimeZone.getAvailableIDs. 627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public SimpleTimeZone(int rawOffset, String ID) { 657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert super(ID); 667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert construct(rawOffset, 0, 0, 0, 677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0, WALL_TIME, 687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0, 0, 0, 697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0, WALL_TIME, 707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Grego.MILLIS_PER_HOUR); 717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Constructs a SimpleTimeZone with the given base time zone offset from 757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * GMT, time zone ID, time to start and end the daylight time. Timezone IDs 767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * can be obtained from TimeZone.getAvailableIDs. Normally you should use 777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * TimeZone.getDefault to create a TimeZone. For a time zone that does not 787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * use daylight saving time, do not use this constructor; instead you should 797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * use SimpleTimeZone(rawOffset, ID). 807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * By default, this constructor specifies day-of-week-in-month rules. That 827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is, if the startDay is 1, and the startDayOfWeek is SUNDAY, then this 837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * indicates the first Sunday in the startMonth. A startDay of -1 likewise 847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * indicates the last Sunday. However, by using negative or zero values for 857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * certain parameters, other types of rules can be specified. 867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Day of month. To specify an exact day of the month, such as March 1, set 887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * startDayOfWeek to zero. 897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Day of week after day of month. To specify the first day of the week 917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * occurring on or after an exact day of the month, make the day of the week 927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * negative. For example, if startDay is 5 and startDayOfWeek is -MONDAY, 937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * this indicates the first Monday on or after the 5th day of the 947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * startMonth. 957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Day of week before day of month. To specify the last day of the week 977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * occurring on or before an exact day of the month, make the day of the 987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * week and the day of the month negative. For example, if startDay is -21 997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and startDayOfWeek is -WEDNESDAY, this indicates the last Wednesday on or 1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * before the 21st of the startMonth. 1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The above examples refer to the startMonth, startDay, and startDayOfWeek; 1037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the same applies for the endMonth, endDay, and endDayOfWeek. 1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param rawOffset The given base time zone offset to GMT. 1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param ID The time zone ID which is obtained from 1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * TimeZone.getAvailableIDs. 1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param startMonth The daylight savings starting month. Month is 1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 0-based. eg, 0 for January. 1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param startDay The daylight savings starting 1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * day-of-week-in-month. Please see the member 1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * description for an example. 1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param startDayOfWeek The daylight savings starting day-of-week. Please 1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * see the member description for an example. 1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param startTime The daylight savings starting time in local wall 1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * time, which is standard time in this case. Please see the 1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * member description for an example. 1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param endMonth The daylight savings ending month. Month is 1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 0-based. eg, 0 for January. 1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param endDay The daylight savings ending day-of-week-in-month. 1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Please see the member description for an example. 1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param endDayOfWeek The daylight savings ending day-of-week. Please 1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * see the member description for an example. 1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param endTime The daylight savings ending time in local wall time, 1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * which is daylight time in this case. Please see the 1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * member description for an example. 1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException the month, day, dayOfWeek, or time 1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * parameters are out of range for the start or end rule 1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public SimpleTimeZone(int rawOffset, String ID, 1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int startMonth, int startDay, int startDayOfWeek, int startTime, 1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int endMonth, int endDay, int endDayOfWeek, int endTime) { 1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert super(ID); 1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert construct(rawOffset, 1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startMonth, startDay, startDayOfWeek, 1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startTime, WALL_TIME, 1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endMonth, endDay, endDayOfWeek, 1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endTime, WALL_TIME, 1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Grego.MILLIS_PER_HOUR); 1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Constructs a SimpleTimeZone with the given base time zone offset from 1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * GMT, time zone ID, time and its mode to start and end the daylight time. 1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The mode specifies either {@link #WALL_TIME} or {@link #STANDARD_TIME} 1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * or {@link #UTC_TIME}. 1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param rawOffset The given base time zone offset to GMT. 1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param ID The time zone ID which is obtained from 1517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * TimeZone.getAvailableIDs. 1527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param startMonth The daylight savings starting month. Month is 1537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 0-based. eg, 0 for January. 1547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param startDay The daylight savings starting 1557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * day-of-week-in-month. Please see the member 1567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * description for an example. 1577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param startDayOfWeek The daylight savings starting day-of-week. Please 1587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * see the member description for an example. 1597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param startTime The daylight savings starting time in local wall 1607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * time, which is standard time in this case. Please see the 1617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * member description for an example. 1627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param startTimeMode The mode of the start time specified by startTime. 1637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param endMonth The daylight savings ending month. Month is 1647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 0-based. eg, 0 for January. 1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param endDay The daylight savings ending day-of-week-in-month. 1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Please see the member description for an example. 1677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param endDayOfWeek The daylight savings ending day-of-week. Please 1687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * see the member description for an example. 1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param endTime The daylight savings ending time in local wall time, 1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * which is daylight time in this case. Please see the 1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * member description for an example. 1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param endTimeMode The mode of the end time specified by endTime. 1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param dstSavings The amount of time in ms saved during DST. 1747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException the month, day, dayOfWeek, or time 1757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * parameters are out of range for the start or end rule 1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public SimpleTimeZone(int rawOffset, String ID, 1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int startMonth, int startDay, 1807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int startDayOfWeek, int startTime, 1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int startTimeMode, 1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int endMonth, int endDay, 1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int endDayOfWeek, int endTime, 1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int endTimeMode,int dstSavings){ 1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert super(ID); 1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert construct(rawOffset, 1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startMonth, startDay, startDayOfWeek, 1887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startTime, startTimeMode, 1897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endMonth, endDay, endDayOfWeek, 1907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endTime, endTimeMode, 1917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dstSavings); 1927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Constructor. This constructor is identical to the 10-argument 1967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * constructor, but also takes a dstSavings parameter. 1977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param rawOffset The given base time zone offset to GMT. 1987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param ID The time zone ID which is obtained from 1997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * TimeZone.getAvailableIDs. 2007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param startMonth The daylight savings starting month. Month is 2017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 0-based. eg, 0 for January. 2027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param startDay The daylight savings starting 2037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * day-of-week-in-month. Please see the member 2047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * description for an example. 2057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param startDayOfWeek The daylight savings starting day-of-week. Please 2067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * see the member description for an example. 2077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param startTime The daylight savings starting time in local wall 2087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * time, which is standard time in this case. Please see the 2097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * member description for an example. 2107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param endMonth The daylight savings ending month. Month is 2117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 0-based. eg, 0 for January. 2127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param endDay The daylight savings ending day-of-week-in-month. 2137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Please see the member description for an example. 2147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param endDayOfWeek The daylight savings ending day-of-week. Please 2157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * see the member description for an example. 2167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param endTime The daylight savings ending time in local wall time, 2177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * which is daylight time in this case. Please see the 2187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * member description for an example. 2197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param dstSavings The amount of time in ms saved during DST. 2207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException the month, day, dayOfWeek, or time 2217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * parameters are out of range for the start or end rule 2227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 2237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public SimpleTimeZone(int rawOffset, String ID, 2257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int startMonth, int startDay, int startDayOfWeek, int startTime, 2267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int endMonth, int endDay, int endDayOfWeek, int endTime, 2277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int dstSavings) { 2287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert super(ID); 2297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert construct(rawOffset, 2307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startMonth, startDay, startDayOfWeek, 2317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startTime, WALL_TIME, 2327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endMonth, endDay, endDayOfWeek, 2337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endTime, WALL_TIME, 2347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dstSavings); 2357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@inheritDoc} 2397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 2417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 2437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setID(String ID) { 2447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isFrozen()) { 2457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new UnsupportedOperationException("Attempt to modify a frozen SimpleTimeZone instance."); 2467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert super.setID(ID); 2487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert transitionRulesInitialized = false; 2497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Overrides TimeZone 2537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the base time zone offset to GMT. 2547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This is the offset to add "to" UTC to get local time. 2557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param offsetMillis the raw offset of the time zone 2567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 2577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 2597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setRawOffset(int offsetMillis) { 2607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isFrozen()) { 2617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new UnsupportedOperationException("Attempt to modify a frozen SimpleTimeZone instance."); 2627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert raw = offsetMillis; 2657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert transitionRulesInitialized = false; 2667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Overrides TimeZone 2707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Gets the GMT offset for this time zone. 2717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the raw offset 2727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 2737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 2757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int getRawOffset() { 2767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return raw; 2777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the daylight savings starting year. 2817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param year The daylight savings starting year. 2837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 2847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setStartYear(int year) { 2867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isFrozen()) { 2877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new UnsupportedOperationException("Attempt to modify a frozen SimpleTimeZone instance."); 2887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert getSTZInfo().sy = year; 2917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.startYear = year; 2927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert transitionRulesInitialized = false; 2937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the daylight savings starting rule. For example, Daylight Savings 2977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Time starts at the second Sunday in March, at 2 AM in standard time. 2987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Therefore, you can set the start rule by calling: 2997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * setStartRule(Calendar.MARCH, 2, Calendar.SUNDAY, 2*60*60*1000); 3007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param month The daylight savings starting month. Month is 3027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 0-based. eg, 0 for January. 3037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param dayOfWeekInMonth The daylight savings starting 3047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * day-of-week-in-month. Please see the member 3057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * description for an example. 3067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param dayOfWeek The daylight savings starting day-of-week. 3077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Please see the member description for an 3087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * example. 3097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param time The daylight savings starting time in local wall 3107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * time, which is standard time in this case. Please see 3117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the member description for an example. 3127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException the month, dayOfWeekInMonth, 3137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * dayOfWeek, or time parameters are out of range 3147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 3157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setStartRule(int month, int dayOfWeekInMonth, int dayOfWeek, 3177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int time) { 3187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isFrozen()) { 3197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new UnsupportedOperationException("Attempt to modify a frozen SimpleTimeZone instance."); 3207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert getSTZInfo().setStart(month, dayOfWeekInMonth, dayOfWeek, time, -1, false); 3237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setStartRule(month, dayOfWeekInMonth, dayOfWeek, time, WALL_TIME); 3247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 3277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the daylight savings starting rule. For example, in the U.S., Daylight Savings 3287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Time starts at the second Sunday in March, at 2 AM in standard time. 3297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Therefore, you can set the start rule by calling: 3307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>setStartRule(Calendar.MARCH, 2, Calendar.SUNDAY, 2*60*60*1000);</code> 3317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The dayOfWeekInMonth and dayOfWeek parameters together specify how to calculate 3327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the exact starting date. Their exact meaning depend on their respective signs, 3337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * allowing various types of rules to be constructed, as follows:<ul> 3347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>If both dayOfWeekInMonth and dayOfWeek are positive, they specify the 3357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * day of week in the month (e.g., (2, WEDNESDAY) is the second Wednesday 3367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * of the month). 3377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>If dayOfWeek is positive and dayOfWeekInMonth is negative, they specify 3387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the day of week in the month counting backward from the end of the month. 3397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * (e.g., (-1, MONDAY) is the last Monday in the month) 3407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>If dayOfWeek is zero and dayOfWeekInMonth is positive, dayOfWeekInMonth 3417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * specifies the day of the month, regardless of what day of the week it is. 3427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * (e.g., (10, 0) is the tenth day of the month) 3437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>If dayOfWeek is zero and dayOfWeekInMonth is negative, dayOfWeekInMonth 3447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * specifies the day of the month counting backward from the end of the 3457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * month, regardless of what day of the week it is (e.g., (-2, 0) is the 3467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * next-to-last day of the month). 3477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>If dayOfWeek is negative and dayOfWeekInMonth is positive, they specify the 3487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * first specified day of the week on or after the specfied day of the month. 3497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * (e.g., (15, -SUNDAY) is the first Sunday after the 15th of the month 3507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * [or the 15th itself if the 15th is a Sunday].) 3517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>If dayOfWeek and DayOfWeekInMonth are both negative, they specify the 3527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * last specified day of the week on or before the specified day of the month. 3537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * (e.g., (-20, -TUESDAY) is the last Tuesday before the 20th of the month 3547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * [or the 20th itself if the 20th is a Tuesday].)</ul> 3557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param month the daylight savings starting month. Month is 0-based. 3567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * eg, 0 for January. 3577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param dayOfWeekInMonth the daylight savings starting 3587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * day-of-week-in-month. Please see the member description for an example. 3597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param dayOfWeek the daylight savings starting day-of-week. Please see 3607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the member description for an example. 3617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param time the daylight savings starting time. Please see the member 3627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * description for an example. 3637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void setStartRule(int month, int dayOfWeekInMonth, int dayOfWeek, int time, int mode) { 3657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assert (!isFrozen()); 3667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startMonth = month; 3687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startDay = dayOfWeekInMonth; 3697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startDayOfWeek = dayOfWeek; 3707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startTime = time; 3717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startTimeMode = mode; 3727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert decodeStartRule(); 3737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert transitionRulesInitialized = false; 3757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 3787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the DST start rule to a fixed date within a month. 3797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param month The month in which this rule occurs (0-based). 3817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param dayOfMonth The date in that month (1-based). 3827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param time The time of that day (number of millis after midnight) 3837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * when DST takes effect in local wall time, which is 3847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * standard time in this case. 3857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException the month, 3867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * dayOfMonth, or time parameters are out of range 3877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 3887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setStartRule(int month, int dayOfMonth, int time) { 3907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isFrozen()) { 3917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new UnsupportedOperationException("Attempt to modify a frozen SimpleTimeZone instance."); 3927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert getSTZInfo().setStart(month, -1, -1, time, dayOfMonth, false); 3957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setStartRule(month, dayOfMonth, 0, time, WALL_TIME); 3967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 3997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the DST start rule to a weekday before or after a give date within 4007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * a month, e.g., the first Monday on or after the 8th. 4017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param month The month in which this rule occurs (0-based). 4037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param dayOfMonth A date within that month (1-based). 4047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param dayOfWeek The day of the week on which this rule occurs. 4057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param time The time of that day (number of millis after midnight) 4067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * when DST takes effect in local wall time, which is 4077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * standard time in this case. 4087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param after If true, this rule selects the first dayOfWeek on 4097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * or after dayOfMonth. If false, this rule selects 4107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the last dayOfWeek on or before dayOfMonth. 4117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException the month, dayOfMonth, 4127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * dayOfWeek, or time parameters are out of range 4137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 4147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 4157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setStartRule(int month, int dayOfMonth, int dayOfWeek, int time, boolean after) { 4167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isFrozen()) { 4177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new UnsupportedOperationException("Attempt to modify a frozen SimpleTimeZone instance."); 4187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert getSTZInfo().setStart(month, -1, dayOfWeek, time, dayOfMonth, after); 4217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setStartRule(month, after ? dayOfMonth : -dayOfMonth, 4227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert -dayOfWeek, time, WALL_TIME); 4237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 4267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the daylight savings ending rule. For example, if Daylight Savings Time 4277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * ends at the last (-1) Sunday in October, at 2 AM in standard time, 4287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * you can set the end rule by calling: 4297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*60*60*1000);</code> 4307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param month The daylight savings ending month. Month is 4327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 0-based. eg, 0 for January. 4337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param dayOfWeekInMonth The daylight savings ending 4347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * day-of-week-in-month. Please see the member 4357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * description for an example. 4367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param dayOfWeek The daylight savings ending day-of-week. Please 4377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * see the member description for an example. 4387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param time The daylight savings ending time in local wall time, 4397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * which is daylight time in this case. Please see the 4407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * member description for an example. 4417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException the month, dayOfWeekInMonth, 4427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * dayOfWeek, or time parameters are out of range 4437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 4447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 4457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setEndRule(int month, int dayOfWeekInMonth, int dayOfWeek, int time) { 4467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isFrozen()) { 4477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new UnsupportedOperationException("Attempt to modify a frozen SimpleTimeZone instance."); 4487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert getSTZInfo().setEnd(month, dayOfWeekInMonth, dayOfWeek, time, -1, false); 4517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setEndRule(month, dayOfWeekInMonth, dayOfWeek, time, WALL_TIME); 4527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 4557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the DST end rule to a fixed date within a month. 4567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param month The month in which this rule occurs (0-based). 4587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param dayOfMonth The date in that month (1-based). 4597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param time The time of that day (number of millis after midnight) 4607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * when DST ends in local wall time, which is daylight 4617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * time in this case. 4627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException the month, 4637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * dayOfMonth, or time parameters are out of range 4647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 4657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 4667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setEndRule(int month, int dayOfMonth, int time) { 4677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isFrozen()) { 4687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new UnsupportedOperationException("Attempt to modify a frozen SimpleTimeZone instance."); 4697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert getSTZInfo().setEnd(month, -1, -1, time, dayOfMonth, false); 4727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setEndRule(month, dayOfMonth, WALL_TIME, time); 4737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 4767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the DST end rule to a weekday before or after a give date within 4777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * a month, e.g., the first Monday on or after the 8th. 4787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param month The month in which this rule occurs (0-based). 4807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param dayOfMonth A date within that month (1-based). 4817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param dayOfWeek The day of the week on which this rule occurs. 4827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param time The time of that day (number of millis after midnight) 4837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * when DST ends in local wall time, which is daylight 4847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * time in this case. 4857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param after If true, this rule selects the first dayOfWeek on 4867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * or after dayOfMonth. If false, this rule selects 4877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the last dayOfWeek on or before dayOfMonth. 4887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException the month, dayOfMonth, 4897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * dayOfWeek, or time parameters are out of range 4907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 4917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 4927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setEndRule(int month, int dayOfMonth, int dayOfWeek, int time, boolean after) { 4937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isFrozen()) { 4947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new UnsupportedOperationException("Attempt to modify a frozen SimpleTimeZone instance."); 4957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert getSTZInfo().setEnd(month, -1, dayOfWeek, time, dayOfMonth, after); 4987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setEndRule(month, dayOfMonth, dayOfWeek, time, WALL_TIME, after); 4997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void setEndRule(int month, int dayOfMonth, int dayOfWeek, 5027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int time, int mode, boolean after){ 5037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assert (!isFrozen()); 5047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setEndRule(month, after ? dayOfMonth : -dayOfMonth, -dayOfWeek, time, mode); 5057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 5087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the daylight savings ending rule. For example, in the U.S., Daylight 5097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Savings Time ends at the first Sunday in November, at 2 AM in standard time. 5107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Therefore, you can set the end rule by calling: 5117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * setEndRule(Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2*60*60*1000); 5127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Various other types of rules can be specified by manipulating the dayOfWeek 5137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and dayOfWeekInMonth parameters. For complete details, see the documentation 5147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * for setStartRule(). 5157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param month the daylight savings ending month. Month is 0-based. 5167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * eg, 0 for January. 5177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param dayOfWeekInMonth the daylight savings ending 5187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * day-of-week-in-month. See setStartRule() for a complete explanation. 5197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param dayOfWeek the daylight savings ending day-of-week. See setStartRule() 5207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * for a complete explanation. 5217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param time the daylight savings ending time. Please see the member 5227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * description for an example. 5237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 5247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void setEndRule(int month, int dayOfWeekInMonth, int dayOfWeek, int time, int mode){ 5257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assert (!isFrozen()); 5267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endMonth = month; 5287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endDay = dayOfWeekInMonth; 5297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endDayOfWeek = dayOfWeek; 5307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endTime = time; 5317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endTimeMode = mode; 5327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert decodeEndRule(); 5337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert transitionRulesInitialized = false; 5357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 5387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the amount of time in ms that the clock is advanced during DST. 5397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param millisSavedDuringDST the number of milliseconds the time is 5407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * advanced with respect to standard time when the daylight savings rules 5417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * are in effect. A positive number, typically one hour (3600000). 5427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 5437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 5447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setDSTSavings(int millisSavedDuringDST) { 5457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isFrozen()) { 5467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new UnsupportedOperationException("Attempt to modify a frozen SimpleTimeZone instance."); 5477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (millisSavedDuringDST <= 0) { 5507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException(); 5517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dst = millisSavedDuringDST; 5537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert transitionRulesInitialized = false; 5557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 5587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns the amount of time in ms that the clock is advanced during DST. 5597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the number of milliseconds the time is 5607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * advanced with respect to standard time when the daylight savings rules 5617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * are in effect. A positive number, typically one hour (3600000). 5627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 5637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 5647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 5657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int getDSTSavings() { 5667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return dst; 5677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 5707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns the java.util.SimpleTimeZone that this class wraps. 5717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert java.util.SimpleTimeZone unwrapSTZ() { 5737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return (java.util.SimpleTimeZone) unwrap(); 5747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 5767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // on JDK 1.4 and later, can't deserialize a SimpleTimeZone as a SimpleTimeZone... 5787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void readObject(java.io.ObjectInputStream in) throws IOException, 5797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ClassNotFoundException { 5807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert in.defaultReadObject(); 5817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 5827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String id = getID(); 5837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (id!=null && !(zone instanceof java.util.SimpleTimeZone && zone.getID().equals(id))) { 5847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // System.out.println("*** readjust " + zone.getClass().getName() + 5857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // " " + zone.getID() + " ***"); 5867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert java.util.SimpleTimeZone stz = 5877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert new java.util.SimpleTimeZone(raw, id); 5887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (dst != 0) { 5897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert stz.setDSTSavings(dst); 5907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // if it is 0, then there shouldn't be start/end rules and the default 5917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // behavior should be no dst 5927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (xinfo != null) { 5957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert xinfo.applyTo(stz); 5967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert zoneJDK = stz; 5987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 6007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* set all instance variables in this object 6017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * to the values in zone 6027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 6037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (xinfo != null) { 6047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert xinfo.applyTo(this); 6057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 6097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns a string representation of this object. 6107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return a string representation of this object 6117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.6 6127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 6137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 6147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String toString() { 6157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return "SimpleTimeZone: " + getID(); 6167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private STZInfo getSTZInfo() { 6197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (xinfo == null) { 6207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert xinfo = new STZInfo(); 6217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return xinfo; 6237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Use only for decodeStartRule() and decodeEndRule() where the year is not 6267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // available. Set February to 29 days to accomodate rules with that date 6277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // and day-of-week-on-or-before-that-date mode (DOW_LE_DOM_MODE). 6287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // The compareToRule() method adjusts to February 28 in non-leap years. 6297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 6307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // For actual getOffset() calculations, use TimeZone::monthLength() and 6317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // TimeZone::previousMonthLength() which take leap years into account. 6327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We handle leap years assuming always 6337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Gregorian, since we know they didn't have daylight time when 6347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Gregorian calendar started. 6357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private final static byte staticMonthLength[] = {31,29,31,30,31,30,31,31,30,31,30,31}; 6367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 6387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@inheritDoc} 6397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 6407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 6417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 6427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int getOffset(int era, int year, int month, int day, 6437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int dayOfWeek, int millis) 6447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 6457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Check the month before calling Grego.monthLength(). This 6467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // duplicates the test that occurs in the 7-argument getOffset(), 6477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // however, this is unavoidable. We don't mind because this method, in 6487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // fact, should not be called; internal code should always call the 6497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 7-argument getOffset(), and outside code should use Calendar.get(int 6507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // field) with fields ZONE_OFFSET and DST_OFFSET. We can't get rid of 6517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // this method because it's public API. - liu 8/10/98 6527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(month < Calendar.JANUARY || month > Calendar.DECEMBER) { 6537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException(); 6547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return getOffset(era, year, month, day, dayOfWeek, millis, Grego.monthLength(year, month)); 6577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 6607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @internal 6617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @deprecated This API is ICU internal only. 6627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 6637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Deprecated 6647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int getOffset(int era, int year, int month, int day, 6657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int dayOfWeek, int millis, 6667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int monthLength) { 6677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Check the month before calling Grego.monthLength(). This 6687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // duplicates a test that occurs in the 9-argument getOffset(), 6697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // however, this is unavoidable. We don't mind because this method, in 6707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // fact, should not be called; internal code should always call the 6717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 9-argument getOffset(), and outside code should use Calendar.get(int 6727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // field) with fields ZONE_OFFSET and DST_OFFSET. We can't get rid of 6737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // this method because it's public API. - liu 8/10/98 6747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(month < Calendar.JANUARY || month > Calendar.DECEMBER) { 6757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException(); 6767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return getOffset(era, year, month, day, dayOfWeek, millis, 6797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Grego.monthLength(year, month), Grego.previousMonthLength(year, month)); 6807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int getOffset(int era, int year, int month, int day, 6837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int dayOfWeek, int millis, 6847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int monthLength, int prevMonthLength ){ 6857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (true) { 6877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* Use this parameter checking code for normal operation. Only one 6887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * of these two blocks should actually get compiled into the class 6897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * file. */ 6907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ((era != GregorianCalendar.AD && era != GregorianCalendar.BC) 6917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || month < Calendar.JANUARY 6927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || month > Calendar.DECEMBER 6937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || day < 1 6947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || day > monthLength 6957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || dayOfWeek < Calendar.SUNDAY 6967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || dayOfWeek > Calendar.SATURDAY 6977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || millis < 0 6987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || millis >= Grego.MILLIS_PER_DAY 6997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || monthLength < 28 7007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || monthLength > 31 7017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || prevMonthLength < 28 7027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || prevMonthLength > 31) { 7037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException(); 7047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert //Eclipse stated the following is "dead code" 7077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*else { 7087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // This parameter checking code is better for debugging, but 7097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // overkill for normal operation. Only one of these two blocks 7107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // should actually get compiled into the class file. 7117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (era != GregorianCalendar.AD && era != GregorianCalendar.BC) { 7127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Illegal era " + era); 7137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (month < Calendar.JANUARY 7157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || month > Calendar.DECEMBER) { 7167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Illegal month " + month); 7177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (day < 1 7197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || day > monthLength) { 7207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Illegal day " + day+" max month len: "+monthLength); 7217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (dayOfWeek < Calendar.SUNDAY 7237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || dayOfWeek > Calendar.SATURDAY) { 7247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Illegal day of week " + dayOfWeek); 7257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (millis < 0 7277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || millis >= Grego.MILLIS_PER_DAY) { 7287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Illegal millis " + millis); 7297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (monthLength < 28 7317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || monthLength > 31) { 7327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Illegal month length " + monthLength); 7337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (prevMonthLength < 28 7357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || prevMonthLength > 31) { 7367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Illegal previous month length " + prevMonthLength); 7377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }*/ 7397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int result = raw; 7417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Bail out if we are before the onset of daylight savings time 7437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!useDaylight || year < startYear || era != GregorianCalendar.AD) return result; 7447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Check for southern hemisphere. We assume that the start and end 7467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // month are different. 7477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean southern = (startMonth > endMonth); 7487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Compare the date to the starting and ending rules.+1 = date>rule, -1 7507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // = date<rule, 0 = date==rule. 7517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int startCompare = compareToRule(month, monthLength, prevMonthLength, 7527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert day, dayOfWeek, millis, 7537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startTimeMode == UTC_TIME ? -raw : 0, 7547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startMode, startMonth, startDayOfWeek, 7557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startDay, startTime); 7567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int endCompare = 0; 7577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* We don't always have to compute endCompare. For many instances, 7597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * startCompare is enough to determine if we are in DST or not. In the 7607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * northern hemisphere, if we are before the start rule, we can't have 7617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DST. In the southern hemisphere, if we are after the start rule, we 7627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * must have DST. This is reflected in the way the next if statement 7637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * (not the one immediately following) short circuits. */ 7647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (southern != (startCompare >= 0)) { 7657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* For the ending rule comparison, we add the dstSavings to the millis 7667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * passed in to convert them from standard to wall time. We then must 7677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * normalize the millis to the range 0..millisPerDay-1. */ 7687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endCompare = compareToRule(month, monthLength, prevMonthLength, 7697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert day, dayOfWeek, millis, 7707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endTimeMode == WALL_TIME ? dst : 7717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (endTimeMode == UTC_TIME ? -raw : 0), 7727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endMode, endMonth, endDayOfWeek, 7737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endDay, endTime); 7747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Check for both the northern and southern hemisphere cases. We 7777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // assume that in the northern hemisphere, the start rule is before the 7787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // end rule within the calendar year, and vice versa for the southern 7797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // hemisphere. 7807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ((!southern && (startCompare >= 0 && endCompare < 0)) || 7817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (southern && (startCompare >= 0 || endCompare < 0))) 7827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result += dst; 7837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return result; 7857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 7887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@inheritDoc} 7897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @internal 7907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @deprecated This API is ICU internal only. 7917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 7927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Deprecated 7937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void getOffsetFromLocal(long date, 7947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int nonExistingTimeOpt, int duplicatedTimeOpt, int[] offsets) { 7957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert offsets[0] = getRawOffset(); 7967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int fields[] = new int[6]; 7977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Grego.timeToFields(date, fields); 7987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert offsets[1] = getOffset(GregorianCalendar.AD, 7997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fields[0], fields[1], fields[2], 8007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fields[3], fields[5]) - offsets[0]; 8017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean recalc = false; 8037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Now, we need some adjustment 8057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (offsets[1] > 0) { 8067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ((nonExistingTimeOpt & STD_DST_MASK) == LOCAL_STD 8077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || (nonExistingTimeOpt & STD_DST_MASK) != LOCAL_DST 8087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && (nonExistingTimeOpt & FORMER_LATTER_MASK) != LOCAL_LATTER) { 8097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert date -= getDSTSavings(); 8107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert recalc = true; 8117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 8137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ((duplicatedTimeOpt & STD_DST_MASK) == LOCAL_DST 8147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || (duplicatedTimeOpt & STD_DST_MASK) != LOCAL_STD 8157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && (duplicatedTimeOpt & FORMER_LATTER_MASK) == LOCAL_FORMER) { 8167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert date -= getDSTSavings(); 8177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert recalc = true; 8187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (recalc) { 8227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Grego.timeToFields(date, fields); 8237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert offsets[1] = getOffset(GregorianCalendar.AD, 8247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fields[0], fields[1], fields[2], 8257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fields[3], fields[5]) - offsets[0]; 8267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final int 8307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DOM_MODE = 1, 8317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DOW_IN_MONTH_MODE=2, 8327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DOW_GE_DOM_MODE=3, 8337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DOW_LE_DOM_MODE=4; 8347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 8367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Compare a given date in the year to a rule. Return 1, 0, or -1, depending 8377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * on whether the date is after, equal to, or before the rule date. The 8387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * millis are compared directly against the ruleMillis, so any 8397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * standard-daylight adjustments must be handled by the caller. 8407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 8417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return 1 if the date is after the rule date, -1 if the date is before 8427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the rule date, or 0 if the date is equal to the rule date. 8437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 8447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int compareToRule(int month, int monthLen, int prevMonthLen, 8457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int dayOfMonth, 8467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int dayOfWeek, int millis, int millisDelta, 8477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int ruleMode, int ruleMonth, int ruleDayOfWeek, 8487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int ruleDay, int ruleMillis) 8497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 8507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Make adjustments for startTimeMode and endTimeMode 8517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert millis += millisDelta; 8537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (millis >= Grego.MILLIS_PER_DAY) { 8557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert millis -= Grego.MILLIS_PER_DAY; 8567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++dayOfMonth; 8577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dayOfWeek = 1 + (dayOfWeek % 7); // dayOfWeek is one-based 8587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (dayOfMonth > monthLen) { 8597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dayOfMonth = 1; 8607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* When incrementing the month, it is desirable to overflow 8617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * from DECEMBER to DECEMBER+1, since we use the result to 8627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * compare against a real month. Wraparound of the value 8637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * leads to bug 4173604. */ 8647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++month; 8657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 8687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For some reasons, Sun Java 6 on Solaris/Linux has a problem with 8697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the while loop below (at least Java 6 up to build 1.6.0_02-b08). 8707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * It looks the JRE messes up the variable 'millis' while executing 8717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the code in the while block. The problem is not reproduced with 8727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * JVM option -Xint, that is, it is likely a bug of the HotSpot 8737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * adaptive compiler. Moving 'millis += Grego.MILLIS_PER_DAY' 8747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * to the end of this while block seems to resolve the problem. 8757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * See ticket#5887 about the problem in detail. 8767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 8777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (millis < 0) { 8787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert //millis += Grego.MILLIS_PER_DAY; 8797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert --dayOfMonth; 8807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dayOfWeek = 1 + ((dayOfWeek+5) % 7); // dayOfWeek is one-based 8817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (dayOfMonth < 1) { 8827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dayOfMonth = prevMonthLen; 8837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert --month; 8847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert millis += Grego.MILLIS_PER_DAY; 8867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (month < ruleMonth) return -1; 8897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert else if (month > ruleMonth) return 1; 8907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int ruleDayOfMonth = 0; 8927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Adjust the ruleDay to the monthLen, for non-leap year February 29 rule days. 8947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ruleDay > monthLen) { 8957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ruleDay = monthLen; 8967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert switch (ruleMode) 8997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 9007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case DOM_MODE: 9017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ruleDayOfMonth = ruleDay; 9027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 9037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case DOW_IN_MONTH_MODE: 9047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // In this case ruleDay is the day-of-week-in-month 9057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ruleDay > 0) 9067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ruleDayOfMonth = 1 + (ruleDay - 1) * 7 + 9077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (7 + ruleDayOfWeek - (dayOfWeek - dayOfMonth + 1)) % 7; 9087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert else // Assume ruleDay < 0 here 9097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 9107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ruleDayOfMonth = monthLen + (ruleDay + 1) * 7 - 9117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (7 + (dayOfWeek + monthLen - dayOfMonth) - ruleDayOfWeek) % 7; 9127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 9147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case DOW_GE_DOM_MODE: 9157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ruleDayOfMonth = ruleDay + 9167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (49 + ruleDayOfWeek - ruleDay - dayOfWeek + dayOfMonth) % 7; 9177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 9187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case DOW_LE_DOM_MODE: 9197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ruleDayOfMonth = ruleDay - 9207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (49 - ruleDayOfWeek + ruleDay + dayOfWeek - dayOfMonth) % 7; 9217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Note at this point ruleDayOfMonth may be <1, although it will 9227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // be >=1 for well-formed rules. 9237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 9247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (dayOfMonth < ruleDayOfMonth) return -1; 9277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert else if (dayOfMonth > ruleDayOfMonth) return 1; 9287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (millis < ruleMillis){ 9307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return -1; 9317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }else if (millis > ruleMillis){ 9327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return 1; 9337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }else{ 9347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return 0; 9357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // data needed for streaming mutated SimpleTimeZones in JDK14 9397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int raw;// the TimeZone's raw GMT offset 9407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int dst = 3600000; 9417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private STZInfo xinfo = null; 9427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int startMonth, startDay, startDayOfWeek; // the month, day, DOW, and time DST starts 9437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int startTime; 9447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int startTimeMode, endTimeMode; // Mode for startTime, endTime; see TimeMode 9457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int endMonth, endDay, endDayOfWeek; // the month, day, DOW, and time DST ends 9467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int endTime; 9477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int startYear; // the year these DST rules took effect 9487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private boolean useDaylight; // flag indicating whether this TimeZone uses DST 9497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int startMode, endMode; // flags indicating what kind of rules the DST rules are 9507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 9527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Overrides TimeZone 9537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Queries if this time zone uses Daylight Saving Time. 9547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 9557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 9567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 9577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean useDaylightTime(){ 9587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return useDaylight; 9597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 9627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@inheritDoc} 9637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 49 9647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 9657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean observesDaylightTime() { 9667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return useDaylight; 9677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 9707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Overrides TimeZone 9717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Queries if the give date is in Daylight Saving Time. 9727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 9737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 9747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 9757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean inDaylightTime(Date date){ 9767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert GregorianCalendar gc = new GregorianCalendar(this); 9777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert gc.setTime(date); 9787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return gc.inDaylightTime(); 9797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 9827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Internal construction method. 9837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 9847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void construct(int _raw, 9857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int _startMonth, 9867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int _startDay, 9877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int _startDayOfWeek, 9887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int _startTime, 9897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int _startTimeMode, 9907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int _endMonth, 9917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int _endDay, 9927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int _endDayOfWeek, 9937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int _endTime, 9947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int _endTimeMode, 9957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int _dst) { 9967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert raw = _raw; 9977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startMonth = _startMonth; 9987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startDay = _startDay; 9997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startDayOfWeek = _startDayOfWeek; 10007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startTime = _startTime; 10017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startTimeMode = _startTimeMode; 10027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endMonth = _endMonth; 10037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endDay = _endDay; 10047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endDayOfWeek = _endDayOfWeek; 10057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endTime = _endTime; 10067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endTimeMode = _endTimeMode; 10077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dst = _dst; 10087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startYear = 0; 10097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startMode = DOM_MODE; 10107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endMode = DOM_MODE; 10117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert decodeRules(); 10137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (_dst <= 0) { 10157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException(); 10167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void decodeRules(){ 10197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert decodeStartRule(); 10207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert decodeEndRule(); 10217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 10247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Decode the start rule and validate the parameters. The parameters are 10257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * expected to be in encoded form, which represents the various rule modes 10267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * by negating or zeroing certain values. Representation formats are: 10277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p> 10287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <pre> 10297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DOW_IN_MONTH DOM DOW>=DOM DOW<=DOM no DST 10307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * ------------ ----- -------- -------- ---------- 10317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * month 0..11 same same same don't care 10327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * day -5..5 1..31 1..31 -1..-31 0 10337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * dayOfWeek 1..7 0 -1..-7 -1..-7 don't care 10347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * time 0..ONEDAY same same same don't care 10357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </pre> 10367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The range for month does not include UNDECIMBER since this class is 10377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * really specific to GregorianCalendar, which does not use that month. 10387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The range for time includes ONEDAY (vs. ending at ONEDAY-1) because the 10397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * end rule is an exclusive limit point. That is, the range of times that 10407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * are in DST include those >= the start and < the end. For this reason, 10417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * it should be possible to specify an end of ONEDAY in order to include the 10427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * entire day. Although this is equivalent to time 0 of the following day, 10437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * it's not always possible to specify that, for example, on December 31. 10447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * While arguably the start range should still be 0..ONEDAY-1, we keep 10457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the start and end ranges the same for consistency. 10467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 10477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void decodeStartRule() { 10487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert useDaylight = (startDay != 0) && (endDay != 0); 10497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (useDaylight && dst == 0) { 10507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dst = Grego.MILLIS_PER_DAY; 10517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (startDay != 0) { 10537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (startMonth < Calendar.JANUARY || startMonth > Calendar.DECEMBER) { 10547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException(); 10557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (startTime < 0 || startTime > Grego.MILLIS_PER_DAY || 10577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startTimeMode < WALL_TIME || startTimeMode > UTC_TIME) { 10587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException(); 10597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (startDayOfWeek == 0) { 10617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startMode = DOM_MODE; 10627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 10637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (startDayOfWeek > 0) { 10647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startMode = DOW_IN_MONTH_MODE; 10657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 10667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startDayOfWeek = -startDayOfWeek; 10677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (startDay > 0) { 10687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startMode = DOW_GE_DOM_MODE; 10697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 10707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startDay = -startDay; 10717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startMode = DOW_LE_DOM_MODE; 10727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (startDayOfWeek > Calendar.SATURDAY) { 10757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException(); 10767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (startMode == DOW_IN_MONTH_MODE) { 10797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (startDay < -5 || startDay > 5) { 10807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException(); 10817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (startDay < 1 || startDay > staticMonthLength[startMonth]) { 10837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException(); 10847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 10897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Decode the end rule and validate the parameters. This method is exactly 10907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * analogous to decodeStartRule(). 10917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #decodeStartRule 10927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 10937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void decodeEndRule() { 10947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert useDaylight = (startDay != 0) && (endDay != 0); 10957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (useDaylight && dst == 0) { 10967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dst = Grego.MILLIS_PER_DAY; 10977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (endDay != 0) { 10997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (endMonth < Calendar.JANUARY || endMonth > Calendar.DECEMBER) { 11007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException(); 11017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (endTime < 0 || endTime > Grego.MILLIS_PER_DAY || 11037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endTimeMode < WALL_TIME || endTimeMode > UTC_TIME) { 11047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException(); 11057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (endDayOfWeek == 0) { 11077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endMode = DOM_MODE; 11087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 11097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (endDayOfWeek > 0) { 11107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endMode = DOW_IN_MONTH_MODE; 11117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 11127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endDayOfWeek = -endDayOfWeek; 11137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (endDay > 0) { 11147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endMode = DOW_GE_DOM_MODE; 11157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 11167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endDay = -endDay; 11177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endMode = DOW_LE_DOM_MODE; 11187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (endDayOfWeek > Calendar.SATURDAY) { 11217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException(); 11227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (endMode == DOW_IN_MONTH_MODE) { 11257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (endDay < -5 || endDay > 5) { 11267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException(); 11277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (endDay<1 || endDay > staticMonthLength[endMonth]) { 11297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException(); 11307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 11347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 11357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Overrides equals. 11367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return true if obj is a SimpleTimeZone equivalent to this 11377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.6 11387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 11397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 11407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean equals(Object obj){ 11417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (this == obj) return true; 11427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (obj == null || getClass() != obj.getClass()) return false; 11437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert SimpleTimeZone that = (SimpleTimeZone) obj; 11447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return raw == that.raw && 11457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert useDaylight == that.useDaylight && 11467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert idEquals(getID(),that.getID()) && 11477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (!useDaylight 11487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Only check rules if using DST 11497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || (dst == that.dst && 11507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startMode == that.startMode && 11517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startMonth == that.startMonth && 11527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startDay == that.startDay && 11537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startDayOfWeek == that.startDayOfWeek && 11547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startTime == that.startTime && 11557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startTimeMode == that.startTimeMode && 11567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endMode == that.endMode && 11577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endMonth == that.endMonth && 11587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endDay == that.endDay && 11597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endDayOfWeek == that.endDayOfWeek && 11607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endTime == that.endTime && 11617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endTimeMode == that.endTimeMode && 11627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startYear == that.startYear )); 11637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 11647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private boolean idEquals(String id1, String id2){ 11667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(id1==null && id2==null){ 11677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return true; 11687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(id1!=null && id2!=null){ 11707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return id1.equals(id2); 11717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 11737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 11757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 11767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Overrides hashCode. 11777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.6 11787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 11797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 11807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int hashCode(){ 11817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int ret = super.hashCode() 11827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert + raw ^ (raw >>> 8) 11837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert + (useDaylight ? 0 : 1); 11847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(!useDaylight){ 11857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ret += dst ^ (dst >>> 10) + 11867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startMode ^ (startMode>>>11) + 11877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startMonth ^ (startMonth>>>12) + 11887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startDay ^ (startDay>>>13) + 11897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startDayOfWeek ^ (startDayOfWeek>>>14) + 11907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startTime ^ (startTime>>>15) + 11917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startTimeMode ^ (startTimeMode>>>16) + 11927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endMode ^ (endMode>>>17) + 11937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endMonth ^ (endMonth>>>18) + 11947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endDay ^ (endDay>>>19) + 11957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endDayOfWeek ^ (endDayOfWeek>>>20) + 11967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endTime ^ (endTime>>>21) + 11977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endTimeMode ^ (endTimeMode>>>22) + 11987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startYear ^ (startYear>>>23); 11997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return ret; 12017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 12037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 12047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Overrides clone. 12057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.6 12067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 12077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 12087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public Object clone() { 12097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isFrozen()) { 12107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return this; 12117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return cloneAsThawed(); 12137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 12157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 12167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns true if this zone has the same rules and offset as another zone. 12177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param othr the TimeZone object to be compared with 12187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return true if the given zone has the same rules and offset as this one 12197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 12207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 12217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 12227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean hasSameRules(TimeZone othr) { 12237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (this == othr) { 12247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return true; 12257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(!(othr instanceof SimpleTimeZone)){ 12277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 12287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert SimpleTimeZone other = (SimpleTimeZone)othr; 12307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return other != null && 12317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert raw == other.raw && 12327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert useDaylight == other.useDaylight && 12337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (!useDaylight 12347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Only check rules if using DST 12357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || (dst == other.dst && 12367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startMode == other.startMode && 12377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startMonth == other.startMonth && 12387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startDay == other.startDay && 12397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startDayOfWeek == other.startDayOfWeek && 12407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startTime == other.startTime && 12417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startTimeMode == other.startTimeMode && 12427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endMode == other.endMode && 12437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endMonth == other.endMonth && 12447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endDay == other.endDay && 12457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endDayOfWeek == other.endDayOfWeek && 12467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endTime == other.endTime && 12477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert endTimeMode == other.endTimeMode && 12487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startYear == other.startYear)); 12497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 12517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // BasicTimeZone methods 12527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 12537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 12547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@inheritDoc} 12557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 12567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 12577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 12587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public TimeZoneTransition getNextTransition(long base, boolean inclusive) { 12597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!useDaylight) { 12607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return null; 12617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 12637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert initTransitionRules(); 12647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert long firstTransitionTime = firstTransition.getTime(); 12657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (base < firstTransitionTime || (inclusive && base == firstTransitionTime)) { 12667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return firstTransition; 12677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Date stdDate = stdRule.getNextStart(base, dstRule.getRawOffset(), dstRule.getDSTSavings(), 12697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert inclusive); 12707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Date dstDate = dstRule.getNextStart(base, stdRule.getRawOffset(), stdRule.getDSTSavings(), 12717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert inclusive); 12727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (stdDate != null && (dstDate == null || stdDate.before(dstDate))) { 12737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return new TimeZoneTransition(stdDate.getTime(), dstRule, stdRule); 12747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (dstDate != null && (stdDate == null || dstDate.before(stdDate))) { 12767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return new TimeZoneTransition(dstDate.getTime(), stdRule, dstRule); 12777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return null; 12797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 12817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 12827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@inheritDoc} 12837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 12847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 12857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 12867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public TimeZoneTransition getPreviousTransition(long base, boolean inclusive) { 12877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!useDaylight) { 12887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return null; 12897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 12917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert initTransitionRules(); 12927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert long firstTransitionTime = firstTransition.getTime(); 12937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (base < firstTransitionTime || (!inclusive && base == firstTransitionTime)) { 12947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return null; 12957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Date stdDate = stdRule.getPreviousStart(base, dstRule.getRawOffset(), 12977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dstRule.getDSTSavings(), inclusive); 12987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Date dstDate = dstRule.getPreviousStart(base, stdRule.getRawOffset(), 12997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert stdRule.getDSTSavings(), inclusive); 13007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (stdDate != null && (dstDate == null || stdDate.after(dstDate))) { 13017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return new TimeZoneTransition(stdDate.getTime(), dstRule, stdRule); 13027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (dstDate != null && (stdDate == null || dstDate.after(stdDate))) { 13047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return new TimeZoneTransition(dstDate.getTime(), stdRule, dstRule); 13057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return null; 13077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 13107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@inheritDoc} 13117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 13127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 13137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 13147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public TimeZoneRule[] getTimeZoneRules() { 13157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert initTransitionRules(); 13167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int size = useDaylight ? 3 : 1; 13187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert TimeZoneRule[] rules = new TimeZoneRule[size]; 13197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert rules[0] = initialRule; 13207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (useDaylight) { 13217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert rules[1] = stdRule; 13227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert rules[2] = dstRule; 13237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return rules; 13257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private transient boolean transitionRulesInitialized; 13287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private transient InitialTimeZoneRule initialRule; 13297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private transient TimeZoneTransition firstTransition; 13307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private transient AnnualTimeZoneRule stdRule; 13317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private transient AnnualTimeZoneRule dstRule; 13327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private synchronized void initTransitionRules() { 13347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (transitionRulesInitialized) { 13357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return; 13367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (useDaylight) { 13387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DateTimeRule dtRule = null; 13397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int timeRuleType; 13407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert long firstStdStart, firstDstStart; 13417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Create a TimeZoneRule for daylight saving time 13437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert timeRuleType = (startTimeMode == STANDARD_TIME) ? DateTimeRule.STANDARD_TIME : 13447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ((startTimeMode == UTC_TIME) ? DateTimeRule.UTC_TIME : DateTimeRule.WALL_TIME); 13457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert switch (startMode) { 13467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case DOM_MODE: 13477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dtRule = new DateTimeRule(startMonth, startDay, startTime, timeRuleType); 13487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 13497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case DOW_IN_MONTH_MODE: 13507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dtRule = new DateTimeRule(startMonth, startDay, startDayOfWeek, startTime, 13517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert timeRuleType); 13527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 13537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case DOW_GE_DOM_MODE: 13547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dtRule = new DateTimeRule(startMonth, startDay, startDayOfWeek, true, startTime, 13557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert timeRuleType); 13567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 13577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case DOW_LE_DOM_MODE: 13587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dtRule = new DateTimeRule(startMonth, startDay, startDayOfWeek, false, startTime, 13597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert timeRuleType); 13607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 13617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // For now, use ID + "(DST)" as the name 13637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dstRule = new AnnualTimeZoneRule(getID() + "(DST)", getRawOffset(), getDSTSavings(), 13647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dtRule, startYear, AnnualTimeZoneRule.MAX_YEAR); 13657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Calculate the first DST start time 13677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert firstDstStart = dstRule.getFirstStart(getRawOffset(), 0).getTime(); 13687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Create a TimeZoneRule for standard time 13707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert timeRuleType = (endTimeMode == STANDARD_TIME) ? DateTimeRule.STANDARD_TIME : 13717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ((endTimeMode == UTC_TIME) ? DateTimeRule.UTC_TIME : DateTimeRule.WALL_TIME); 13727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert switch (endMode) { 13737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case DOM_MODE: 13747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dtRule = new DateTimeRule(endMonth, endDay, endTime, timeRuleType); 13757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 13767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case DOW_IN_MONTH_MODE: 13777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dtRule = new DateTimeRule(endMonth, endDay, endDayOfWeek, endTime, timeRuleType); 13787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 13797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case DOW_GE_DOM_MODE: 13807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dtRule = new DateTimeRule(endMonth, endDay, endDayOfWeek, true, endTime, 13817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert timeRuleType); 13827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 13837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case DOW_LE_DOM_MODE: 13847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dtRule = new DateTimeRule(endMonth, endDay, endDayOfWeek, false, endTime, 13857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert timeRuleType); 13867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 13877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // For now, use ID + "(STD)" as the name 13897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert stdRule = new AnnualTimeZoneRule(getID() + "(STD)", getRawOffset(), 0, 13907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dtRule, startYear, AnnualTimeZoneRule.MAX_YEAR); 13917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Calculate the first STD start time 13937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert firstStdStart = stdRule.getFirstStart(getRawOffset(), dstRule.getDSTSavings()).getTime(); 13947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Create a TimeZoneRule for initial time 13967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (firstStdStart < firstDstStart) { 13977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert initialRule = new InitialTimeZoneRule(getID() + "(DST)", getRawOffset(), 13987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dstRule.getDSTSavings()); 13997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert firstTransition = new TimeZoneTransition(firstStdStart, initialRule, stdRule); 14007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 14017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert initialRule = new InitialTimeZoneRule(getID() + "(STD)", getRawOffset(), 0); 14027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert firstTransition = new TimeZoneTransition(firstDstStart, initialRule, dstRule); 14037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 14057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 14067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Create a TimeZoneRule for initial time 14077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert initialRule = new InitialTimeZoneRule(getID(), getRawOffset(), 0); 14087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert transitionRulesInitialized = true; 14107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 14127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Freezable stuffs 14137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private volatile transient boolean isFrozen = false; 14147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 14157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 14167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@inheritDoc} 14177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 49 14187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 14197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean isFrozen() { 14207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return isFrozen; 14217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 14237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 14247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@inheritDoc} 14257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 49 14267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 14277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public TimeZone freeze() { 14287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert isFrozen = true; 14297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return this; 14307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 14327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 14337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@inheritDoc} 14347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 49 14357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 14367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public TimeZone cloneAsThawed() { 14377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert SimpleTimeZone tz = (SimpleTimeZone)super.cloneAsThawed(); 14387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tz.isFrozen = false; 14397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return tz; 14407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert} 1442