Source Code Cross Referenced for SimpleTimeZone.java in  » 6.0-JDK-Modules » j2me » java » util » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » j2me » java.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * 
0003:         * @(#)SimpleTimeZone.java	1.47 06/10/10
0004:         * 
0005:         * Portions Copyright  2000-2006 Sun Microsystems, Inc. All Rights
0006:         * Reserved.  Use is subject to license terms.
0007:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
0008:         * 
0009:         * This program is free software; you can redistribute it and/or
0010:         * modify it under the terms of the GNU General Public License version
0011:         * 2 only, as published by the Free Software Foundation.
0012:         * 
0013:         * This program is distributed in the hope that it will be useful, but
0014:         * WITHOUT ANY WARRANTY; without even the implied warranty of
0015:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0016:         * General Public License version 2 for more details (a copy is
0017:         * included at /legal/license.txt).
0018:         * 
0019:         * You should have received a copy of the GNU General Public License
0020:         * version 2 along with this work; if not, write to the Free Software
0021:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0022:         * 02110-1301 USA
0023:         * 
0024:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0025:         * Clara, CA 95054 or visit www.sun.com if you need additional
0026:         * information or have any questions.
0027:         */
0028:
0029:        /*
0030:         * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
0031:         * (C) Copyright IBM Corp. 1996 - All Rights Reserved
0032:         *
0033:         *   The original version of this source code and documentation is copyrighted
0034:         * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
0035:         * materials are provided under terms of a License Agreement between Taligent
0036:         * and Sun. This technology is protected by multiple US and International
0037:         * patents. This notice and attribution to Taligent may not be removed.
0038:         *   Taligent is a registered trademark of Taligent, Inc.
0039:         *
0040:         */
0041:
0042:        package java.util;
0043:
0044:        import java.io.ObjectInputStream;
0045:        import java.io.ObjectOutputStream;
0046:        import java.io.IOException;
0047:        import sun.util.calendar.CalendarDate;
0048:        import sun.util.calendar.Gregorian;
0049:
0050:        /**
0051:         * <code>SimpleTimeZone</code> is a concrete subclass of <code>TimeZone</code>
0052:         * that represents a time zone for use with a Gregorian calendar.
0053:         * The class holds an offset from GMT, called <em>raw offset</em>, and start
0054:         * and end rules for a daylight saving time schedule.  Since it only holds
0055:         * single values for each, it cannot handle historical changes in the offset
0056:         * from GMT and the daylight saving schedule, except that the {@link
0057:         * #setStartYear setStartYear} method can specify the year when the daylight
0058:         * saving time schedule starts in effect.
0059:         * <p>
0060:         * To construct a <code>SimpleTimeZone</code> with a daylight saving time
0061:         * schedule, the schedule can be described with a set of rules,
0062:         * <em>start-rule</em> and <em>end-rule</em>. A day when daylight saving time
0063:         * starts or ends is specified by a combination of <em>month</em>,
0064:         * <em>day-of-month</em>, and <em>day-of-week</em> values. The <em>month</em>
0065:         * value is represented by a Calendar {@link Calendar#MONTH MONTH} field
0066:         * value, such as {@link Calendar#MARCH}. The <em>day-of-week</em> value is
0067:         * represented by a Calendar {@link Calendar#DAY_OF_WEEK DAY_OF_WEEK} value,
0068:         * such as {@link Calendar#SUNDAY SUNDAY}. The meanings of value combinations
0069:         * are as follows.
0070:         *
0071:         * <ul>
0072:         * <li><b>Exact day of month</b><br>
0073:         * To specify an exact day of month, set the <em>month</em> and
0074:         * <em>day-of-month</em> to an exact value, and <em>day-of-week</em> to zero. For
0075:         * example, to specify March 1, set the <em>month</em> to {@link Calendar#MARCH
0076:         * MARCH}, <em>day-of-month</em> to 1, and <em>day-of-week</em> to 0.</li>
0077:         *
0078:         * <li><b>Day of week on or after day of month</b><br>
0079:         * To specify a day of week on or after an exact day of month, set the
0080:         * <em>month</em> to an exact month value, <em>day-of-month</em> to the day on
0081:         * or after which the rule is applied, and <em>day-of-week</em> to a {@link
0082:         * Calendar#DAY_OF_WEEK DAY_OF_WEEK} field value. For example, to specify the
0083:         * second Sunday of April, set <em>month</em> to {@link Calendar#APRIL APRIL},
0084:         * <em>day-of-month</em> to 8, and <em>day-of-week</em> to {@link
0085:         * Calendar#SUNDAY SUNDAY}.</li>
0086:         *
0087:         * <li><b>Day of week on or before day of month</b><br>
0088:         * To specify a day of the week on or before an exact day of the month, set
0089:         * <em>day-of-month</em> and <em>day-of-week</em> to a negative value. For
0090:         * example, to specify the last Wednesday on or before the 21st of March, set
0091:         * <em>month</em> to {@link Calendar#MARCH MARCH}, <em>day-of-month</em> is -21
0092:         * and <em>day-of-week</em> is {@link Calendar#WEDNESDAY -WEDNESDAY}. </li>
0093:         *
0094:         * <li><b>Last day-of-week of month</b><br>
0095:         * To specify, the last day-of-week of the month, set <em>day-of-week</em> to a
0096:         * {@link Calendar#DAY_OF_WEEK DAY_OF_WEEK} value and <em>day-of-month</em> to
0097:         * -1. For example, to specify the last Sunday of October, set <em>month</em>
0098:         * to {@link Calendar#OCTOBER OCTOBER}, <em>day-of-week</em> to {@link
0099:         * Calendar#SUNDAY SUNDAY} and <em>day-of-month</em> to -1.  </li>
0100:         *
0101:         * </ul>
0102:         * The time of the day at which daylight saving time starts or ends is
0103:         * specified by a millisecond value within the day. There are three kinds of
0104:         * <em>mode</em>s to specify the time: {@link #WALL_TIME}, {@link
0105:         * #STANDARD_TIME} and {@link #UTC_TIME}. For example, if daylight
0106:         * saving time ends
0107:         * at 2:00 am in the wall clock time, it can be specified by 7200000
0108:         * milliseconds in the {@link #WALL_TIME} mode. In this case, the wall clock time
0109:         * for an <em>end-rule</em> means the same thing as the daylight time.
0110:         * <p>
0111:         * The following are examples of parameters for constructing time zone objects.
0112:         * <pre><code>
0113:         *      // Base GMT offset: -8:00
0114:         *      // DST starts:      at 2:00am in standard time
0115:         *      //                  on the first Sunday in April
0116:         *      // DST ends:        at 2:00am in daylight time
0117:         *      //                  on the last Sunday in October
0118:         *      // Save:            1 hour
0119:         *      SimpleTimeZone(-28800000,
0120:         *                     "America/Los_Angeles",
0121:         *                     Calendar.APRIL, 1, -Calendar.SUNDAY,
0122:         *                     7200000,
0123:         *                     Calendar.OCTOBER, -1, Calendar.SUNDAY,
0124:         *                     7200000,
0125:         *                     3600000)
0126:         *
0127:         *      // Base GMT offset: +1:00
0128:         *      // DST starts:      at 1:00am in UTC time
0129:         *      //                  on the last Sunday in March
0130:         *      // DST ends:        at 1:00am in UTC time
0131:         *      //                  on the last Sunday in October
0132:         *      // Save:            1 hour
0133:         *      SimpleTimeZone(3600000,
0134:         *                     "Europe/Paris",
0135:         *                     Calendar.MARCH, -1, Calendar.SUNDAY,
0136:         *                     3600000, SimpleTimeZone.UTC_TIME,
0137:         *                     Calendar.OCTOBER, -1, Calendar.SUNDAY,
0138:         *                     3600000, SimpleTimeZone.UTC_TIME,
0139:         *                     3600000)
0140:         * </code></pre>
0141:         * These parameter rules are also applicable to the set rule methods, such as
0142:         * <code>setStartRule</code>.
0143:         *
0144:         * @since 1.1
0145:         * @see      Calendar
0146:         * @see      GregorianCalendar
0147:         * @see      TimeZone
0148:         * @version  1.47, 10/10/06
0149:         * @author   David Goldsmith, Mark Davis, Chen-Lieh Huang, Alan Liu
0150:         */
0151:
0152:        public class SimpleTimeZone extends TimeZone {
0153:            /**
0154:             * Constructs a SimpleTimeZone with the given base time zone offset from GMT
0155:             * and time zone ID with no daylight saving time schedule.
0156:             *
0157:             * @param rawOffset  The base time zone offset in milliseconds to GMT.
0158:             * @param ID         The time zone name that is given to this instance.
0159:             */
0160:            public SimpleTimeZone(int rawOffset, String ID) {
0161:                this .rawOffset = rawOffset;
0162:                setID(ID);
0163:                dstSavings = millisPerHour; // In case user sets rules later
0164:            }
0165:
0166:            /**
0167:             * Constructs a SimpleTimeZone with the given base time zone offset from
0168:             * GMT, time zone ID, and rules for starting and ending the daylight
0169:             * time.
0170:             * Both <code>startTime</code> and <code>endTime</code> are specified to be
0171:             * represented in the wall clock time. The amount of daylight saving is
0172:             * assumed to be 3600000 milliseconds (i.e., one hour). This constructor is
0173:             * equivalent to:
0174:             * <pre><code>
0175:             *     SimpleTimeZone(rawOffset,
0176:             *                    ID,
0177:             *                    startMonth,
0178:             *                    startDay,
0179:             *                    startDayOfWeek,
0180:             *                    startTime,
0181:             *                    SimpleTimeZone.{@link #WALL_TIME},
0182:             *                    endMonth,
0183:             *                    endDay,
0184:             *                    endDayOfWeek,
0185:             *                    endTime,
0186:             *                    SimpleTimeZone.{@link #WALL_TIME},
0187:             *                    3600000)
0188:             * </code></pre>
0189:             *
0190:             * @param rawOffset       The given base time zone offset from GMT.
0191:             * @param ID              The time zone ID which is given to this object.
0192:             * @param startMonth      The daylight saving time starting month. Month is
0193:             *                        a {@link Calendar#MONTH MONTH} field value (0-based. e.g., 0
0194:             *                        for January).
0195:             * @param startDay        The day of the month on which the daylight saving time starts.
0196:             *                        See the class description for the special cases of this parameter.
0197:             * @param startDayOfWeek  The daylight saving time starting day-of-week.
0198:             *                        See the class description for the special cases of this parameter.
0199:             * @param startTime       The daylight saving time starting time in local wall clock
0200:             *                        time (in milliseconds within the day), which is local
0201:             *                        standard time in this case.
0202:             * @param endMonth        The daylight saving time ending month. Month is
0203:             *                        a {@link Calendar#MONTH MONTH} field
0204:             *                        value (0-based. e.g., 9 for October).
0205:             * @param endDay          The day of the month on which the daylight saving time ends.
0206:             *                        See the class description for the special cases of this parameter.
0207:             * @param endDayOfWeek    The daylight saving time ending day-of-week.
0208:             *                        See the class description for the special cases of this parameter.
0209:             * @param endTime         The daylight saving ending time in local wall clock time,
0210:             *                        (in milliseconds within the day) which is local daylight
0211:             *                        time in this case.
0212:             * @exception IllegalArgumentException if the month, day, dayOfWeek, or time
0213:             * parameters are out of range for the start or end rule
0214:             */
0215:            public SimpleTimeZone(int rawOffset, String ID, int startMonth,
0216:                    int startDay, int startDayOfWeek, int startTime,
0217:                    int endMonth, int endDay, int endDayOfWeek, int endTime) {
0218:                this (rawOffset, ID, startMonth, startDay, startDayOfWeek,
0219:                        startTime, WALL_TIME, endMonth, endDay, endDayOfWeek,
0220:                        endTime, WALL_TIME, millisPerHour);
0221:            }
0222:
0223:            /**
0224:             * Constructs a SimpleTimeZone with the given base time zone offset from
0225:             * GMT, time zone ID, and rules for starting and ending the daylight
0226:             * time.
0227:             * Both <code>startTime</code> and <code>endTime</code> are assumed to be
0228:             * represented in the wall clock time. This constructor is equivalent to:
0229:             * <pre><code>
0230:             *     SimpleTimeZone(rawOffset,
0231:             *                    ID,
0232:             *                    startMonth,
0233:             *                    startDay,
0234:             *                    startDayOfWeek,
0235:             *                    startTime,
0236:             *                    SimpleTimeZone.{@link #WALL_TIME},
0237:             *                    endMonth,
0238:             *                    endDay,
0239:             *                    endDayOfWeek,
0240:             *                    endTime,
0241:             *                    SimpleTimeZone.{@link #WALL_TIME},
0242:             *                    dstSavings)
0243:             * </code></pre>
0244:             *
0245:             * @param rawOffset       The given base time zone offset from GMT.
0246:             * @param ID              The time zone ID which is given to this object.
0247:             * @param startMonth      The daylight saving time starting month. Month is
0248:             *                        a {@link Calendar#MONTH MONTH} field
0249:             *                        value (0-based. e.g., 0 for January).
0250:             * @param startDay        The day of the month on which the daylight saving time starts.
0251:             *                        See the class description for the special cases of this parameter.
0252:             * @param startDayOfWeek  The daylight saving time starting day-of-week.
0253:             *                        See the class description for the special cases of this parameter.
0254:             * @param startTime       The daylight saving time starting time in local wall clock
0255:             *                        time, which is local standard time in this case.
0256:             * @param endMonth        The daylight saving time ending month. Month is
0257:             *                        a {@link Calendar#MONTH MONTH} field
0258:             *                        value (0-based. e.g., 9 for October).
0259:             * @param endDay          The day of the month on which the daylight saving time ends.
0260:             *                        See the class description for the special cases of this parameter.
0261:             * @param endDayOfWeek    The daylight saving time ending day-of-week.
0262:             *                        See the class description for the special cases of this parameter.
0263:             * @param endTime         The daylight saving ending time in local wall clock time,
0264:             *                        which is local daylight time in this case.
0265:             * @param dstSavings      The amount of time in milliseconds saved during
0266:             *                        daylight saving time.
0267:             * @exception IllegalArgumentException if the month, day, dayOfWeek, or time
0268:             * parameters are out of range for the start or end rule
0269:             * @since 1.2
0270:             */
0271:            public SimpleTimeZone(int rawOffset, String ID, int startMonth,
0272:                    int startDay, int startDayOfWeek, int startTime,
0273:                    int endMonth, int endDay, int endDayOfWeek, int endTime,
0274:                    int dstSavings) {
0275:                this (rawOffset, ID, startMonth, startDay, startDayOfWeek,
0276:                        startTime, WALL_TIME, endMonth, endDay, endDayOfWeek,
0277:                        endTime, WALL_TIME, dstSavings);
0278:            }
0279:
0280:            /**
0281:             * Constructs a SimpleTimeZone with the given base time zone offset from
0282:             * GMT, time zone ID, and rules for starting and ending the daylight
0283:             * time.
0284:             * This constructor takes the full set of the start and end rules
0285:             * parameters, including modes of <code>startTime</code> and
0286:             * <code>endTime</code>. The mode specifies either {@link #WALL_TIME wall
0287:             * time} or {@link #STANDARD_TIME standard time} or {@link #UTC_TIME UTC
0288:             * time}.
0289:             *
0290:             * @param rawOffset       The given base time zone offset from GMT.
0291:             * @param ID              The time zone ID which is given to this object.
0292:             * @param startMonth      The daylight saving time starting month. Month is
0293:             *                        a {@link Calendar#MONTH MONTH} field
0294:             *                        value (0-based. e.g., 0 for January).
0295:             * @param startDay        The day of the month on which the daylight saving time starts.
0296:             *                        See the class description for the special cases of this parameter.
0297:             * @param startDayOfWeek  The daylight saving time starting day-of-week.
0298:             *                        See the class description for the special cases of this parameter.
0299:             * @param startTime       The daylight saving time starting time in the time mode
0300:             *                        specified by <code>startTimeMode</code>.
0301:             * @param startTimeMode   The mode of the start time specified by startTime.
0302:             * @param endMonth        The daylight saving time ending month. Month is
0303:             *                        a {@link Calendar#MONTH MONTH} field
0304:             *                        value (0-based. e.g., 9 for October).
0305:             * @param endDay          The day of the month on which the daylight saving time ends.
0306:             *                        See the class description for the special cases of this parameter.
0307:             * @param endDayOfWeek    The daylight saving time ending day-of-week.
0308:             *                        See the class description for the special cases of this parameter.
0309:             * @param endTime         The daylight saving ending time in time time mode
0310:             *                        specified by <code>endTimeMode</code>.
0311:             * @param endTimeMode     The mode of the end time specified by endTime
0312:             * @param dstSavings      The amount of time in milliseconds saved during
0313:             *                        daylight saving time.
0314:             *
0315:             * @exception IllegalArgumentException if the month, day, dayOfWeek, time more, or
0316:             * time parameters are out of range for the start or end rule, or if a time mode
0317:             * value is invalid.
0318:             *
0319:             * @see #WALL_TIME
0320:             * @see #STANDARD_TIME
0321:             * @see #UTC_TIME
0322:             *
0323:             * @since 1.4
0324:             */
0325:            public SimpleTimeZone(int rawOffset, String ID, int startMonth,
0326:                    int startDay, int startDayOfWeek, int startTime,
0327:                    int startTimeMode, int endMonth, int endDay,
0328:                    int endDayOfWeek, int endTime, int endTimeMode,
0329:                    int dstSavings) {
0330:
0331:                // Workaround fix for 4278609 (JCK failure)
0332:                if (endMonth == Calendar.JANUARY && endDay == 1
0333:                        && endDayOfWeek == 0 && endTime == 0
0334:                        && endTimeMode == WALL_TIME && dstSavings > 0) {
0335:                    endMonth = Calendar.DECEMBER;
0336:                    endDay = 31;
0337:                    endTime = (24 * 60 * 60 * 1000) - dstSavings;
0338:                    endTimeMode = STANDARD_TIME;
0339:                }
0340:
0341:                setID(ID);
0342:                this .rawOffset = rawOffset;
0343:                this .startMonth = startMonth;
0344:                this .startDay = startDay;
0345:                this .startDayOfWeek = startDayOfWeek;
0346:                this .startTime = startTime;
0347:                this .startTimeMode = startTimeMode;
0348:                this .endMonth = endMonth;
0349:                this .endDay = endDay;
0350:                this .endDayOfWeek = endDayOfWeek;
0351:                this .endTime = endTime;
0352:                this .endTimeMode = endTimeMode;
0353:                this .dstSavings = dstSavings;
0354:
0355:                // this.useDaylight is set by decodeRules
0356:                decodeRules();
0357:                if (dstSavings <= 0) {
0358:                    throw new IllegalArgumentException(
0359:                            "Illegal daylight saving value: " + dstSavings);
0360:                }
0361:            }
0362:
0363:            /**
0364:             * Sets the daylight saving time starting year.
0365:             *
0366:             * @param year  The daylight saving starting year.
0367:             */
0368:            public void setStartYear(int year) {
0369:                startYear = year;
0370:            }
0371:
0372:            /**
0373:             * Sets the daylight saving time start rule. For example, if daylight saving
0374:             * time starts on the first Sunday in April at 2 am in local wall clock
0375:             * time, you can set the start rule by calling:
0376:             * <pre><code>setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2*60*60*1000);</code></pre>
0377:             *
0378:             * @param startMonth      The daylight saving time starting month. Month is
0379:             *                        a {@link Calendar#MONTH MONTH} field
0380:             *                        value (0-based. e.g., 0 for January).
0381:             * @param startDay        The day of the month on which the daylight saving time starts.
0382:             *                        See the class description for the special cases of this parameter.
0383:             * @param startDayOfWeek  The daylight saving time starting day-of-week.
0384:             *                        See the class description for the special cases of this parameter.
0385:             * @param startTime       The daylight saving time starting time in local wall clock
0386:             *                        time, which is local standard time in this case.
0387:             * @exception IllegalArgumentException if the <code>startMonth</code>, <code>startDay</code>,
0388:             * <code>startDayOfWeek</code>, or <code>startTime</code> parameters are out of range
0389:             */
0390:            public void setStartRule(int startMonth, int startDay,
0391:                    int startDayOfWeek, int startTime) {
0392:                this .startMonth = startMonth;
0393:                this .startDay = startDay;
0394:                this .startDayOfWeek = startDayOfWeek;
0395:                this .startTime = startTime;
0396:                startTimeMode = WALL_TIME;
0397:                // useDaylight = true; // Set by decodeRules
0398:                decodeStartRule();
0399:            }
0400:
0401:            /**
0402:             * Sets the daylight saving time start rule to a fixed date within a month.
0403:             * This method is equivalent to:
0404:             * <pre><code>setStartRule(startMonth, startDay, 0, startTime)</code></pre>
0405:             *
0406:             * @param startMonth      The daylight saving time starting month. Month is
0407:             *                        a {@link Calendar#MONTH MONTH} field
0408:             *                        value (0-based. e.g., 0 for January).
0409:             * @param startDay        The day of the month on which the daylight saving time starts.
0410:             * @param startTime       The daylight saving time starting time in local wall clock
0411:             *                        time, which is local standard time in this case.
0412:             *                        See the class description for the special cases of this parameter.
0413:             * @exception IllegalArgumentException if the <code>startMonth</code>,
0414:             * <code>startDayOfMonth</code>, or <code>startTime</code> parameters are out of range
0415:             * @since 1.2
0416:             */
0417:            public void setStartRule(int startMonth, int startDay, int startTime) {
0418:                setStartRule(startMonth, startDay, 0, startTime);
0419:            }
0420:
0421:            /**
0422:             * Sets the daylight saving time start rule to a weekday before or after the given date within
0423:             * a month, e.g., the first Monday on or after the 8th.
0424:             *
0425:             * @param startMonth      The daylight saving time starting month. Month is
0426:             *                        a {@link Calendar#MONTH MONTH} field
0427:             *                        value (0-based. e.g., 0 for January).
0428:             * @param startDay        The day of the month on which the daylight saving time starts.
0429:             * @param startDayOfWeek  The daylight saving time starting day-of-week.
0430:             * @param startTime       The daylight saving time starting time in local wall clock
0431:             *                        time, which is local standard time in this case.
0432:             * @param after           If true, this rule selects the first <code>dayOfWeek</code> on or
0433:             *                        <em>after</em> <code>dayOfMonth</code>.  If false, this rule
0434:             *                        selects the last <code>dayOfWeek</code> on or <em>before</em>
0435:             *                        <code>dayOfMonth</code>.
0436:             * @exception IllegalArgumentException if the <code>startMonth</code>, <code>startDay</code>,
0437:             * <code>startDayOfWeek</code>, or <code>startTime</code> parameters are out of range
0438:             * @since 1.2
0439:             */
0440:            public void setStartRule(int startMonth, int startDay,
0441:                    int startDayOfWeek, int startTime, boolean after) {
0442:                // TODO: this method doesn't check the initial values of dayOfMonth or dsyOfWeek.
0443:                if (after) {
0444:                    setStartRule(startMonth, startDay, -startDayOfWeek,
0445:                            startTime);
0446:                } else {
0447:                    setStartRule(startMonth, -startDay, -startDayOfWeek,
0448:                            startTime);
0449:                }
0450:            }
0451:
0452:            /**
0453:             * Sets the daylight saving time end rule. For example, if daylight saving time
0454:             * ends on the last Sunday in October at 2 am in wall clock time,
0455:             * you can set the end rule by calling:
0456:             * <code>setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*60*60*1000);</code>
0457:             *
0458:             * @param endMonth        The daylight saving time ending month. Month is
0459:             *                        a {@link Calendar#MONTH MONTH} field
0460:             *                        value (0-based. e.g., 9 for October).
0461:             * @param endDay          The day of the month on which the daylight saving time ends.
0462:             *                        See the class description for the special cases of this parameter.
0463:             * @param endDayOfWeek    The daylight saving time ending day-of-week.
0464:             *                        See the class description for the special cases of this parameter.
0465:             * @param endTime         The daylight saving ending time in local wall clock time,
0466:             *                        (in milliseconds within the day) which is local daylight
0467:             *                        time in this case.
0468:             * @exception IllegalArgumentException if the <code>endMonth</code>, <code>endDay</code>,
0469:             * <code>endDayOfWeek</code>, or <code>endTime</code> parameters are out of range
0470:             */
0471:            public void setEndRule(int endMonth, int endDay, int endDayOfWeek,
0472:                    int endTime) {
0473:                this .endMonth = endMonth;
0474:                this .endDay = endDay;
0475:                this .endDayOfWeek = endDayOfWeek;
0476:                this .endTime = endTime;
0477:                this .endTimeMode = WALL_TIME;
0478:                // useDaylight = true; // Set by decodeRules
0479:                decodeEndRule();
0480:            }
0481:
0482:            /**
0483:             * Sets the daylight saving time end rule to a fixed date within a month.
0484:             * This method is equivalent to:
0485:             * <pre><code>setEndRule(endMonth, endDay, 0, endTime)</code></pre>
0486:             *
0487:             * @param endMonth        The daylight saving time ending month. Month is
0488:             *                        a {@link Calendar#MONTH MONTH} field
0489:             *                        value (0-based. e.g., 9 for October).
0490:             * @param endDay          The day of the month on which the daylight saving time ends.
0491:             * @param endTime         The daylight saving ending time in local wall clock time,
0492:             *                        (in milliseconds within the day) which is local daylight
0493:             *                        time in this case.
0494:             * @exception IllegalArgumentException the <code>endMonth</code>, <code>endDay</code>,
0495:             * or <code>endTime</code> parameters are out of range
0496:             * @since 1.2
0497:             */
0498:            public void setEndRule(int endMonth, int endDay, int endTime) {
0499:                setEndRule(endMonth, endDay, 0, endTime);
0500:            }
0501:
0502:            /**
0503:             * Sets the daylight saving time end rule to a weekday before or after the given date within
0504:             * a month, e.g., the first Monday on or after the 8th.
0505:             *
0506:             * @param endMonth        The daylight saving time ending month. Month is
0507:             *                        a {@link Calendar#MONTH MONTH} field
0508:             *                        value (0-based. e.g., 9 for October).
0509:             * @param endDay          The day of the month on which the daylight saving time ends.
0510:             * @param endDayOfWeek    The daylight saving time ending day-of-week.
0511:             * @param endTime         The daylight saving ending time in local wall clock time,
0512:             *                        (in milliseconds within the day) which is local daylight
0513:             *                        time in this case.
0514:             * @param after           If true, this rule selects the first <code>endDayOfWeek</code> on
0515:             *                        or <em>after</em> <code>endDay</code>.  If false, this rule
0516:             *                        selects the last <code>endDayOfWeek</code> on or before
0517:             *                        <code>endDay</code> of the month.
0518:             * @exception IllegalArgumentException the <code>endMonth</code>, <code>endDay</code>,
0519:             * <code>endDayOfWeek</code>, or <code>endTime</code> parameters are out of range
0520:             * @since 1.2
0521:             */
0522:            public void setEndRule(int endMonth, int endDay, int endDayOfWeek,
0523:                    int endTime, boolean after) {
0524:                if (after) {
0525:                    setEndRule(endMonth, endDay, -endDayOfWeek, endTime);
0526:                } else {
0527:                    setEndRule(endMonth, -endDay, -endDayOfWeek, endTime);
0528:                }
0529:            }
0530:
0531:            /**
0532:             * Returns the offset of this time zone from UTC at the given
0533:             * time. If daylight saving time is in effect at the given time,
0534:             * the offset value is adjusted with the amount of daylight
0535:             * saving.
0536:             *
0537:             * @param date the time at which the time zone offset is found
0538:             * @return the amount of time in milliseconds to add to UTC to get
0539:             * local time.
0540:             * @since 1.4
0541:             */
0542:            public int getOffset(long date) {
0543:                return getOffsets(date, null);
0544:            }
0545:
0546:            /**
0547:             * @see TimeZone#getOffsets
0548:             */
0549:            int getOffsets(long date, int[] offsets) {
0550:                int offset;
0551:
0552:                calc: {
0553:                    if (!useDaylight) {
0554:                        offset = rawOffset;
0555:                        break calc;
0556:                    }
0557:
0558:                    // get standard local time
0559:                    CalendarDate cdate = Gregorian.getCalendarDate(date
0560:                            + rawOffset);
0561:
0562:                    int year = cdate.getYear();
0563:                    // if it's BC, assume no DST.
0564:                    if (year <= 0) {
0565:                        offset = rawOffset;
0566:                        break calc;
0567:                    }
0568:                    int month = cdate.getMonth();
0569:                    int monthLength = staticMonthLength[month];
0570:                    int prevMonthLength = staticMonthLength[(month + Calendar.DECEMBER) % 12];
0571:                    if (Gregorian.isLeapYear(year)) {
0572:                        if (month == Calendar.FEBRUARY) {
0573:                            ++monthLength;
0574:                        } else if (month == Calendar.MARCH) {
0575:                            ++prevMonthLength;
0576:                        }
0577:                    }
0578:                    offset = getOffset(GregorianCalendar.AD, year, month, cdate
0579:                            .getDate(), cdate.getDayOfWeek(), cdate
0580:                            .getTimeOfDay(), monthLength, prevMonthLength);
0581:                }
0582:
0583:                if (offsets != null) {
0584:                    offsets[0] = rawOffset;
0585:                    offsets[1] = offset - rawOffset;
0586:                }
0587:                return offset;
0588:            }
0589:
0590:            /**
0591:             * Returns the difference in milliseconds between local time and
0592:             * UTC, taking into account both the raw offset and the effect of
0593:             * daylight saving, for the specified date and time.  This method
0594:             * assumes that the start and end month are distinct.  It also
0595:             * uses a default {@link GregorianCalendar} object as its
0596:             * underlying calendar, such as for determining leap years.  Do
0597:             * not use the result of this method with a calendar other than a
0598:             * default <code>GregorianCalendar</code>.
0599:             *
0600:             * <p><em>Note:  In general, clients should use
0601:             * <code>Calendar.get(ZONE_OFFSET) + Calendar.get(DST_OFFSET)</code>
0602:             * instead of calling this method.</em>
0603:             *
0604:             * @param era       The era of the given date.
0605:             * @param year      The year in the given date.
0606:             * @param month     The month in the given date. Month is 0-based. e.g.,
0607:             *                  0 for January.
0608:             * @param day       The day-in-month of the given date.
0609:             * @param dayOfWeek The day-of-week of the given date.
0610:             * @param millis    The milliseconds in day in <em>standard</em> local time.
0611:             * @return          The milliseconds to add to UTC to get local time.
0612:             * @exception       IllegalArgumentException the <code>era</code>,
0613:             *			<code>month</code>, <code>day</code>, <code>dayOfWeek</code>,
0614:             *			or <code>millis</code> parameters are out of range
0615:             */
0616:            public int getOffset(int era, int year, int month, int day,
0617:                    int dayOfWeek, int millis) {
0618:                // Check the month before indexing into staticMonthLength. This
0619:                // duplicates the test that occurs in the 7-argument getOffset(),
0620:                // however, this is unavoidable. We don't mind because this method, in
0621:                // fact, should not be called; internal code should always call the
0622:                // 7-argument getOffset(), and outside code should use Calendar.get(int
0623:                // field) with fields ZONE_OFFSET and DST_OFFSET. We can't get rid of
0624:                // this method because it's public API. - liu 8/10/98
0625:                if (month < Calendar.JANUARY || month > Calendar.DECEMBER) {
0626:                    throw new IllegalArgumentException("Illegal month " + month);
0627:                }
0628:
0629:                int monthLength, prevMonthLength;
0630:                if ((era == GregorianCalendar.AD) && Gregorian.isLeapYear(year)) {
0631:                    monthLength = staticLeapMonthLength[month];
0632:                    prevMonthLength = (month > 1) ? staticLeapMonthLength[month - 1]
0633:                            : 31;
0634:                } else {
0635:                    monthLength = staticMonthLength[month];
0636:                    prevMonthLength = (month > 1) ? staticMonthLength[month - 1]
0637:                            : 31;
0638:                }
0639:
0640:                if (true) {
0641:                    /* Use this parameter checking code for normal operation.  Only one
0642:                     * of these two blocks should actually get compiled into the class
0643:                     * file.  */
0644:                    if ((era != GregorianCalendar.AD && era != GregorianCalendar.BC)
0645:                            || month < Calendar.JANUARY
0646:                            || month > Calendar.DECEMBER
0647:                            || day < 1
0648:                            || day > monthLength
0649:                            || dayOfWeek < Calendar.SUNDAY
0650:                            || dayOfWeek > Calendar.SATURDAY
0651:                            || millis < 0
0652:                            || millis >= millisPerDay) {
0653:                        throw new IllegalArgumentException();
0654:                    }
0655:                } else {
0656:                    /* This parameter checking code is better for debugging, but
0657:                     * overkill for normal operation.  Only one of these two blocks
0658:                     * should actually get compiled into the class file.  */
0659:                    if (era != GregorianCalendar.AD
0660:                            && era != GregorianCalendar.BC) {
0661:                        throw new IllegalArgumentException("Illegal era " + era);
0662:                    }
0663:                    if (month < Calendar.JANUARY || month > Calendar.DECEMBER) {
0664:                        throw new IllegalArgumentException("Illegal month "
0665:                                + month);
0666:                    }
0667:                    if (day < 1 || day > monthLength) {
0668:                        throw new IllegalArgumentException("Illegal day " + day);
0669:                    }
0670:                    if (dayOfWeek < Calendar.SUNDAY
0671:                            || dayOfWeek > Calendar.SATURDAY) {
0672:                        throw new IllegalArgumentException(
0673:                                "Illegal day of week " + dayOfWeek);
0674:                    }
0675:                    if (millis < 0 || millis >= millisPerDay) {
0676:                        throw new IllegalArgumentException("Illegal millis "
0677:                                + millis);
0678:                    }
0679:                }
0680:
0681:                return getOffset(era, year, month, day, dayOfWeek, millis,
0682:                        monthLength, prevMonthLength);
0683:            }
0684:
0685:            /**
0686:             * Gets offset, for current date, modified in case of
0687:             * daylight saving time. This is the offset to add <em>to</em> UTC to get local time.
0688:             * Gets the time zone offset, for current date, modified in case of daylight
0689:             * saving time. This is the offset to add to UTC to get local time. Assume
0690:             * that the start and end month are distinct.
0691:             * @param era           The era of the given date.
0692:             * @param year          The year in the given date.
0693:             * @param month         The month in the given date. Month is 0-based. e.g.,
0694:             *                      0 for January.
0695:             * @param day           The day-in-month of the given date.
0696:             * @param dayOfWeek     The day-of-week of the given date.
0697:             * @param millis        The milliseconds in day in <em>standard</em> local time.
0698:             * @param monthLength   The length of the given month in days.
0699:             * @param prevMonthLength The length of the previous month in days.
0700:             * @return              The offset to add to GMT to get local time.
0701:             * @exception IllegalArgumentException the era, month, day,
0702:             * dayOfWeek, millis, or monthLength parameters are out of range
0703:             */
0704:            private int getOffset(int era, int year, int month, int day,
0705:                    int dayOfWeek, int millis, int monthLength,
0706:                    int prevMonthLength) {
0707:                int result = rawOffset;
0708:
0709:                // Bail out if we are before the onset of daylight saving time
0710:                if (!useDaylight || year < startYear
0711:                        || era != GregorianCalendar.AD) {
0712:                    return result;
0713:                }
0714:
0715:                // Check for southern hemisphere.  We assume that the start and end
0716:                // month are different.
0717:                boolean southern = (startMonth > endMonth);
0718:
0719:                // Compare the date to the starting and ending rules.+1 = date>rule, -1
0720:                // = date<rule, 0 = date==rule.
0721:                int startCompare = compareToRule(month, monthLength,
0722:                        prevMonthLength, day, dayOfWeek, millis,
0723:                        startTimeMode == UTC_TIME ? -rawOffset : 0, startMode,
0724:                        startMonth, startDayOfWeek, startDay, startTime);
0725:                int endCompare = 0;
0726:
0727:                /* We don't always have to compute endCompare.  For many instances,
0728:                 * startCompare is enough to determine if we are in DST or not.  In the
0729:                 * northern hemisphere, if we are before the start rule, we can't have
0730:                 * DST.  In the southern hemisphere, if we are after the start rule, we
0731:                 * must have DST.  This is reflected in the way the next if statement
0732:                 * (not the one immediately following) short circuits. */
0733:                if (southern != (startCompare >= 0)) {
0734:                    /* For the ending rule comparison, we add the dstSavings to the millis
0735:                     * passed in to convert them from standard to wall time.  We then must
0736:                     * normalize the millis to the range 0..millisPerDay-1. */
0737:                    endCompare = compareToRule(
0738:                            month,
0739:                            monthLength,
0740:                            prevMonthLength,
0741:                            day,
0742:                            dayOfWeek,
0743:                            millis,
0744:                            endTimeMode == WALL_TIME ? dstSavings
0745:                                    : (endTimeMode == UTC_TIME ? -rawOffset : 0),
0746:                            endMode, endMonth, endDayOfWeek, endDay, endTime);
0747:                }
0748:
0749:                // Check for both the northern and southern hemisphere cases.  We
0750:                // assume that in the northern hemisphere, the start rule is before the
0751:                // end rule within the calendar year, and vice versa for the southern
0752:                // hemisphere.
0753:                if ((!southern && (startCompare >= 0 && endCompare < 0))
0754:                        || (southern && (startCompare >= 0 || endCompare < 0))) {
0755:                    result += dstSavings;
0756:                }
0757:
0758:                return result;
0759:            }
0760:
0761:            /**
0762:             * Compares the given date in the year to the given rule and returns 1, 0,
0763:             * or -1, depending on whether the date is after, equal to, or before the
0764:             * rule date. The millis are compared directly against the ruleMillis, so
0765:             * any standard-daylight adjustments must be handled by the caller.
0766:             *
0767:             * @return  1 if the date is after the rule date, -1 if the date is before
0768:             *          the rule date, or 0 if the date is equal to the rule date.
0769:             */
0770:            private static int compareToRule(int month, int monthLen,
0771:                    int prevMonthLen, int dayOfMonth, int dayOfWeek,
0772:                    int millis, int millisDelta, int ruleMode, int ruleMonth,
0773:                    int ruleDayOfWeek, int ruleDay, int ruleMillis) {
0774:                // Make adjustments for startTimeMode and endTimeMode
0775:                millis += millisDelta;
0776:                while (millis >= millisPerDay) {
0777:                    millis -= millisPerDay;
0778:                    ++dayOfMonth;
0779:                    dayOfWeek = 1 + (dayOfWeek % 7); // dayOfWeek is one-based
0780:                    if (dayOfMonth > monthLen) {
0781:                        dayOfMonth = 1;
0782:                        /* When incrementing the month, it is desirable to overflow
0783:                         * from DECEMBER to DECEMBER+1, since we use the result to
0784:                         * compare against a real month. Wraparound of the value
0785:                         * leads to bug 4173604. */
0786:                        ++month;
0787:                    }
0788:                }
0789:                while (millis < 0) {
0790:                    millis += millisPerDay;
0791:                    --dayOfMonth;
0792:                    dayOfWeek = 1 + ((dayOfWeek + 5) % 7); // dayOfWeek is one-based
0793:                    if (dayOfMonth < 1) {
0794:                        dayOfMonth = prevMonthLen;
0795:                        --month;
0796:                    }
0797:                }
0798:
0799:                if (month < ruleMonth) {
0800:                    return -1;
0801:                }
0802:                if (month > ruleMonth) {
0803:                    return 1;
0804:                }
0805:
0806:                int ruleDayOfMonth = 0;
0807:                switch (ruleMode) {
0808:                case DOM_MODE:
0809:                    ruleDayOfMonth = ruleDay;
0810:                    break;
0811:
0812:                case DOW_IN_MONTH_MODE:
0813:                    // In this case ruleDay is the day-of-week-in-month
0814:                    if (ruleDay > 0) {
0815:                        ruleDayOfMonth = 1
0816:                                + (ruleDay - 1)
0817:                                * 7
0818:                                + (7 + ruleDayOfWeek - (dayOfWeek - dayOfMonth + 1))
0819:                                % 7;
0820:                    } else {
0821:                        // Assume ruleDay < 0 here
0822:                        ruleDayOfMonth = monthLen
0823:                                + (ruleDay + 1)
0824:                                * 7
0825:                                - (7 + (dayOfWeek + monthLen - dayOfMonth) - ruleDayOfWeek)
0826:                                % 7;
0827:                    }
0828:                    break;
0829:
0830:                case DOW_GE_DOM_MODE:
0831:                    ruleDayOfMonth = ruleDay
0832:                            + (49 + ruleDayOfWeek - ruleDay - dayOfWeek + dayOfMonth)
0833:                            % 7;
0834:                    break;
0835:
0836:                case DOW_LE_DOM_MODE:
0837:                    ruleDayOfMonth = ruleDay
0838:                            - (49 - ruleDayOfWeek + ruleDay + dayOfWeek - dayOfMonth)
0839:                            % 7;
0840:                    // Note at this point ruleDayOfMonth may be <1, although it will
0841:                    // be >=1 for well-formed rules.
0842:                    break;
0843:                }
0844:
0845:                if (dayOfMonth < ruleDayOfMonth) {
0846:                    return -1;
0847:                }
0848:                if (dayOfMonth > ruleDayOfMonth) {
0849:                    return 1;
0850:                }
0851:
0852:                if (millis < ruleMillis) {
0853:                    return -1;
0854:                }
0855:                if (millis > ruleMillis) {
0856:                    return 1;
0857:                }
0858:                return 0;
0859:            }
0860:
0861:            /**
0862:             * Gets the GMT offset for this time zone.
0863:             * @return the GMT offset value in milliseconds
0864:             * @see #setRawOffset
0865:             */
0866:            public int getRawOffset() {
0867:                // The given date will be taken into account while
0868:                // we have the historical time zone data in place.
0869:                return rawOffset;
0870:            }
0871:
0872:            /**
0873:             * Sets the base time zone offset to GMT.
0874:             * This is the offset to add to UTC to get local time.
0875:             * @see #getRawOffset
0876:             */
0877:            public void setRawOffset(int offsetMillis) {
0878:                this .rawOffset = offsetMillis;
0879:            }
0880:
0881:            /**
0882:             * Sets the amount of time in milliseconds that the clock is advanced
0883:             * during daylight saving time.
0884:             * @param millisSavedDuringDST the number of milliseconds the time is
0885:             * advanced with respect to standard time when the daylight saving time rules
0886:             * are in effect. A positive number, typically one hour (3600000).
0887:             * @see #getDSTSavings
0888:             * @since 1.2
0889:             */
0890:            public void setDSTSavings(int millisSavedDuringDST) {
0891:                if (millisSavedDuringDST <= 0) {
0892:                    throw new IllegalArgumentException(
0893:                            "Illegal daylight saving value: "
0894:                                    + millisSavedDuringDST);
0895:                }
0896:                dstSavings = millisSavedDuringDST;
0897:            }
0898:
0899:            /**
0900:             * Returns the amount of time in milliseconds that the clock is
0901:             * advanced during daylight saving time.
0902:             *
0903:             * @return the number of milliseconds the time is advanced with
0904:             * respect to standard time when the daylight saving rules are in
0905:             * effect, or 0 (zero) if this time zone doesn't observe daylight
0906:             * saving time.
0907:             *
0908:             * @see #setDSTSavings
0909:             * @since 1.2
0910:             */
0911:            public int getDSTSavings() {
0912:                if (useDaylight) {
0913:                    return dstSavings;
0914:                }
0915:                return 0;
0916:            }
0917:
0918:            /**
0919:             * Queries if this time zone uses daylight saving time.
0920:             * @return true if this time zone uses daylight saving time;
0921:             * false otherwise.
0922:             */
0923:            public boolean useDaylightTime() {
0924:                return useDaylight;
0925:            }
0926:
0927:            /**
0928:             * Queries if the given date is in daylight saving time.
0929:             * @return true if daylight saving time is in effective at the
0930:             * given date; false otherwise.
0931:             */
0932:            public boolean inDaylightTime(Date date) {
0933:                return (getOffset(date.getTime()) != rawOffset);
0934:            }
0935:
0936:            /**
0937:             * Returns a clone of this <code>SimpleTimeZone</code> instance.
0938:             * @return a clone of this instance.
0939:             */
0940:            public Object clone() {
0941:                return super .clone();
0942:            }
0943:
0944:            /**
0945:             * Generates the hash code for the SimpleDateFormat object.
0946:             * @return the hash code for this object
0947:             */
0948:            public synchronized int hashCode() {
0949:                return startMonth ^ startDay ^ startDayOfWeek ^ startTime
0950:                        ^ endMonth ^ endDay ^ endDayOfWeek ^ endTime
0951:                        ^ rawOffset;
0952:            }
0953:
0954:            /**
0955:             * Compares the equality of two <code>SimpleTimeZone</code> objects.
0956:             *
0957:             * @param obj  The <code>SimpleTimeZone</code> object to be compared with.
0958:             * @return     True if the given <code>obj</code> is the same as this
0959:             *		   <code>SimpleTimeZone</code> object; false otherwise.
0960:             */
0961:            public boolean equals(Object obj) {
0962:                if (this  == obj) {
0963:                    return true;
0964:                }
0965:                if (!(obj instanceof  SimpleTimeZone)) {
0966:                    return false;
0967:                }
0968:
0969:                SimpleTimeZone that = (SimpleTimeZone) obj;
0970:
0971:                return getID().equals(that.getID()) && hasSameRules(that);
0972:            }
0973:
0974:            /**
0975:             * Returns true if this zone has the same rules and offset as another zone.
0976:             * @param other the TimeZone object to be compared with
0977:             * @return true if the given zone is a SimpleTimeZone and has the
0978:             * same rules and offset as this one
0979:             * @since 1.2
0980:             */
0981:            public boolean hasSameRules(TimeZone other) {
0982:                if (this  == other) {
0983:                    return true;
0984:                }
0985:                if (!(other instanceof  SimpleTimeZone)) {
0986:                    return false;
0987:                }
0988:                SimpleTimeZone that = (SimpleTimeZone) other;
0989:                return rawOffset == that.rawOffset
0990:                        && useDaylight == that.useDaylight && (!useDaylight
0991:                        // Only check rules if using DST
0992:                        || (dstSavings == that.dstSavings
0993:                                && startMode == that.startMode
0994:                                && startMonth == that.startMonth
0995:                                && startDay == that.startDay
0996:                                && startDayOfWeek == that.startDayOfWeek
0997:                                && startTime == that.startTime
0998:                                && startTimeMode == that.startTimeMode
0999:                                && endMode == that.endMode
1000:                                && endMonth == that.endMonth
1001:                                && endDay == that.endDay
1002:                                && endDayOfWeek == that.endDayOfWeek
1003:                                && endTime == that.endTime
1004:                                && endTimeMode == that.endTimeMode && startYear == that.startYear));
1005:            }
1006:
1007:            /**
1008:             * Returns a string representation of this time zone.
1009:             * @return a string representation of this time zone.
1010:             */
1011:            public String toString() {
1012:                return getClass().getName() + "[id=" + getID() + ",offset="
1013:                        + rawOffset + ",dstSavings=" + dstSavings
1014:                        + ",useDaylight=" + useDaylight + ",startYear="
1015:                        + startYear + ",startMode=" + startMode
1016:                        + ",startMonth=" + startMonth + ",startDay=" + startDay
1017:                        + ",startDayOfWeek=" + startDayOfWeek + ",startTime="
1018:                        + startTime + ",startTimeMode=" + startTimeMode
1019:                        + ",endMode=" + endMode + ",endMonth=" + endMonth
1020:                        + ",endDay=" + endDay + ",endDayOfWeek=" + endDayOfWeek
1021:                        + ",endTime=" + endTime + ",endTimeMode=" + endTimeMode
1022:                        + ']';
1023:            }
1024:
1025:            // =======================privates===============================
1026:
1027:            /**
1028:             * The month in which daylight saving time starts.  This value must be
1029:             * between <code>Calendar.JANUARY</code> and
1030:             * <code>Calendar.DECEMBER</code> inclusive.  This value must not equal
1031:             * <code>endMonth</code>.
1032:             * <p>If <code>useDaylight</code> is false, this value is ignored.
1033:             * @serial
1034:             */
1035:            private int startMonth;
1036:
1037:            /**
1038:             * This field has two possible interpretations:
1039:             * <dl>
1040:             * <dt><code>startMode == DOW_IN_MONTH</code></dt>
1041:             * <dd>
1042:             * <code>startDay</code> indicates the day of the month of
1043:             * <code>startMonth</code> on which daylight
1044:             * saving time starts, from 1 to 28, 30, or 31, depending on the
1045:             * <code>startMonth</code>.
1046:             * </dd>
1047:             * <dt><code>startMode != DOW_IN_MONTH</code></dt>
1048:             * <dd>
1049:             * <code>startDay</code> indicates which <code>startDayOfWeek</code> in th
1050:             * month <code>startMonth</code> daylight
1051:             * saving time starts on.  For example, a value of +1 and a
1052:             * <code>startDayOfWeek</code> of <code>Calendar.SUNDAY</code> indicates the
1053:             * first Sunday of <code>startMonth</code>.  Likewise, +2 would indicate the
1054:             * second Sunday, and -1 the last Sunday.  A value of 0 is illegal.
1055:             * </dd>
1056:             * </ul>
1057:             * <p>If <code>useDaylight</code> is false, this value is ignored.
1058:             * @serial
1059:             */
1060:            private int startDay;
1061:
1062:            /**
1063:             * The day of the week on which daylight saving time starts.  This value
1064:             * must be between <code>Calendar.SUNDAY</code> and
1065:             * <code>Calendar.SATURDAY</code> inclusive.
1066:             * <p>If <code>useDaylight</code> is false or
1067:             * <code>startMode == DAY_OF_MONTH</code>, this value is ignored.
1068:             * @serial
1069:             */
1070:            private int startDayOfWeek;
1071:
1072:            /**
1073:             * The time in milliseconds after midnight at which daylight saving
1074:             * time starts.  This value is expressed as wall time, standard time,
1075:             * or UTC time, depending on the setting of <code>startTimeMode</code>.
1076:             * <p>If <code>useDaylight</code> is false, this value is ignored.
1077:             * @serial
1078:             */
1079:            private int startTime;
1080:
1081:            /**
1082:             * The format of startTime, either WALL_TIME, STANDARD_TIME, or UTC_TIME.
1083:             * @serial
1084:             * @since 1.3
1085:             */
1086:            private int startTimeMode;
1087:
1088:            /**
1089:             * The month in which daylight saving time ends.  This value must be
1090:             * between <code>Calendar.JANUARY</code> and
1091:             * <code>Calendar.UNDECIMBER</code>.  This value must not equal
1092:             * <code>startMonth</code>.
1093:             * <p>If <code>useDaylight</code> is false, this value is ignored.
1094:             * @serial
1095:             */
1096:            private int endMonth;
1097:
1098:            /**
1099:             * This field has two possible interpretations:
1100:             * <dl>
1101:             * <dt><code>endMode == DOW_IN_MONTH</code></dt>
1102:             * <dd>
1103:             * <code>endDay</code> indicates the day of the month of
1104:             * <code>endMonth</code> on which daylight
1105:             * saving time ends, from 1 to 28, 30, or 31, depending on the
1106:             * <code>endMonth</code>.
1107:             * </dd>
1108:             * <dt><code>endMode != DOW_IN_MONTH</code></dt>
1109:             * <dd>
1110:             * <code>endDay</code> indicates which <code>endDayOfWeek</code> in th
1111:             * month <code>endMonth</code> daylight
1112:             * saving time ends on.  For example, a value of +1 and a
1113:             * <code>endDayOfWeek</code> of <code>Calendar.SUNDAY</code> indicates the
1114:             * first Sunday of <code>endMonth</code>.  Likewise, +2 would indicate the
1115:             * second Sunday, and -1 the last Sunday.  A value of 0 is illegal.
1116:             * </dd>
1117:             * </ul>
1118:             * <p>If <code>useDaylight</code> is false, this value is ignored.
1119:             * @serial
1120:             */
1121:            private int endDay;
1122:
1123:            /**
1124:             * The day of the week on which daylight saving time ends.  This value
1125:             * must be between <code>Calendar.SUNDAY</code> and
1126:             * <code>Calendar.SATURDAY</code> inclusive.
1127:             * <p>If <code>useDaylight</code> is false or
1128:             * <code>endMode == DAY_OF_MONTH</code>, this value is ignored.
1129:             * @serial
1130:             */
1131:            private int endDayOfWeek;
1132:
1133:            /**
1134:             * The time in milliseconds after midnight at which daylight saving
1135:             * time ends.  This value is expressed as wall time, standard time,
1136:             * or UTC time, depending on the setting of <code>endTimeMode</code>.
1137:             * <p>If <code>useDaylight</code> is false, this value is ignored.
1138:             * @serial
1139:             */
1140:            private int endTime;
1141:
1142:            /**
1143:             * The format of endTime, either WALL_TIME, STANDARD_TIME, or UTC_TIME.
1144:             * @serial
1145:             * @since 1.3
1146:             */
1147:            private int endTimeMode;
1148:
1149:            /**
1150:             * The year in which daylight saving time is first observed.  This is an AD
1151:             * value.  If this value is less than 1 then daylight saving time is observed
1152:             * for all AD years.
1153:             * <p>If <code>useDaylight</code> is false, this value is ignored.
1154:             * @serial
1155:             */
1156:            private int startYear;
1157:
1158:            /**
1159:             * The offset in milliseconds between this zone and GMT.  Negative offsets
1160:             * are to the west of Greenwich.  To obtain local <em>standard</em> time,
1161:             * add the offset to GMT time.  To obtain local wall time it may also be
1162:             * necessary to add <code>dstSavings</code>.
1163:             * @serial
1164:             */
1165:            private int rawOffset;
1166:
1167:            /**
1168:             * A boolean value which is true if and only if this zone uses daylight
1169:             * saving time.  If this value is false, several other fields are ignored.
1170:             * @serial
1171:             */
1172:            private boolean useDaylight = false; // indicate if this time zone uses DST
1173:
1174:            private static final int millisPerHour = 60 * 60 * 1000;
1175:            private static final int millisPerDay = 24 * millisPerHour;
1176:
1177:            /**
1178:             * This field was serialized in JDK 1.1, so we have to keep it that way
1179:             * to maintain serialization compatibility. However, there's no need to
1180:             * recreate the array each time we create a new time zone.
1181:             * @serial An array of bytes containing the values {31, 28, 31, 30, 31, 30,
1182:             * 31, 31, 30, 31, 30, 31}.  This is ignored as of the Java 2 platform v1.2, however, it must
1183:             * be streamed out for compatibility with JDK 1.1.
1184:             */
1185:            private final byte monthLength[] = staticMonthLength;
1186:            private final static byte staticMonthLength[] = { 31, 28, 31, 30,
1187:                    31, 30, 31, 31, 30, 31, 30, 31 };
1188:            private final static byte staticLeapMonthLength[] = { 31, 29, 31,
1189:                    30, 31, 30, 31, 31, 30, 31, 30, 31 };
1190:
1191:            /**
1192:             * Variables specifying the mode of the start rule.  Takes the following
1193:             * values:
1194:             * <dl>
1195:             * <dt><code>DOM_MODE</code></dt>
1196:             * <dd>
1197:             * Exact day of week; e.g., March 1.
1198:             * </dd>
1199:             * <dt><code>DOW_IN_MONTH_MODE</code></dt>    
1200:             * <dd>
1201:             * Day of week in month; e.g., last Sunday in March.
1202:             * </dd>
1203:             * <dt><code>DOW_GE_DOM_MODE</code></dt>
1204:             * <dd>
1205:             * Day of week after day of month; e.g., Sunday on or after March 15.
1206:             * </dd>
1207:             * <dt><code>DOW_LE_DOM_MODE</code></dt>
1208:             * <dd>
1209:             * Day of week before day of month; e.g., Sunday on or before March 15.
1210:             * </dd>
1211:             * </dl>
1212:             * The setting of this field affects the interpretation of the
1213:             * <code>startDay</code> field.
1214:             * <p>If <code>useDaylight</code> is false, this value is ignored.
1215:             * @serial
1216:             * @since 1.1.4
1217:             */
1218:            private int startMode;
1219:
1220:            /**
1221:             * Variables specifying the mode of the end rule.  Takes the following
1222:             * values:
1223:             * <dl>
1224:             * <dt><code>DOM_MODE</code></dt>
1225:             * <dd>
1226:             * Exact day of week; e.g., March 1.
1227:             * </dd>
1228:             * <dt><code>DOW_IN_MONTH_MODE</code></dt>    
1229:             * <dd>
1230:             * Day of week in month; e.g., last Sunday in March.
1231:             * </dd>
1232:             * <dt><code>DOW_GE_DOM_MODE</code></dt>
1233:             * <dd>
1234:             * Day of week after day of month; e.g., Sunday on or after March 15.
1235:             * </dd>
1236:             * <dt><code>DOW_LE_DOM_MODE</code></dt>
1237:             * <dd>
1238:             * Day of week before day of month; e.g., Sunday on or before March 15.
1239:             * </dd>
1240:             * </dl>
1241:             * The setting of this field affects the interpretation of the
1242:             * <code>endDay</code> field.
1243:             * <p>If <code>useDaylight</code> is false, this value is ignored.
1244:             * @serial
1245:             * @since 1.1.4
1246:             */
1247:            private int endMode;
1248:
1249:            /**
1250:             * A positive value indicating the amount of time saved during DST in
1251:             * milliseconds.
1252:             * Typically one hour (3600000); sometimes 30 minutes (1800000).
1253:             * <p>If <code>useDaylight</code> is false, this value is ignored.
1254:             * @serial
1255:             * @since 1.1.4
1256:             */
1257:            private int dstSavings;
1258:
1259:            /**
1260:             * Constants specifying values of startMode and endMode.
1261:             */
1262:            private static final int DOM_MODE = 1; // Exact day of month, "Mar 1"
1263:            private static final int DOW_IN_MONTH_MODE = 2; // Day of week in month, "lastSun"
1264:            private static final int DOW_GE_DOM_MODE = 3; // Day of week after day of month, "Sun>=15"
1265:            private static final int DOW_LE_DOM_MODE = 4; // Day of week before day of month, "Sun<=21"
1266:
1267:            /**
1268:             * Constant for a mode of start or end time specified as wall clock
1269:             * time.  Wall clock time is standard time for the onset rule, and
1270:             * daylight time for the end rule.
1271:             * @since 1.4
1272:             */
1273:            public static final int WALL_TIME = 0; // Zero for backward compatibility
1274:
1275:            /**
1276:             * Constant for a mode of start or end time specified as standard time.
1277:             * @since 1.4
1278:             */
1279:            public static final int STANDARD_TIME = 1;
1280:
1281:            /**
1282:             * Constant for a mode of start or end time specified as UTC. European
1283:             * Union rules are specified as UTC time, for example.
1284:             * @since 1.4
1285:             */
1286:            public static final int UTC_TIME = 2;
1287:
1288:            // Proclaim compatibility with 1.1
1289:            static final long serialVersionUID = -403250971215465050L;
1290:
1291:            // the internal serial version which says which version was written
1292:            // - 0 (default) for version up to JDK 1.1.3
1293:            // - 1 for version from JDK 1.1.4, which includes 3 new fields
1294:            // - 2 for JDK 1.3, which includes 2 new fields
1295:            static final int currentSerialVersion = 2;
1296:
1297:            /**
1298:             * The version of the serialized data on the stream.  Possible values:
1299:             * <dl>
1300:             * <dt><b>0</b> or not present on stream</dt>
1301:             * <dd>
1302:             * JDK 1.1.3 or earlier.
1303:             * </dd>
1304:             * <dt><b>1</b></dt>
1305:             * <dd>
1306:             * JDK 1.1.4 or later.  Includes three new fields: <code>startMode</code>,
1307:             * <code>endMode</code>, and <code>dstSavings</code>.
1308:             * </dd>
1309:             * <dt><b>2</b></dt>
1310:             * <dd>
1311:             * JDK 1.3 or later.  Includes two new fields: <code>startTimeMode</code>
1312:             * and <code>endTimeMode</code>.
1313:             * </dd>
1314:             * </dl>
1315:             * When streaming out this class, the most recent format
1316:             * and the highest allowable <code>serialVersionOnStream</code>
1317:             * is written.
1318:             * @serial
1319:             * @since 1.1.4
1320:             */
1321:            private int serialVersionOnStream = currentSerialVersion;
1322:
1323:            //----------------------------------------------------------------------
1324:            // Rule representation
1325:            //
1326:            // We represent the following flavors of rules:
1327:            //       5        the fifth of the month
1328:            //       lastSun  the last Sunday in the month
1329:            //       lastMon  the last Monday in the month
1330:            //       Sun>=8   first Sunday on or after the eighth
1331:            //       Sun<=25  last Sunday on or before the 25th
1332:            // This is further complicated by the fact that we need to remain
1333:            // backward compatible with the 1.1.  Finally, we need to minimize
1334:            // API changes.  In order to satisfy these requirements, we support
1335:            // three representation systems, and we translate between them.
1336:            //
1337:            // INTERNAL REPRESENTATION
1338:            // This is the format SimpleTimeZone objects take after construction or
1339:            // streaming in is complete.  Rules are represented directly, using an
1340:            // unencoded format.  We will discuss the start rule only below; the end
1341:            // rule is analogous.
1342:            //   startMode      Takes on enumerated values DAY_OF_MONTH,
1343:            //                  DOW_IN_MONTH, DOW_AFTER_DOM, or DOW_BEFORE_DOM.
1344:            //   startDay       The day of the month, or for DOW_IN_MONTH mode, a
1345:            //                  value indicating which DOW, such as +1 for first,
1346:            //                  +2 for second, -1 for last, etc.
1347:            //   startDayOfWeek The day of the week.  Ignored for DAY_OF_MONTH.
1348:            //
1349:            // ENCODED REPRESENTATION
1350:            // This is the format accepted by the constructor and by setStartRule()
1351:            // and setEndRule().  It uses various combinations of positive, negative,
1352:            // and zero values to encode the different rules.  This representation
1353:            // allows us to specify all the different rule flavors without altering
1354:            // the API.
1355:            //   MODE              startMonth    startDay    startDayOfWeek
1356:            //   DOW_IN_MONTH_MODE >=0           !=0         >0
1357:            //   DOM_MODE          >=0           >0          ==0
1358:            //   DOW_GE_DOM_MODE   >=0           >0          <0
1359:            //   DOW_LE_DOM_MODE   >=0           <0          <0
1360:            //   (no DST)          don't care    ==0         don't care
1361:            //
1362:            // STREAMED REPRESENTATION
1363:            // We must retain binary compatibility with the 1.1.  The 1.1 code only
1364:            // handles DOW_IN_MONTH_MODE and non-DST mode, the latter indicated by the
1365:            // flag useDaylight.  When we stream an object out, we translate into an
1366:            // approximate DOW_IN_MONTH_MODE representation so the object can be parsed
1367:            // and used by 1.1 code.  Following that, we write out the full
1368:            // representation separately so that contemporary code can recognize and
1369:            // parse it.  The full representation is written in a "packed" format,
1370:            // consisting of a version number, a length, and an array of bytes.  Future
1371:            // versions of this class may specify different versions.  If they wish to
1372:            // include additional data, they should do so by storing them after the
1373:            // packed representation below.
1374:            //----------------------------------------------------------------------
1375:
1376:            /**
1377:             * Given a set of encoded rules in startDay and startDayOfMonth, decode
1378:             * them and set the startMode appropriately.  Do the same for endDay and
1379:             * endDayOfMonth.  Upon entry, the day of week variables may be zero or
1380:             * negative, in order to indicate special modes.  The day of month
1381:             * variables may also be negative.  Upon exit, the mode variables will be
1382:             * set, and the day of week and day of month variables will be positive.
1383:             * This method also recognizes a startDay or endDay of zero as indicating
1384:             * no DST.
1385:             */
1386:            private void decodeRules() {
1387:                decodeStartRule();
1388:                decodeEndRule();
1389:            }
1390:
1391:            /**
1392:             * Decode the start rule and validate the parameters.  The parameters are
1393:             * expected to be in encoded form, which represents the various rule modes
1394:             * by negating or zeroing certain values.  Representation formats are:
1395:             * <p>
1396:             * <pre>
1397:             *            DOW_IN_MONTH  DOM    DOW>=DOM  DOW<=DOM  no DST
1398:             *            ------------  -----  --------  --------  ----------
1399:             * month       0..11        same    same      same     don't care
1400:             * day        -5..5         1..31   1..31    -1..-31   0
1401:             * dayOfWeek   1..7         0      -1..-7    -1..-7    don't care
1402:             * time        0..ONEDAY    same    same      same     don't care
1403:             * </pre>
1404:             * The range for month does not include UNDECIMBER since this class is
1405:             * really specific to GregorianCalendar, which does not use that month.
1406:             * The range for time includes ONEDAY (vs. ending at ONEDAY-1) because the
1407:             * end rule is an exclusive limit point.  That is, the range of times that
1408:             * are in DST include those >= the start and < the end.  For this reason,
1409:             * it should be possible to specify an end of ONEDAY in order to include the
1410:             * entire day.  Although this is equivalent to time 0 of the following day,
1411:             * it's not always possible to specify that, for example, on December 31.
1412:             * While arguably the start range should still be 0..ONEDAY-1, we keep
1413:             * the start and end ranges the same for consistency.
1414:             */
1415:            private void decodeStartRule() {
1416:                useDaylight = (startDay != 0) && (endDay != 0);
1417:                if (startDay != 0) {
1418:                    if (startMonth < Calendar.JANUARY
1419:                            || startMonth > Calendar.DECEMBER) {
1420:                        throw new IllegalArgumentException(
1421:                                "Illegal start month " + startMonth);
1422:                    }
1423:                    if (startTime < 0 || startTime >= millisPerDay) {
1424:                        throw new IllegalArgumentException(
1425:                                "Illegal start time " + startTime);
1426:                    }
1427:                    if (startDayOfWeek == 0) {
1428:                        startMode = DOM_MODE;
1429:                    } else {
1430:                        if (startDayOfWeek > 0) {
1431:                            startMode = DOW_IN_MONTH_MODE;
1432:                        } else {
1433:                            startDayOfWeek = -startDayOfWeek;
1434:                            if (startDay > 0) {
1435:                                startMode = DOW_GE_DOM_MODE;
1436:                            } else {
1437:                                startDay = -startDay;
1438:                                startMode = DOW_LE_DOM_MODE;
1439:                            }
1440:                        }
1441:                        if (startDayOfWeek > Calendar.SATURDAY) {
1442:                            throw new IllegalArgumentException(
1443:                                    "Illegal start day of week "
1444:                                            + startDayOfWeek);
1445:                        }
1446:                    }
1447:                    if (startMode == DOW_IN_MONTH_MODE) {
1448:                        if (startDay < -5 || startDay > 5) {
1449:                            throw new IllegalArgumentException(
1450:                                    "Illegal start day of week in month "
1451:                                            + startDay);
1452:                        }
1453:                    } else if (startDay < 1
1454:                            || startDay > staticMonthLength[startMonth]) {
1455:                        throw new IllegalArgumentException("Illegal start day "
1456:                                + startDay);
1457:                    }
1458:                }
1459:            }
1460:
1461:            /**
1462:             * Decode the end rule and validate the parameters.  This method is exactly
1463:             * analogous to decodeStartRule().
1464:             * @see decodeStartRule
1465:             */
1466:            private void decodeEndRule() {
1467:                useDaylight = (startDay != 0) && (endDay != 0);
1468:                if (endDay != 0) {
1469:                    if (endMonth < Calendar.JANUARY
1470:                            || endMonth > Calendar.DECEMBER) {
1471:                        throw new IllegalArgumentException("Illegal end month "
1472:                                + endMonth);
1473:                    }
1474:                    if (endTime < 0 || endTime >= millisPerDay) {
1475:                        throw new IllegalArgumentException("Illegal end time "
1476:                                + endTime);
1477:                    }
1478:                    if (endDayOfWeek == 0) {
1479:                        endMode = DOM_MODE;
1480:                    } else {
1481:                        if (endDayOfWeek > 0) {
1482:                            endMode = DOW_IN_MONTH_MODE;
1483:                        } else {
1484:                            endDayOfWeek = -endDayOfWeek;
1485:                            if (endDay > 0) {
1486:                                endMode = DOW_GE_DOM_MODE;
1487:                            } else {
1488:                                endDay = -endDay;
1489:                                endMode = DOW_LE_DOM_MODE;
1490:                            }
1491:                        }
1492:                        if (endDayOfWeek > Calendar.SATURDAY) {
1493:                            throw new IllegalArgumentException(
1494:                                    "Illegal end day of week " + endDayOfWeek);
1495:                        }
1496:                    }
1497:                    if (endMode == DOW_IN_MONTH_MODE) {
1498:                        if (endDay < -5 || endDay > 5) {
1499:                            throw new IllegalArgumentException(
1500:                                    "Illegal end day of week in month "
1501:                                            + endDay);
1502:                        }
1503:                    } else if (endDay < 1
1504:                            || endDay > staticMonthLength[endMonth]) {
1505:                        throw new IllegalArgumentException("Illegal end day "
1506:                                + endDay);
1507:                    }
1508:                }
1509:            }
1510:
1511:            /**
1512:             * Make rules compatible to 1.1 code.  Since 1.1 code only understands
1513:             * day-of-week-in-month rules, we must modify other modes of rules to their
1514:             * approximate equivalent in 1.1 terms.  This method is used when streaming
1515:             * out objects of this class.  After it is called, the rules will be modified,
1516:             * with a possible loss of information.  startMode and endMode will NOT be
1517:             * altered, even though semantically they should be set to DOW_IN_MONTH_MODE,
1518:             * since the rule modification is only intended to be temporary.
1519:             */
1520:            private void makeRulesCompatible() {
1521:                switch (startMode) {
1522:                case DOM_MODE:
1523:                    startDay = 1 + (startDay / 7);
1524:                    startDayOfWeek = Calendar.SUNDAY;
1525:                    break;
1526:
1527:                case DOW_GE_DOM_MODE:
1528:                    // A day-of-month of 1 is equivalent to DOW_IN_MONTH_MODE
1529:                    // that is, Sun>=1 == firstSun.
1530:                    if (startDay != 1) {
1531:                        startDay = 1 + (startDay / 7);
1532:                    }
1533:                    break;
1534:
1535:                case DOW_LE_DOM_MODE:
1536:                    if (startDay >= 30) {
1537:                        startDay = -1;
1538:                    } else {
1539:                        startDay = 1 + (startDay / 7);
1540:                    }
1541:                    break;
1542:                }
1543:
1544:                switch (endMode) {
1545:                case DOM_MODE:
1546:                    endDay = 1 + (endDay / 7);
1547:                    endDayOfWeek = Calendar.SUNDAY;
1548:                    break;
1549:
1550:                case DOW_GE_DOM_MODE:
1551:                    // A day-of-month of 1 is equivalent to DOW_IN_MONTH_MODE
1552:                    // that is, Sun>=1 == firstSun.
1553:                    if (endDay != 1) {
1554:                        endDay = 1 + (endDay / 7);
1555:                    }
1556:                    break;
1557:
1558:                case DOW_LE_DOM_MODE:
1559:                    if (endDay >= 30) {
1560:                        endDay = -1;
1561:                    } else {
1562:                        endDay = 1 + (endDay / 7);
1563:                    }
1564:                    break;
1565:                }
1566:
1567:                /*
1568:                 * Adjust the start and end times to wall time.  This works perfectly
1569:                 * well unless it pushes into the next or previous day.  If that
1570:                 * happens, we attempt to adjust the day rule somewhat crudely.  The day
1571:                 * rules have been forced into DOW_IN_MONTH mode already, so we change
1572:                 * the day of week to move forward or back by a day.  It's possible to
1573:                 * make a more refined adjustment of the original rules first, but in
1574:                 * most cases this extra effort will go to waste once we adjust the day
1575:                 * rules anyway.
1576:                 */
1577:                switch (startTimeMode) {
1578:                case UTC_TIME:
1579:                    startTime += rawOffset;
1580:                    break;
1581:                }
1582:                while (startTime < 0) {
1583:                    startTime += millisPerDay;
1584:                    startDayOfWeek = 1 + ((startDayOfWeek + 5) % 7); // Back 1 day
1585:                }
1586:                while (startTime >= millisPerDay) {
1587:                    startTime -= millisPerDay;
1588:                    startDayOfWeek = 1 + (startDayOfWeek % 7); // Forward 1 day
1589:                }
1590:
1591:                switch (endTimeMode) {
1592:                case UTC_TIME:
1593:                    endTime += rawOffset + dstSavings;
1594:                    break;
1595:                case STANDARD_TIME:
1596:                    endTime += dstSavings;
1597:                }
1598:                while (endTime < 0) {
1599:                    endTime += millisPerDay;
1600:                    endDayOfWeek = 1 + ((endDayOfWeek + 5) % 7); // Back 1 day
1601:                }
1602:                while (endTime >= millisPerDay) {
1603:                    endTime -= millisPerDay;
1604:                    endDayOfWeek = 1 + (endDayOfWeek % 7); // Forward 1 day
1605:                }
1606:            }
1607:
1608:            /**
1609:             * Pack the start and end rules into an array of bytes.  Only pack
1610:             * data which is not preserved by makeRulesCompatible.
1611:             */
1612:            private byte[] packRules() {
1613:                byte[] rules = new byte[6];
1614:                rules[0] = (byte) startDay;
1615:                rules[1] = (byte) startDayOfWeek;
1616:                rules[2] = (byte) endDay;
1617:                rules[3] = (byte) endDayOfWeek;
1618:
1619:                // As of serial version 2, include time modes
1620:                rules[4] = (byte) startTimeMode;
1621:                rules[5] = (byte) endTimeMode;
1622:
1623:                return rules;
1624:            }
1625:
1626:            /**
1627:             * Given an array of bytes produced by packRules, interpret them
1628:             * as the start and end rules.
1629:             */
1630:            private void unpackRules(byte[] rules) {
1631:                startDay = rules[0];
1632:                startDayOfWeek = rules[1];
1633:                endDay = rules[2];
1634:                endDayOfWeek = rules[3];
1635:
1636:                // As of serial version 2, include time modes
1637:                if (rules.length >= 6) {
1638:                    startTimeMode = rules[4];
1639:                    endTimeMode = rules[5];
1640:                }
1641:            }
1642:
1643:            /**
1644:             * Pack the start and end times into an array of bytes.  This is required
1645:             * as of serial version 2.
1646:             */
1647:            private int[] packTimes() {
1648:                int[] times = new int[2];
1649:                times[0] = startTime;
1650:                times[1] = endTime;
1651:                return times;
1652:            }
1653:
1654:            /**
1655:             * Unpack the start and end times from an array of bytes.  This is required
1656:             * as of serial version 2.
1657:             */
1658:            private void unpackTimes(int[] times) {
1659:                startTime = times[0];
1660:                endTime = times[1];
1661:            }
1662:
1663:            /**
1664:             * Save the state of this object to a stream (i.e., serialize it).
1665:             *
1666:             * @serialData We write out two formats, a JDK 1.1 compatible format, using
1667:             * <code>DOW_IN_MONTH_MODE</code> rules, in the required section, followed
1668:             * by the full rules, in packed format, in the optional section.  The
1669:             * optional section will be ignored by JDK 1.1 code upon stream in.
1670:             * <p> Contents of the optional section: The length of a byte array is
1671:             * emitted (int); this is 4 as of this release. The byte array of the given
1672:             * length is emitted. The contents of the byte array are the true values of
1673:             * the fields <code>startDay</code>, <code>startDayOfWeek</code>,
1674:             * <code>endDay</code>, and <code>endDayOfWeek</code>.  The values of these
1675:             * fields in the required section are approximate values suited to the rule
1676:             * mode <code>DOW_IN_MONTH_MODE</code>, which is the only mode recognized by
1677:             * JDK 1.1.
1678:             */
1679:            private void writeObject(ObjectOutputStream stream)
1680:                    throws IOException {
1681:                // Construct a binary rule
1682:                byte[] rules = packRules();
1683:                int[] times = packTimes();
1684:
1685:                // Convert to 1.1 rules.  This step may cause us to lose information.
1686:                makeRulesCompatible();
1687:
1688:                // Write out the 1.1 rules
1689:                stream.defaultWriteObject();
1690:
1691:                // Write out the binary rules in the optional data area of the stream.
1692:                stream.writeInt(rules.length);
1693:                stream.write(rules);
1694:                stream.writeObject(times);
1695:
1696:                // Recover the original rules.  This recovers the information lost
1697:                // by makeRulesCompatible.
1698:                unpackRules(rules);
1699:                unpackTimes(times);
1700:            }
1701:
1702:            /**
1703:             * Reconstitute this object from a stream (i.e., deserialize it).
1704:             *
1705:             * We handle both JDK 1.1
1706:             * binary formats and full formats with a packed byte array.
1707:             */
1708:            private void readObject(ObjectInputStream stream)
1709:                    throws IOException, ClassNotFoundException {
1710:                stream.defaultReadObject();
1711:
1712:                if (serialVersionOnStream < 1) {
1713:                    // Fix a bug in the 1.1 SimpleTimeZone code -- namely,
1714:                    // startDayOfWeek and endDayOfWeek were usually uninitialized.  We can't do
1715:                    // too much, so we assume SUNDAY, which actually works most of the time.
1716:                    if (startDayOfWeek == 0) {
1717:                        startDayOfWeek = Calendar.SUNDAY;
1718:                    }
1719:                    if (endDayOfWeek == 0) {
1720:                        endDayOfWeek = Calendar.SUNDAY;
1721:                    }
1722:
1723:                    // The variables dstSavings, startMode, and endMode are post-1.1, so they
1724:                    // won't be present if we're reading from a 1.1 stream.  Fix them up.
1725:                    startMode = endMode = DOW_IN_MONTH_MODE;
1726:                    dstSavings = millisPerHour;
1727:                } else {
1728:                    // For 1.1.4, in addition to the 3 new instance variables, we also
1729:                    // store the actual rules (which have not be made compatible with 1.1)
1730:                    // in the optional area.  Read them in here and parse them.
1731:                    int length = stream.readInt();
1732:                    byte[] rules = new byte[length];
1733:                    stream.readFully(rules);
1734:                    unpackRules(rules);
1735:                }
1736:
1737:                if (serialVersionOnStream >= 2) {
1738:                    int[] times = (int[]) stream.readObject();
1739:                    unpackTimes(times);
1740:                }
1741:
1742:                serialVersionOnStream = currentSerialVersion;
1743:            }
1744:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.