0001: /*
0002: * Copyright (C) 1996-2006, International Business Machines
0003: * Corporation and others. All Rights Reserved.
0004: */
0005:
0006: package com.ibm.icu.util;
0007:
0008: import com.ibm.icu.impl.JDKTimeZone;
0009:
0010: import java.io.IOException;
0011: import java.util.Date;
0012:
0013: import com.ibm.icu.impl.OlsonTimeZone;
0014: import com.ibm.icu.impl.Utility;
0015:
0016: ///CLOVER:USECLASS
0017: /**
0018: * <code>SimpleTimeZone</code> is a concrete subclass of <code>TimeZone</code>
0019: * that represents a time zone for use with a Gregorian calendar. This
0020: * class does not handle historical changes.
0021: *
0022: * <P>
0023: * Use a negative value for <code>dayOfWeekInMonth</code> to indicate that
0024: * <code>SimpleTimeZone</code> should count from the end of the month backwards.
0025: * For example, Daylight Savings Time ends at the last
0026: * (dayOfWeekInMonth = -1) Sunday in October, at 2 AM in standard time.
0027: *
0028: * @see Calendar
0029: * @see GregorianCalendar
0030: * @see TimeZone
0031: * @author David Goldsmith, Mark Davis, Chen-Lieh Huang, Alan Liu
0032: * @stable ICU 2.0
0033: */
0034: public class SimpleTimeZone extends JDKTimeZone {
0035: private static final long serialVersionUID = -7034676239311322769L;
0036:
0037: /**
0038: * Constructs a SimpleTimeZone with the given base time zone offset from GMT
0039: * and time zone ID. Timezone IDs can be obtained from
0040: * TimeZone.getAvailableIDs. Normally you should use TimeZone.getDefault to
0041: * construct a TimeZone.
0042: *
0043: * @param rawOffset The given base time zone offset to GMT.
0044: * @param ID The time zone ID which is obtained from
0045: * TimeZone.getAvailableIDs.
0046: * @stable ICU 2.0
0047: */
0048: public SimpleTimeZone(int rawOffset, String ID) {
0049: //this(new java.util.SimpleTimeZone(rawOffset, ID), ID);
0050: //super(ID);
0051: construct(rawOffset, 0, 0, 0, 0, WALL_TIME, 0, 0, 0, 0,
0052: WALL_TIME, MILLIS_PER_HOUR);
0053: super .setID(ID);
0054: }
0055:
0056: /**
0057: * Construct a SimpleTimeZone with the given base time zone offset from
0058: * GMT, time zone ID, time to start and end the daylight time. Timezone IDs
0059: * can be obtained from TimeZone.getAvailableIDs. Normally you should use
0060: * TimeZone.getDefault to create a TimeZone. For a time zone that does not
0061: * use daylight saving time, do not use this constructor; instead you should
0062: * use SimpleTimeZone(rawOffset, ID).
0063: *
0064: * By default, this constructor specifies day-of-week-in-month rules. That
0065: * is, if the startDay is 1, and the startDayOfWeek is SUNDAY, then this
0066: * indicates the first Sunday in the startMonth. A startDay of -1 likewise
0067: * indicates the last Sunday. However, by using negative or zero values for
0068: * certain parameters, other types of rules can be specified.
0069: *
0070: * Day of month. To specify an exact day of the month, such as March 1, set
0071: * startDayOfWeek to zero.
0072: *
0073: * Day of week after day of month. To specify the first day of the week
0074: * occurring on or after an exact day of the month, make the day of the week
0075: * negative. For example, if startDay is 5 and startDayOfWeek is -MONDAY,
0076: * this indicates the first Monday on or after the 5th day of the
0077: * startMonth.
0078: *
0079: * Day of week before day of month. To specify the last day of the week
0080: * occurring on or before an exact day of the month, make the day of the
0081: * week and the day of the month negative. For example, if startDay is -21
0082: * and startDayOfWeek is -WEDNESDAY, this indicates the last Wednesday on or
0083: * before the 21st of the startMonth.
0084: *
0085: * The above examples refer to the startMonth, startDay, and startDayOfWeek;
0086: * the same applies for the endMonth, endDay, and endDayOfWeek.
0087: *
0088: * @param rawOffset The given base time zone offset to GMT.
0089: * @param ID The time zone ID which is obtained from
0090: * TimeZone.getAvailableIDs.
0091: * @param startMonth The daylight savings starting month. Month is
0092: * 0-based. eg, 0 for January.
0093: * @param startDay The daylight savings starting
0094: * day-of-week-in-month. Please see the member
0095: * description for an example.
0096: * @param startDayOfWeek The daylight savings starting day-of-week. Please
0097: * see the member description for an example.
0098: * @param startTime The daylight savings starting time in local wall
0099: * time, which is standard time in this case. Please see the
0100: * member description for an example.
0101: * @param endMonth The daylight savings ending month. Month is
0102: * 0-based. eg, 0 for January.
0103: * @param endDay The daylight savings ending day-of-week-in-month.
0104: * Please see the member description for an example.
0105: * @param endDayOfWeek The daylight savings ending day-of-week. Please
0106: * see the member description for an example.
0107: * @param endTime The daylight savings ending time in local wall time,
0108: * which is daylight time in this case. Please see the
0109: * member description for an example.
0110: * @exception IllegalArgumentException the month, day, dayOfWeek, or time
0111: * parameters are out of range for the start or end rule
0112: * @stable ICU 2.0
0113: */
0114: public SimpleTimeZone(int rawOffset, String ID, int startMonth,
0115: int startDay, int startDayOfWeek, int startTime,
0116: int endMonth, int endDay, int endDayOfWeek, int endTime) {
0117: /* this(new java.util.SimpleTimeZone(rawOffset, ID, startMonth, startDay,
0118: startDayOfWeek, startTime, endMonth,
0119: endDay, endDayOfWeek, endTime), ID);*/
0120: // STZInfo xinfo = getSTZInfo();
0121: // xinfo.setStart(startMonth, startDay, startDayOfWeek, startTime, -1, false);
0122: // xinfo.setEnd(endMonth, endDay, endDayOfWeek, endTime, -1, false);
0123: construct(rawOffset, startMonth, startDay, startDayOfWeek,
0124: startTime, WALL_TIME, endMonth, endDay, endDayOfWeek,
0125: endTime, WALL_TIME, MILLIS_PER_HOUR);
0126: super .setID(ID);
0127: }
0128:
0129: /**
0130: * Constructor. This constructor is identical to the 10-argument
0131: * constructor, but also takes a dstSavings parameter.
0132: * @param dstSavings The amount of time in ms saved during DST.
0133: * @exception IllegalArgumentException the month, day, dayOfWeek, or time
0134: * parameters are out of range for the start or end rule
0135: * @stable ICU 2.0
0136: */
0137: public SimpleTimeZone(int rawOffset, String ID, int startMonth,
0138: int startDay, int startDayOfWeek, int startTime,
0139: int endMonth, int endDay, int endDayOfWeek, int endTime,
0140: int dstSavings) {
0141: /*this(new java.util.SimpleTimeZone(rawOffset, ID, startMonth, startDay,
0142: startDayOfWeek, startTime, endMonth,
0143: endDay, endDayOfWeek, endTime, dstSavings), ID);*/
0144: this .raw = rawOffset;
0145: this .dst = dstSavings;
0146: /*
0147: STZInfo xinfo = getSTZInfo();
0148: xinfo.setStart(startMonth, startDay, startDayOfWeek, startTime, -1, false);
0149: xinfo.setEnd(endMonth, endDay, endDayOfWeek, endTime, -1, false);
0150: */
0151:
0152: construct(rawOffset, startMonth, startDay, startDayOfWeek,
0153: startTime, WALL_TIME, endMonth, endDay, endDayOfWeek,
0154: endTime, WALL_TIME, dstSavings);
0155: super .setID(ID);
0156: }
0157:
0158: /**
0159: * Set the raw offset.
0160: *
0161: * @param offsetMillis the raw offset of the time zone
0162: * @draft ICU 3.4
0163: * @provisional This API might change or be removed in a future release.
0164: */
0165: public void setRawOffset(int offsetMillis) {
0166: raw = offsetMillis;
0167: }
0168:
0169: /**
0170: * get the raw offset.
0171: *
0172: * @return the raw offset
0173: * @internal revisit for ICU 3.6
0174: * @deprecated This API is ICU internal only.
0175: */
0176: public int getRawOffset() {
0177: return raw;
0178: }
0179:
0180: /**
0181: * Sets the daylight savings starting year.
0182: *
0183: * @param year The daylight savings starting year.
0184: * @stable ICU 2.0
0185: */
0186: public void setStartYear(int year) {
0187: //unwrapSTZ().setStartYear(year);
0188:
0189: getSTZInfo().sy = year;
0190: this .startYear = year;
0191: }
0192:
0193: /**
0194: * Sets the daylight savings starting rule. For example, Daylight Savings
0195: * Time starts at the first Sunday in April, at 2 AM in standard time.
0196: * Therefore, you can set the start rule by calling:
0197: * setStartRule(TimeFields.APRIL, 1, TimeFields.SUNDAY, 2*60*60*1000);
0198: *
0199: * @param month The daylight savings starting month. Month is
0200: * 0-based. eg, 0 for January.
0201: * @param dayOfWeekInMonth The daylight savings starting
0202: * day-of-week-in-month. Please see the member
0203: * description for an example.
0204: * @param dayOfWeek The daylight savings starting day-of-week.
0205: * Please see the member description for an
0206: * example.
0207: * @param time The daylight savings starting time in local wall
0208: * time, which is standard time in this case. Please see
0209: * the member description for an example.
0210: * @exception IllegalArgumentException the month, dayOfWeekInMonth,
0211: * dayOfWeek, or time parameters are out of range
0212: * @stable ICU 2.0
0213: */
0214: public void setStartRule(int month, int dayOfWeekInMonth,
0215: int dayOfWeek, int time) {
0216: //unwrapSTZ().setStartRule(month, dayOfWeekInMonth, dayOfWeek, time);
0217:
0218: getSTZInfo().setStart(month, dayOfWeekInMonth, dayOfWeek, time,
0219: -1, false);
0220: setStartRule(month, dayOfWeekInMonth, dayOfWeek, time,
0221: WALL_TIME);
0222: }
0223:
0224: /**
0225: * Sets the daylight savings starting rule. For example, in the U.S., Daylight Savings
0226: * Time starts at the first Sunday in April, at 2 AM in standard time.
0227: * Therefore, you can set the start rule by calling:
0228: * setStartRule(TimeFields.APRIL, 1, TimeFields.SUNDAY, 2*60*60*1000);
0229: * The dayOfWeekInMonth and dayOfWeek parameters together specify how to calculate
0230: * the exact starting date. Their exact meaning depend on their respective signs,
0231: * allowing various types of rules to be constructed, as follows:<ul>
0232: * <li>If both dayOfWeekInMonth and dayOfWeek are positive, they specify the
0233: * day of week in the month (e.g., (2, WEDNESDAY) is the second Wednesday
0234: * of the month).
0235: * <li>If dayOfWeek is positive and dayOfWeekInMonth is negative, they specify
0236: * the day of week in the month counting backward from the end of the month.
0237: * (e.g., (-1, MONDAY) is the last Monday in the month)
0238: * <li>If dayOfWeek is zero and dayOfWeekInMonth is positive, dayOfWeekInMonth
0239: * specifies the day of the month, regardless of what day of the week it is.
0240: * (e.g., (10, 0) is the tenth day of the month)
0241: * <li>If dayOfWeek is zero and dayOfWeekInMonth is negative, dayOfWeekInMonth
0242: * specifies the day of the month counting backward from the end of the
0243: * month, regardless of what day of the week it is (e.g., (-2, 0) is the
0244: * next-to-last day of the month).
0245: * <li>If dayOfWeek is negative and dayOfWeekInMonth is positive, they specify the
0246: * first specified day of the week on or after the specfied day of the month.
0247: * (e.g., (15, -SUNDAY) is the first Sunday after the 15th of the month
0248: * [or the 15th itself if the 15th is a Sunday].)
0249: * <li>If dayOfWeek and DayOfWeekInMonth are both negative, they specify the
0250: * last specified day of the week on or before the specified day of the month.
0251: * (e.g., (-20, -TUESDAY) is the last Tuesday before the 20th of the month
0252: * [or the 20th itself if the 20th is a Tuesday].)</ul>
0253: * @param month the daylight savings starting month. Month is 0-based.
0254: * eg, 0 for January.
0255: * @param dayOfWeekInMonth the daylight savings starting
0256: * day-of-week-in-month. Please see the member description for an example.
0257: * @param dayOfWeek the daylight savings starting day-of-week. Please see
0258: * the member description for an example.
0259: * @param time the daylight savings starting time. Please see the member
0260: * description for an example.
0261: */
0262:
0263: private void setStartRule(int month, int dayOfWeekInMonth,
0264: int dayOfWeek, int time, int mode) {
0265: startMonth = month;
0266: startDay = dayOfWeekInMonth;
0267: startDayOfWeek = dayOfWeek;
0268: startTime = time;
0269: startTimeMode = mode;
0270: decodeStartRule();
0271: }
0272:
0273: /**
0274: * Sets the DST start rule to a fixed date within a month.
0275: *
0276: * @param month The month in which this rule occurs (0-based).
0277: * @param dayOfMonth The date in that month (1-based).
0278: * @param time The time of that day (number of millis after midnight)
0279: * when DST takes effect in local wall time, which is
0280: * standard time in this case.
0281: * @exception IllegalArgumentException the month,
0282: * dayOfMonth, or time parameters are out of range
0283: * @stable ICU 2.0
0284: */
0285: public void setStartRule(int month, int dayOfMonth, int time) {
0286: // unwrapSTZ().setStartRule(month, dayOfMonth, time);
0287:
0288: getSTZInfo().setStart(month, -1, -1, time, dayOfMonth, false);
0289: setStartRule(month, dayOfMonth, 0, time, WALL_TIME);
0290: }
0291:
0292: /**
0293: * Sets the DST start rule to a weekday before or after a give date within
0294: * a month, e.g., the first Monday on or after the 8th.
0295: *
0296: * @param month The month in which this rule occurs (0-based).
0297: * @param dayOfMonth A date within that month (1-based).
0298: * @param dayOfWeek The day of the week on which this rule occurs.
0299: * @param time The time of that day (number of millis after midnight)
0300: * when DST takes effect in local wall time, which is
0301: * standard time in this case.
0302: * @param after If true, this rule selects the first dayOfWeek on
0303: * or after dayOfMonth. If false, this rule selects
0304: * the last dayOfWeek on or before dayOfMonth.
0305: * @exception IllegalArgumentException the month, dayOfMonth,
0306: * dayOfWeek, or time parameters are out of range
0307: * @stable ICU 2.0
0308: */
0309: public void setStartRule(int month, int dayOfMonth, int dayOfWeek,
0310: int time, boolean after) {
0311: //unwrapSTZ().setStartRule(month, dayOfMonth, dayOfWeek, time, after);
0312:
0313: getSTZInfo().setStart(month, -1, dayOfWeek, time, dayOfMonth,
0314: after);
0315: setStartRule(month, after ? dayOfMonth : -dayOfMonth,
0316: -dayOfWeek, time, WALL_TIME);
0317:
0318: }
0319:
0320: /**
0321: * Sets the daylight savings ending rule. For example, Daylight Savings Time
0322: * ends at the last (-1) Sunday in October, at 2 AM in standard time.
0323: * Therefore, you can set the end rule by calling:
0324: * setEndRule(TimeFields.OCTOBER, -1, TimeFields.SUNDAY, 2*60*60*1000);
0325: *
0326: * @param month The daylight savings ending month. Month is
0327: * 0-based. eg, 0 for January.
0328: * @param dayOfWeekInMonth The daylight savings ending
0329: * day-of-week-in-month. Please see the member
0330: * description for an example.
0331: * @param dayOfWeek The daylight savings ending day-of-week. Please
0332: * see the member description for an example.
0333: * @param time The daylight savings ending time in local wall time,
0334: * which is daylight time in this case. Please see the
0335: * member description for an example.
0336: * @exception IllegalArgumentException the month, dayOfWeekInMonth,
0337: * dayOfWeek, or time parameters are out of range
0338: * @stable ICU 2.0
0339: */
0340: public void setEndRule(int month, int dayOfWeekInMonth,
0341: int dayOfWeek, int time) {
0342: //unwrapSTZ().setEndRule(month, dayOfWeekInMonth, dayOfWeek, time);
0343:
0344: getSTZInfo().setEnd(month, dayOfWeekInMonth, dayOfWeek, time,
0345: -1, false);
0346: setEndRule(month, dayOfWeekInMonth, dayOfWeek, time, WALL_TIME);
0347: }
0348:
0349: /**
0350: * Sets the DST end rule to a fixed date within a month.
0351: *
0352: * @param month The month in which this rule occurs (0-based).
0353: * @param dayOfMonth The date in that month (1-based).
0354: * @param time The time of that day (number of millis after midnight)
0355: * when DST ends in local wall time, which is daylight
0356: * time in this case.
0357: * @exception IllegalArgumentException the month,
0358: * dayOfMonth, or time parameters are out of range
0359: * @stable ICU 2.0
0360: */
0361: public void setEndRule(int month, int dayOfMonth, int time) {
0362: //unwrapSTZ().setEndRule(month, dayOfMonth, time);
0363:
0364: getSTZInfo().setEnd(month, -1, -1, time, dayOfMonth, false);
0365: setEndRule(month, dayOfMonth, WALL_TIME, time);
0366: }
0367:
0368: /**
0369: * Sets the DST end rule to a weekday before or after a give date within
0370: * a month, e.g., the first Monday on or after the 8th.
0371: *
0372: * @param month The month in which this rule occurs (0-based).
0373: * @param dayOfMonth A date within that month (1-based).
0374: * @param dayOfWeek The day of the week on which this rule occurs.
0375: * @param time The time of that day (number of millis after midnight)
0376: * when DST ends in local wall time, which is daylight
0377: * time in this case.
0378: * @param after If true, this rule selects the first dayOfWeek on
0379: * or after dayOfMonth. If false, this rule selects
0380: * the last dayOfWeek on or before dayOfMonth.
0381: * @exception IllegalArgumentException the month, dayOfMonth,
0382: * dayOfWeek, or time parameters are out of range
0383: * @stable ICU 2.0
0384: */
0385: public void setEndRule(int month, int dayOfMonth, int dayOfWeek,
0386: int time, boolean after) {
0387: // unwrapSTZ().setEndRule(month, dayOfMonth, dayOfWeek, time, after);
0388:
0389: getSTZInfo().setEnd(month, -1, dayOfWeek, time, dayOfMonth,
0390: after);
0391: setEndRule(month, dayOfMonth, dayOfWeek, time, WALL_TIME, after);
0392: }
0393:
0394: private void setEndRule(int month, int dayOfMonth, int dayOfWeek,
0395: int time, int mode, boolean after) {
0396: setEndRule(month, after ? dayOfMonth : -dayOfMonth, -dayOfWeek,
0397: time, mode);
0398: }
0399:
0400: /**
0401: * Sets the daylight savings ending rule. For example, in the U.S., Daylight
0402: * Savings Time ends at the last (-1) Sunday in October, at 2 AM in standard time.
0403: * Therefore, you can set the end rule by calling:
0404: * setEndRule(TimeFields.OCTOBER, -1, TimeFields.SUNDAY, 2*60*60*1000);
0405: * Various other types of rules can be specified by manipulating the dayOfWeek
0406: * and dayOfWeekInMonth parameters. For complete details, see the documentation
0407: * for setStartRule().
0408: * @param month the daylight savings ending month. Month is 0-based.
0409: * eg, 0 for January.
0410: * @param dayOfWeekInMonth the daylight savings ending
0411: * day-of-week-in-month. See setStartRule() for a complete explanation.
0412: * @param dayOfWeek the daylight savings ending day-of-week. See setStartRule()
0413: * for a complete explanation.
0414: * @param time the daylight savings ending time. Please see the member
0415: * description for an example.
0416: */
0417: private void setEndRule(int month, int dayOfWeekInMonth,
0418: int dayOfWeek, int time, int mode) {
0419: endMonth = month;
0420: endDay = dayOfWeekInMonth;
0421: endDayOfWeek = dayOfWeek;
0422: endTime = time;
0423: endTimeMode = mode;
0424: decodeEndRule();
0425: }
0426:
0427: /**
0428: * Sets the amount of time in ms that the clock is advanced during DST.
0429: * @param millisSavedDuringDST the number of milliseconds the time is
0430: * advanced with respect to standard time when the daylight savings rules
0431: * are in effect. A positive number, typically one hour (3600000).
0432: * @stable ICU 2.0
0433: */
0434: public void setDSTSavings(int millisSavedDuringDST) {
0435: //unwrapSTZ().setDSTSavings(millisSavedDuringDST);
0436: if (millisSavedDuringDST <= 0) {
0437: throw new IllegalArgumentException();
0438: }
0439: dst = millisSavedDuringDST;
0440: }
0441:
0442: /**
0443: * Returns the amount of time in ms that the clock is advanced during DST.
0444: * @return the number of milliseconds the time is
0445: * advanced with respect to standard time when the daylight savings rules
0446: * are in effect. A positive number, typically one hour (3600000).
0447: * @stable ICU 2.0
0448: */
0449: public int getDSTSavings() {
0450: return dst;
0451: }
0452:
0453: /**
0454: * Constructs a SimpleTimeZone that wraps the given
0455: * java.util.SimpleTimeZone. Do not call; use the TimeZone
0456: * API.
0457: * @internal
0458: * @deprecated This API is ICU internal only.
0459: */
0460: public SimpleTimeZone(java.util.SimpleTimeZone tz, String ID) {
0461: super (tz);
0462: super .setID(ID);
0463: dst = tz.getDSTSavings();
0464: raw = tz.getRawOffset();
0465: }
0466:
0467: /**
0468: * Returns the java.util.SimpleTimeZone that this class wraps.
0469: *
0470: java.util.SimpleTimeZone unwrapSTZ() {
0471: return (java.util.SimpleTimeZone) unwrap();
0472: }
0473: */
0474: // on JDK 1.4 and later, can't deserialize a SimpleTimeZone as a SimpleTimeZone...
0475: private void readObject(java.io.ObjectInputStream in)
0476: throws IOException, ClassNotFoundException {
0477: in.defaultReadObject();
0478: String id = getID();
0479: /*
0480: if (id!=null && !(zone instanceof java.util.SimpleTimeZone && zone.getID().equals(id))) {
0481: // System.out.println("*** readjust " + zone.getClass().getName() + " " + zone.getID() + " ***");
0482: java.util.SimpleTimeZone stz =
0483: new java.util.SimpleTimeZone(raw, id);
0484: if (dst != 0) {
0485: stz.setDSTSavings(dst);
0486: // if it is 0, then there shouldn't be start/end rules and the default
0487: // behavior should be no dst
0488: }
0489:
0490: if (xinfo != null) {
0491: xinfo.applyTo(stz);
0492: }
0493: zoneJDK = stz;
0494: }
0495: */
0496: /* set all instance variables in this object
0497: * to the values in zone
0498: */
0499: if (xinfo != null) {
0500: xinfo.applyTo(this );
0501: }
0502:
0503: }
0504:
0505: /**
0506: * Returns a string representation of this object.
0507: * @return a string representation of this object
0508: * @draft ICU 3.4.2
0509: * @provisional This API might change or be removed in a future release.
0510: */
0511: public String toString() {
0512: return "SimpleTimeZone: " + getID();
0513: }
0514:
0515: private STZInfo getSTZInfo() {
0516: if (xinfo == null) {
0517: xinfo = new STZInfo();
0518: }
0519: return xinfo;
0520: }
0521:
0522: // WARNING: assumes that no rule is measured from the end of February,
0523: // since we don't handle leap years. Could handle assuming always
0524: // Gregorian, since we know they didn't have daylight time when
0525: // Gregorian calendar started.
0526: // private static final int[] STATICMONTHLENGTH = new int[]{31,29,31,30,31,30,31,31,30,31,30,31};
0527: private final byte monthLength[] = staticMonthLength;
0528: private final static byte staticMonthLength[] = { 31, 29, 31, 30,
0529: 31, 30, 31, 31, 30, 31, 30, 31 };
0530: private final static byte staticLeapMonthLength[] = { 31, 29, 31,
0531: 30, 31, 30, 31, 31, 30, 31, 30, 31 };
0532:
0533: // -------------------------------------
0534:
0535: /**
0536: * @internal revisit for ICU 3.6
0537: * @deprecated This API is ICU internal only.
0538: */
0539: public int getOffset(int era, int year, int month, int day,
0540: int dayOfWeek, int millis) {
0541: // Check the month before indexing into STATICMONTHLENGTH. This
0542: // duplicates the test that occurs in the 7-argument getOffset(),
0543: // however, this is unavoidable. We don't mind because this method, in
0544: // fact, should not be called; internal code should always call the
0545: // 7-argument getOffset(), and outside code should use Calendar.get(int
0546: // field) with fields ZONE_OFFSET and DST_OFFSET. We can't get rid of
0547: // this method because it's public API. - liu 8/10/98
0548: if (month < Calendar.JANUARY || month > Calendar.DECEMBER) {
0549: throw new IllegalArgumentException();
0550: }
0551:
0552: return getOffset(era, year, month, day, dayOfWeek, millis,
0553: staticMonthLength[month]);
0554: }
0555:
0556: /**
0557: * @internal revisit for ICU 3.6
0558: * @deprecated This API is ICU internal only.
0559: */
0560: public int getOffset(int era, int year, int month, int day,
0561: int dayOfWeek, int millis, int monthLength) {
0562: // Check the month before indexing into STATICMONTHLENGTH. This
0563: // duplicates a test that occurs in the 9-argument getOffset(),
0564: // however, this is unavoidable. We don't mind because this method, in
0565: // fact, should not be called; internal code should always call the
0566: // 9-argument getOffset(), and outside code should use Calendar.get(int
0567: // field) with fields ZONE_OFFSET and DST_OFFSET. We can't get rid of
0568: // this method because it's public API. - liu 8/10/98
0569: if (month < Calendar.JANUARY || month > Calendar.DECEMBER) {
0570: throw new IllegalArgumentException();
0571: }
0572:
0573: // TODO FIX We don't handle leap years yet!
0574: int prevMonthLength = (month >= 1) ? staticMonthLength[month - 1]
0575: : 31;
0576:
0577: return getOffset(era, year, month, day, dayOfWeek, millis,
0578: monthLength, prevMonthLength);
0579: }
0580:
0581: int getOffset(int era, int year, int month, int day, int dayOfWeek,
0582: int millis, int monthLength, int prevMonthLength) {
0583:
0584: if (true) {
0585: /* Use this parameter checking code for normal operation. Only one
0586: * of these two blocks should actually get compiled into the class
0587: * file. */
0588: if ((era != GregorianCalendar.AD && era != GregorianCalendar.BC)
0589: || month < Calendar.JANUARY
0590: || month > Calendar.DECEMBER
0591: || day < 1
0592: || day > monthLength
0593: || dayOfWeek < Calendar.SUNDAY
0594: || dayOfWeek > Calendar.SATURDAY
0595: || millis < 0
0596: || millis >= MILLIS_PER_DAY
0597: || monthLength < 28
0598: || monthLength > 31
0599: || prevMonthLength < 28
0600: || prevMonthLength > 31) {
0601: throw new IllegalArgumentException();
0602: }
0603: } else {
0604: /* This parameter checking code is better for debugging, but
0605: * overkill for normal operation. Only one of these two blocks
0606: * should actually get compiled into the class file. */
0607: if (era != GregorianCalendar.AD
0608: && era != GregorianCalendar.BC) {
0609: throw new IllegalArgumentException("Illegal era " + era);
0610: }
0611: if (month < Calendar.JANUARY || month > Calendar.DECEMBER) {
0612: throw new IllegalArgumentException("Illegal month "
0613: + month);
0614: }
0615: if (day < 1 || day > monthLength) {
0616: throw new IllegalArgumentException("Illegal day " + day
0617: + " max month len: " + monthLength);
0618: }
0619: if (dayOfWeek < Calendar.SUNDAY
0620: || dayOfWeek > Calendar.SATURDAY) {
0621: throw new IllegalArgumentException(
0622: "Illegal day of week " + dayOfWeek);
0623: }
0624: if (millis < 0 || millis >= MILLIS_PER_DAY) {
0625: throw new IllegalArgumentException("Illegal millis "
0626: + millis);
0627: }
0628: if (monthLength < 28 || monthLength > 31) {
0629: throw new IllegalArgumentException(
0630: "Illegal month length " + monthLength);
0631: }
0632: if (prevMonthLength < 28 || prevMonthLength > 31) {
0633: throw new IllegalArgumentException(
0634: "Illegal previous month length "
0635: + prevMonthLength);
0636: }
0637: }
0638:
0639: int result = raw;
0640:
0641: // Bail out if we are before the onset of daylight savings time
0642: if (!useDaylight || year < startYear
0643: || era != GregorianCalendar.AD)
0644: return result;
0645:
0646: // Check for southern hemisphere. We assume that the start and end
0647: // month are different.
0648: boolean southern = (startMonth > endMonth);
0649:
0650: // Compare the date to the starting and ending rules.+1 = date>rule, -1
0651: // = date<rule, 0 = date==rule.
0652: int startCompare = compareToRule(month, monthLength,
0653: prevMonthLength, day, dayOfWeek, millis,
0654: startTimeMode == UTC_TIME ? -raw : 0, startMode,
0655: startMonth, startDayOfWeek, startDay, startTime);
0656: int endCompare = 0;
0657:
0658: /* We don't always have to compute endCompare. For many instances,
0659: * startCompare is enough to determine if we are in DST or not. In the
0660: * northern hemisphere, if we are before the start rule, we can't have
0661: * DST. In the southern hemisphere, if we are after the start rule, we
0662: * must have DST. This is reflected in the way the next if statement
0663: * (not the one immediately following) short circuits. */
0664: if (southern != (startCompare >= 0)) {
0665: /* For the ending rule comparison, we add the dstSavings to the millis
0666: * passed in to convert them from standard to wall time. We then must
0667: * normalize the millis to the range 0..millisPerDay-1. */
0668: endCompare = compareToRule(month, monthLength,
0669: prevMonthLength, day, dayOfWeek, millis,
0670: endTimeMode == WALL_TIME ? dst
0671: : (endTimeMode == UTC_TIME ? -raw : 0),
0672: endMode, endMonth, endDayOfWeek, endDay, endTime);
0673: }
0674:
0675: // Check for both the northern and southern hemisphere cases. We
0676: // assume that in the northern hemisphere, the start rule is before the
0677: // end rule within the calendar year, and vice versa for the southern
0678: // hemisphere.
0679: if ((!southern && (startCompare >= 0 && endCompare < 0))
0680: || (southern && (startCompare >= 0 || endCompare < 0)))
0681: result += dst;
0682:
0683: return result;
0684: }
0685:
0686: // -------------------------------------
0687: private static final int DOM_MODE = 1, DOW_IN_MONTH_MODE = 2,
0688: DOW_GE_DOM_MODE = 3, DOW_LE_DOM_MODE = 4;
0689:
0690: /**
0691: * TimeMode is used, together with a millisecond offset after
0692: * midnight, to specify a rule transition time. Most rules
0693: * transition at a local wall time, that is, according to the
0694: * current time in effect, either standard, or DST. However, some
0695: * rules transition at local standard time, and some at a specific
0696: * UTC time. Although it might seem that all times could be
0697: * converted to wall time, thus eliminating the need for this
0698: * parameter, this is not the case.
0699: * @draft ICU 3.6
0700: */
0701: private static final int WALL_TIME = 0, STANDARD_TIME = 1,
0702: UTC_TIME = 2;
0703:
0704: /**
0705: * Compare a given date in the year to a rule. Return 1, 0, or -1, depending
0706: * on whether the date is after, equal to, or before the rule date. The
0707: * millis are compared directly against the ruleMillis, so any
0708: * standard-daylight adjustments must be handled by the caller.
0709: *
0710: * @return 1 if the date is after the rule date, -1 if the date is before
0711: * the rule date, or 0 if the date is equal to the rule date.
0712: */
0713: private int compareToRule(int month, int monthLen,
0714: int prevMonthLen, int dayOfMonth, int dayOfWeek,
0715: int millis, int millisDelta, int ruleMode, int ruleMonth,
0716: int ruleDayOfWeek, int ruleDay, int ruleMillis) {
0717: // Make adjustments for startTimeMode and endTimeMode
0718:
0719: millis += millisDelta;
0720:
0721: while (millis >= MILLIS_PER_DAY) {
0722: millis -= MILLIS_PER_DAY;
0723: ++dayOfMonth;
0724: dayOfWeek = 1 + (dayOfWeek % 7); // dayOfWeek is one-based
0725: if (dayOfMonth > monthLen) {
0726: dayOfMonth = 1;
0727: /* When incrementing the month, it is desirible to overflow
0728: * from DECEMBER to DECEMBER+1, since we use the result to
0729: * compare against a real month. Wraparound of the value
0730: * leads to bug 4173604. */
0731: ++month;
0732: }
0733: }
0734: while (millis < 0) {
0735: millis += MILLIS_PER_DAY;
0736: --dayOfMonth;
0737: dayOfWeek = 1 + ((dayOfWeek + 5) % 7); // dayOfWeek is one-based
0738: if (dayOfMonth < 1) {
0739: dayOfMonth = prevMonthLen;
0740: --month;
0741: }
0742: }
0743:
0744: if (month < ruleMonth)
0745: return -1;
0746: else if (month > ruleMonth)
0747: return 1;
0748:
0749: int ruleDayOfMonth = 0;
0750: switch (ruleMode) {
0751: case DOM_MODE:
0752: ruleDayOfMonth = ruleDay;
0753: break;
0754: case DOW_IN_MONTH_MODE:
0755: // In this case ruleDay is the day-of-week-in-month
0756: if (ruleDay > 0)
0757: ruleDayOfMonth = 1
0758: + (ruleDay - 1)
0759: * 7
0760: + (7 + ruleDayOfWeek - (dayOfWeek - dayOfMonth + 1))
0761: % 7;
0762: else // Assume ruleDay < 0 here
0763: {
0764: ruleDayOfMonth = monthLen
0765: + (ruleDay + 1)
0766: * 7
0767: - (7 + (dayOfWeek + monthLen - dayOfMonth) - ruleDayOfWeek)
0768: % 7;
0769: }
0770: break;
0771: case DOW_GE_DOM_MODE:
0772: ruleDayOfMonth = ruleDay
0773: + (49 + ruleDayOfWeek - ruleDay - dayOfWeek + dayOfMonth)
0774: % 7;
0775: break;
0776: case DOW_LE_DOM_MODE:
0777: ruleDayOfMonth = ruleDay
0778: - (49 - ruleDayOfWeek + ruleDay + dayOfWeek - dayOfMonth)
0779: % 7;
0780: // Note at this point ruleDayOfMonth may be <1, although it will
0781: // be >=1 for well-formed rules.
0782: break;
0783: }
0784:
0785: if (dayOfMonth < ruleDayOfMonth)
0786: return -1;
0787: else if (dayOfMonth > ruleDayOfMonth)
0788: return 1;
0789:
0790: if (millis < ruleMillis) {
0791: return -1;
0792: } else if (millis > ruleMillis) {
0793: return 1;
0794: } else {
0795: return 0;
0796: }
0797: }
0798:
0799: // data needed for streaming mutated SimpleTimeZones in JDK14
0800: private int raw;// the TimeZone's raw GMT offset
0801: private int dst = 3600000;
0802: private STZInfo xinfo = null;
0803: private int startMonth, startDay, startDayOfWeek; // the month, day, DOW, and time DST starts
0804: private int startTime;
0805: private int startTimeMode, endTimeMode; // Mode for startTime, endTime; see TimeMode
0806: private int endMonth, endDay, endDayOfWeek; // the month, day, DOW, and time DST ends
0807: private int endTime;
0808: private int startYear; // the year these DST rules took effect
0809: private boolean useDaylight; // flag indicating whether this TimeZone uses DST
0810: private int startMode, endMode; // flags indicating what kind of rules the DST rules are
0811:
0812: /**
0813: * @internal revisit for ICU 3.6
0814: * @deprecated This API is ICU internal only.
0815: */
0816: public boolean useDaylightTime() {
0817: return useDaylight;
0818: }
0819:
0820: /**
0821: * @internal revisit for ICU 3.6
0822: * @deprecated This API is ICU internal only.
0823: */
0824: public boolean inDaylightTime(Date date) {
0825: GregorianCalendar gc = new GregorianCalendar(this );
0826: gc.setTime(date);
0827: return gc.inDaylightTime();
0828: }
0829:
0830: /**
0831: * @internal revisit for ICU 3.6
0832: * @deprecated This API is ICU internal only.
0833: */
0834: public SimpleTimeZone(int raw, String ID, int startMonth,
0835: int startDay, int startDayOfWeek, int startTime,
0836: int startTimeMode, int endMonth, int endDay,
0837: int endDayOfWeek, int endTime, int endTimeMode, int dst) {
0838: /*this(new java.util.SimpleTimeZone(rawOffsetGMT, ID, savingsStartMonth, savingsStartDay,
0839: savingsStartDayOfWeek, savingsStartTime, savingsEndMonth,
0840: savingsEndDay, savingsEndDayOfWeek, savingsEndTime, savingsDST), ID);*/
0841: construct(raw, startMonth, startDay, startDayOfWeek, startTime,
0842: startTimeMode, endMonth, endDay, endDayOfWeek, endTime,
0843: endTimeMode, dst);
0844: }
0845:
0846: // -------------------------------------
0847: /*
0848: SimpleTimeZone(int rawOffsetGMT, String ID,
0849: int savingsStartMonth, int savingsStartDay,
0850: int savingsStartDayOfWeek, int savingsStartTime,
0851: int savingsEndMonth, int savingsEndDay,
0852: int savingsEndDayOfWeek, int savingsEndTime)
0853: {
0854: construct(rawOffsetGMT,
0855: savingsStartMonth, savingsStartDay, savingsStartDayOfWeek,
0856: savingsStartTime, WALL_TIME,
0857: savingsEndMonth, savingsEndDay, savingsEndDayOfWeek,
0858: savingsEndTime, WALL_TIME,
0859: TimeZone.MILLIS_PER_DAY);
0860: }
0861: */
0862: // -------------------------------------
0863: /*
0864: SimpleTimeZone(int rawOffsetGMT, String ID,
0865: int savingsStartMonth, int savingsStartDay,
0866: int savingsStartDayOfWeek, int savingsStartTime,
0867: int savingsEndMonth, int savingsEndDay,
0868: int savingsEndDayOfWeek, int savingsEndTime,
0869: int savingsDST)
0870: {
0871: construct(rawOffsetGMT,
0872: savingsStartMonth, savingsStartDay, savingsStartDayOfWeek,
0873: savingsStartTime, WALL_TIME,
0874: savingsEndMonth, savingsEndDay, savingsEndDayOfWeek,
0875: savingsEndTime, WALL_TIME,
0876: savingsDST);
0877: }
0878: */
0879: /**
0880: * Internal construction method.
0881: */
0882: private void construct(int raw, int startMonth, int startDay,
0883: int startDayOfWeek, int startTime, int startTimeMode,
0884: int endMonth, int endDay, int endDayOfWeek, int endTime,
0885: int endTimeMode, int dst) {
0886: this .raw = raw;
0887: this .startMonth = startMonth;
0888: this .startDay = startDay;
0889: this .startDayOfWeek = startDayOfWeek;
0890: this .startTime = startTime;
0891: this .startTimeMode = startTimeMode;
0892: this .endMonth = endMonth;
0893: this .endDay = endDay;
0894: this .endDayOfWeek = endDayOfWeek;
0895: this .endTime = endTime;
0896: this .endTimeMode = endTimeMode;
0897: this .dst = dst;
0898: this .startYear = 0;
0899: this .startMode = DOM_MODE;
0900: this .endMode = DOM_MODE;
0901:
0902: decodeRules();
0903:
0904: if (dst <= 0) {
0905: throw new IllegalArgumentException();
0906: }
0907: }
0908:
0909: private void decodeRules() {
0910: decodeStartRule();
0911: decodeEndRule();
0912: }
0913:
0914: /**
0915: * Decode the start rule and validate the parameters. The parameters are
0916: * expected to be in encoded form, which represents the various rule modes
0917: * by negating or zeroing certain values. Representation formats are:
0918: * <p>
0919: * <pre>
0920: * DOW_IN_MONTH DOM DOW>=DOM DOW<=DOM no DST
0921: * ------------ ----- -------- -------- ----------
0922: * month 0..11 same same same don't care
0923: * day -5..5 1..31 1..31 -1..-31 0
0924: * dayOfWeek 1..7 0 -1..-7 -1..-7 don't care
0925: * time 0..ONEDAY same same same don't care
0926: * </pre>
0927: * The range for month does not include UNDECIMBER since this class is
0928: * really specific to GregorianCalendar, which does not use that month.
0929: * The range for time includes ONEDAY (vs. ending at ONEDAY-1) because the
0930: * end rule is an exclusive limit point. That is, the range of times that
0931: * are in DST include those >= the start and < the end. For this reason,
0932: * it should be possible to specify an end of ONEDAY in order to include the
0933: * entire day. Although this is equivalent to time 0 of the following day,
0934: * it's not always possible to specify that, for example, on December 31.
0935: * While arguably the start range should still be 0..ONEDAY-1, we keep
0936: * the start and end ranges the same for consistency.
0937: */
0938: private void decodeStartRule() {
0939:
0940: useDaylight = (boolean) ((startDay != 0) && (endDay != 0) ? true
0941: : false);
0942: if (useDaylight && dst == 0) {
0943: dst = TimeZone.MILLIS_PER_DAY;
0944: }
0945: if (startDay != 0) {
0946: if (startMonth < Calendar.JANUARY
0947: || startMonth > Calendar.DECEMBER) {
0948: throw new IllegalArgumentException();
0949: }
0950: if (startTime < 0 || startTime >= TimeZone.MILLIS_PER_DAY
0951: || startTimeMode < WALL_TIME
0952: || startTimeMode > UTC_TIME) {
0953: throw new IllegalArgumentException();
0954: }
0955: if (startDayOfWeek == 0) {
0956: startMode = DOM_MODE;
0957: } else {
0958: if (startDayOfWeek > 0) {
0959: startMode = DOW_IN_MONTH_MODE;
0960: } else {
0961: startDayOfWeek = (int) -startDayOfWeek;
0962: if (startDay > 0) {
0963: startMode = DOW_GE_DOM_MODE;
0964: } else {
0965: startDay = (int) -startDay;
0966: startMode = DOW_LE_DOM_MODE;
0967: }
0968: }
0969: if (startDayOfWeek > Calendar.SATURDAY) {
0970: throw new IllegalArgumentException();
0971: }
0972: }
0973: if (startMode == DOW_IN_MONTH_MODE) {
0974: if (startDay < -5 || startDay > 5) {
0975: throw new IllegalArgumentException();
0976: }
0977: } else if (startDay < 1
0978: || startDay > staticMonthLength[startMonth]) {
0979: throw new IllegalArgumentException();
0980: }
0981: }
0982: }
0983:
0984: /**
0985: * Decode the end rule and validate the parameters. This method is exactly
0986: * analogous to decodeStartRule().
0987: * @see #decodeStartRule
0988: */
0989: private void decodeEndRule() {
0990: useDaylight = (boolean) ((startDay != 0) && (endDay != 0) ? true
0991: : false);
0992: if (useDaylight && dst == 0) {
0993: dst = TimeZone.MILLIS_PER_DAY;
0994: }
0995: if (endDay != 0) {
0996: if (endMonth < Calendar.JANUARY
0997: || endMonth > Calendar.DECEMBER) {
0998: throw new IllegalArgumentException();
0999: }
1000: if (endTime < 0 || endTime > TimeZone.MILLIS_PER_DAY
1001: || endTimeMode < WALL_TIME
1002: || endTimeMode > UTC_TIME) {
1003: throw new IllegalArgumentException();
1004: }
1005: if (endDayOfWeek == 0) {
1006: endMode = DOM_MODE;
1007: } else {
1008: if (endDayOfWeek > 0) {
1009: endMode = DOW_IN_MONTH_MODE;
1010: } else {
1011: endDayOfWeek = (int) -endDayOfWeek;
1012: if (endDay > 0) {
1013: endMode = DOW_GE_DOM_MODE;
1014: } else {
1015: endDay = (int) -endDay;
1016: endMode = DOW_LE_DOM_MODE;
1017: }
1018: }
1019: if (endDayOfWeek > Calendar.SATURDAY) {
1020: throw new IllegalArgumentException();
1021: }
1022: }
1023: if (endMode == DOW_IN_MONTH_MODE) {
1024: if (endDay < -5 || endDay > 5) {
1025: throw new IllegalArgumentException();
1026: }
1027: } else if (endDay < 1
1028: || endDay > staticMonthLength[endMonth]) {
1029: throw new IllegalArgumentException();
1030: }
1031: }
1032: }
1033:
1034: /**
1035: * Return true if obj is a SimpleTimeZone equivalent to this.
1036: * @return true if obj is a SimpleTimeZone equivalent to this
1037: * @draft ICU 3.4.2
1038: * @provisional This API might change or be removed in a future release.
1039: */
1040: public boolean equals(Object obj) {
1041: if (this == obj)
1042: return true;
1043: if (obj == null || getClass() != obj.getClass())
1044: return false;
1045: SimpleTimeZone that = (SimpleTimeZone) obj;
1046: return raw == that.raw
1047: && useDaylight == that.useDaylight
1048: && idEquals(getID(), that.getID())
1049: && (!useDaylight
1050: // Only check rules if using DST
1051: || (dst == that.dst && startMode == that.startMode
1052: && startMonth == that.startMonth
1053: && startDay == that.startDay
1054: && startDayOfWeek == that.startDayOfWeek
1055: && startTime == that.startTime
1056: && startTimeMode == that.startTimeMode
1057: && endMode == that.endMode
1058: && endMonth == that.endMonth
1059: && endDay == that.endDay
1060: && endDayOfWeek == that.endDayOfWeek
1061: && endTime == that.endTime
1062: && endTimeMode == that.endTimeMode && startYear == that.startYear));
1063:
1064: }
1065:
1066: private boolean idEquals(String id1, String id2) {
1067: if (id1 == null && id2 == null) {
1068: return true;
1069: }
1070: if (id1 != null && id2 != null) {
1071: return id1.equals(id2);
1072: }
1073: return false;
1074: }
1075:
1076: /**
1077: * Return the hash code.
1078: * @return the hash code
1079: * @draft ICU 3.4.2
1080: * @provisional This API might change or be removed in a future release.
1081: */
1082: public int hashCode() {
1083: int ret = (int) (super .hashCode() + raw ^ (raw >>> 8)
1084: + (useDaylight ? 0 : 1));
1085: if (!useDaylight) {
1086: ret += (int) (dst ^ (dst >>> 10) + startMode
1087: ^ (startMode >>> 11) + startMonth
1088: ^ (startMonth >>> 12) + startDay
1089: ^ (startDay >>> 13) + startDayOfWeek
1090: ^ (startDayOfWeek >>> 14) + startTime
1091: ^ (startTime >>> 15) + startTimeMode
1092: ^ (startTimeMode >>> 16) + endMode
1093: ^ (endMode >>> 17) + endMonth ^ (endMonth >>> 18)
1094: + endDay ^ (endDay >>> 19) + endDayOfWeek
1095: ^ (endDayOfWeek >>> 20) + endTime
1096: ^ (endTime >>> 21) + endTimeMode
1097: ^ (endTimeMode >>> 22) + startYear ^ (startYear >>> 23));
1098: }
1099: return ret;
1100: }
1101:
1102: /**
1103: * Return a clone of this time zone.
1104: * @return a clone of this time zone
1105: * @draft ICU 3.4.2
1106: * @provisional This API might change or be removed in a future release.
1107: */
1108: public Object clone() {
1109: SimpleTimeZone clone = new SimpleTimeZone(raw, getID());
1110: clone.startMonth = startMonth;
1111: clone.startDay = startDay;
1112: clone.startDayOfWeek = startDayOfWeek;
1113: clone.startTime = startTime;
1114: clone.startTimeMode = startTimeMode;
1115: clone.endMonth = endMonth;
1116: clone.endDay = endDay;
1117: clone.endDayOfWeek = endDayOfWeek;
1118: clone.endTime = endTime;
1119: clone.endTimeMode = endTimeMode;
1120: clone.dst = dst;
1121: clone.startYear = startYear;
1122: clone.startMode = startMode;
1123: clone.endMode = endMode;
1124: clone.useDaylight = useDaylight;
1125: return clone;
1126: }
1127:
1128: /**
1129: * @internal revisit for ICU 3.6
1130: * @deprecated This API is ICU internal only.
1131: */
1132: public boolean hasSameRules(TimeZone othr) {
1133: if (!(othr instanceof SimpleTimeZone)) {
1134: return false;
1135: }
1136: SimpleTimeZone other = (SimpleTimeZone) othr;
1137: return other != null
1138: && raw == other.raw
1139: && useDaylight == other.useDaylight
1140: && (!useDaylight
1141: // Only check rules if using DST
1142: || (dst == other.dst && startMode == other.startMode
1143: && startMonth == other.startMonth
1144: && startDay == other.startDay
1145: && startDayOfWeek == other.startDayOfWeek
1146: && startTime == other.startTime
1147: && startTimeMode == other.startTimeMode
1148: && endMode == other.endMode
1149: && endMonth == other.endMonth
1150: && endDay == other.endDay
1151: && endDayOfWeek == other.endDayOfWeek
1152: && endTime == other.endTime
1153: && endTimeMode == other.endTimeMode && startYear == other.startYear));
1154: }
1155: }
|