Source Code Cross Referenced for SimpleTimeZone.java in  » 6.0-JDK-Core » Collections-Jar-Zip-Logging-regex » java » util » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
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
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » Collections Jar Zip Logging regex » java.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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