< prev index next >

src/share/classes/java/util/SimpleTimeZone.java

Print this page
rev 12544 : 8181323: Better timezone processing
Reviewed-by: naoto, rriggs
   1 /*
   2  * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


  24  */
  25 
  26 /*
  27  * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
  28  * (C) Copyright IBM Corp. 1996 - All Rights Reserved
  29  *
  30  *   The original version of this source code and documentation is copyrighted
  31  * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  32  * materials are provided under terms of a License Agreement between Taligent
  33  * and Sun. This technology is protected by multiple US and International
  34  * patents. This notice and attribution to Taligent may not be removed.
  35  *   Taligent is a registered trademark of Taligent, Inc.
  36  *
  37  */
  38 
  39 package java.util;
  40 
  41 import java.io.ObjectInputStream;
  42 import java.io.ObjectOutputStream;
  43 import java.io.IOException;

  44 import sun.util.calendar.CalendarSystem;
  45 import sun.util.calendar.CalendarUtils;
  46 import sun.util.calendar.BaseCalendar;
  47 import sun.util.calendar.Gregorian;
  48 
  49 /**
  50  * <code>SimpleTimeZone</code> is a concrete subclass of <code>TimeZone</code>
  51  * that represents a time zone for use with a Gregorian calendar.
  52  * The class holds an offset from GMT, called <em>raw offset</em>, and start
  53  * and end rules for a daylight saving time schedule.  Since it only holds
  54  * single values for each, it cannot handle historical changes in the offset
  55  * from GMT and the daylight saving schedule, except that the {@link
  56  * #setStartYear setStartYear} method can specify the year when the daylight
  57  * saving time schedule starts in effect.
  58  * <p>
  59  * To construct a <code>SimpleTimeZone</code> with a daylight saving time
  60  * schedule, the schedule can be described with a set of rules,
  61  * <em>start-rule</em> and <em>end-rule</em>. A day when daylight saving time
  62  * starts or ends is specified by a combination of <em>month</em>,
  63  * <em>day-of-month</em>, and <em>day-of-week</em> values. The <em>month</em>


1261      * </dd>
1262      * <dt><b>1</b></dt>
1263      * <dd>
1264      * JDK 1.1.4 or later.  Includes three new fields: <code>startMode</code>,
1265      * <code>endMode</code>, and <code>dstSavings</code>.
1266      * </dd>
1267      * <dt><b>2</b></dt>
1268      * <dd>
1269      * JDK 1.3 or later.  Includes two new fields: <code>startTimeMode</code>
1270      * and <code>endTimeMode</code>.
1271      * </dd>
1272      * </dl>
1273      * When streaming out this class, the most recent format
1274      * and the highest allowable <code>serialVersionOnStream</code>
1275      * is written.
1276      * @serial
1277      * @since 1.1.4
1278      */
1279     private int serialVersionOnStream = currentSerialVersion;
1280 



1281     synchronized private void invalidateCache() {
1282         cacheYear = startYear - 1;
1283         cacheStart = cacheEnd = 0;
1284     }
1285 
1286     //----------------------------------------------------------------------
1287     // Rule representation
1288     //
1289     // We represent the following flavors of rules:
1290     //       5        the fifth of the month
1291     //       lastSun  the last Sunday in the month
1292     //       lastMon  the last Monday in the month
1293     //       Sun>=8   first Sunday on or after the eighth
1294     //       Sun<=25  last Sunday on or before the 25th
1295     // This is further complicated by the fact that we need to remain
1296     // backward compatible with the 1.1 FCS.  Finally, we need to minimize
1297     // API changes.  In order to satisfy these requirements, we support
1298     // three representation systems, and we translate between them.
1299     //
1300     // INTERNAL REPRESENTATION


1552             break;
1553         case STANDARD_TIME:
1554             endTime += dstSavings;
1555         }
1556         while (endTime < 0) {
1557             endTime += millisPerDay;
1558             endDayOfWeek = 1 + ((endDayOfWeek+5) % 7); // Back 1 day
1559         }
1560         while (endTime >= millisPerDay) {
1561             endTime -= millisPerDay;
1562             endDayOfWeek = 1 + (endDayOfWeek % 7); // Forward 1 day
1563         }
1564     }
1565 
1566     /**
1567      * Pack the start and end rules into an array of bytes.  Only pack
1568      * data which is not preserved by makeRulesCompatible.
1569      */
1570     private byte[] packRules()
1571     {
1572         byte[] rules = new byte[6];
1573         rules[0] = (byte)startDay;
1574         rules[1] = (byte)startDayOfWeek;
1575         rules[2] = (byte)endDay;
1576         rules[3] = (byte)endDayOfWeek;
1577 
1578         // As of serial version 2, include time modes
1579         rules[4] = (byte)startTimeMode;
1580         rules[5] = (byte)endTimeMode;
1581 
1582         return rules;
1583     }
1584 
1585     /**
1586      * Given an array of bytes produced by packRules, interpret them
1587      * as the start and end rules.
1588      */
1589     private void unpackRules(byte[] rules)
1590     {
1591         startDay       = rules[0];
1592         startDayOfWeek = rules[1];
1593         endDay         = rules[2];
1594         endDayOfWeek   = rules[3];
1595 
1596         // As of serial version 2, include time modes
1597         if (rules.length >= 6) {
1598             startTimeMode = rules[4];
1599             endTimeMode   = rules[5];
1600         }
1601     }
1602 
1603     /**
1604      * Pack the start and end times into an array of bytes.  This is required
1605      * as of serial version 2.
1606      */
1607     private int[] packTimes() {
1608         int[] times = new int[2];
1609         times[0] = startTime;
1610         times[1] = endTime;
1611         return times;
1612     }
1613 
1614     /**
1615      * Unpack the start and end times from an array of bytes.  This is required
1616      * as of serial version 2.
1617      */


1674         if (serialVersionOnStream < 1) {
1675             // Fix a bug in the 1.1 SimpleTimeZone code -- namely,
1676             // startDayOfWeek and endDayOfWeek were usually uninitialized.  We can't do
1677             // too much, so we assume SUNDAY, which actually works most of the time.
1678             if (startDayOfWeek == 0) {
1679                 startDayOfWeek = Calendar.SUNDAY;
1680             }
1681             if (endDayOfWeek == 0) {
1682                 endDayOfWeek = Calendar.SUNDAY;
1683             }
1684 
1685             // The variables dstSavings, startMode, and endMode are post-1.1, so they
1686             // won't be present if we're reading from a 1.1 stream.  Fix them up.
1687             startMode = endMode = DOW_IN_MONTH_MODE;
1688             dstSavings = millisPerHour;
1689         } else {
1690             // For 1.1.4, in addition to the 3 new instance variables, we also
1691             // store the actual rules (which have not be made compatible with 1.1)
1692             // in the optional area.  Read them in here and parse them.
1693             int length = stream.readInt();

1694             byte[] rules = new byte[length];
1695             stream.readFully(rules);
1696             unpackRules(rules);



1697         }
1698 
1699         if (serialVersionOnStream >= 2) {
1700             int[] times = (int[]) stream.readObject();
1701             unpackTimes(times);
1702         }
1703 
1704         serialVersionOnStream = currentSerialVersion;
1705     }
1706 }
   1 /*
   2  * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


  24  */
  25 
  26 /*
  27  * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
  28  * (C) Copyright IBM Corp. 1996 - All Rights Reserved
  29  *
  30  *   The original version of this source code and documentation is copyrighted
  31  * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  32  * materials are provided under terms of a License Agreement between Taligent
  33  * and Sun. This technology is protected by multiple US and International
  34  * patents. This notice and attribution to Taligent may not be removed.
  35  *   Taligent is a registered trademark of Taligent, Inc.
  36  *
  37  */
  38 
  39 package java.util;
  40 
  41 import java.io.ObjectInputStream;
  42 import java.io.ObjectOutputStream;
  43 import java.io.IOException;
  44 import java.io.InvalidObjectException;
  45 import sun.util.calendar.CalendarSystem;
  46 import sun.util.calendar.CalendarUtils;
  47 import sun.util.calendar.BaseCalendar;
  48 import sun.util.calendar.Gregorian;
  49 
  50 /**
  51  * <code>SimpleTimeZone</code> is a concrete subclass of <code>TimeZone</code>
  52  * that represents a time zone for use with a Gregorian calendar.
  53  * The class holds an offset from GMT, called <em>raw offset</em>, and start
  54  * and end rules for a daylight saving time schedule.  Since it only holds
  55  * single values for each, it cannot handle historical changes in the offset
  56  * from GMT and the daylight saving schedule, except that the {@link
  57  * #setStartYear setStartYear} method can specify the year when the daylight
  58  * saving time schedule starts in effect.
  59  * <p>
  60  * To construct a <code>SimpleTimeZone</code> with a daylight saving time
  61  * schedule, the schedule can be described with a set of rules,
  62  * <em>start-rule</em> and <em>end-rule</em>. A day when daylight saving time
  63  * starts or ends is specified by a combination of <em>month</em>,
  64  * <em>day-of-month</em>, and <em>day-of-week</em> values. The <em>month</em>


1262      * </dd>
1263      * <dt><b>1</b></dt>
1264      * <dd>
1265      * JDK 1.1.4 or later.  Includes three new fields: <code>startMode</code>,
1266      * <code>endMode</code>, and <code>dstSavings</code>.
1267      * </dd>
1268      * <dt><b>2</b></dt>
1269      * <dd>
1270      * JDK 1.3 or later.  Includes two new fields: <code>startTimeMode</code>
1271      * and <code>endTimeMode</code>.
1272      * </dd>
1273      * </dl>
1274      * When streaming out this class, the most recent format
1275      * and the highest allowable <code>serialVersionOnStream</code>
1276      * is written.
1277      * @serial
1278      * @since 1.1.4
1279      */
1280     private int serialVersionOnStream = currentSerialVersion;
1281 
1282     // Maximum number of rules.
1283     private static final int MAX_RULE_NUM = 6;
1284 
1285     synchronized private void invalidateCache() {
1286         cacheYear = startYear - 1;
1287         cacheStart = cacheEnd = 0;
1288     }
1289 
1290     //----------------------------------------------------------------------
1291     // Rule representation
1292     //
1293     // We represent the following flavors of rules:
1294     //       5        the fifth of the month
1295     //       lastSun  the last Sunday in the month
1296     //       lastMon  the last Monday in the month
1297     //       Sun>=8   first Sunday on or after the eighth
1298     //       Sun<=25  last Sunday on or before the 25th
1299     // This is further complicated by the fact that we need to remain
1300     // backward compatible with the 1.1 FCS.  Finally, we need to minimize
1301     // API changes.  In order to satisfy these requirements, we support
1302     // three representation systems, and we translate between them.
1303     //
1304     // INTERNAL REPRESENTATION


1556             break;
1557         case STANDARD_TIME:
1558             endTime += dstSavings;
1559         }
1560         while (endTime < 0) {
1561             endTime += millisPerDay;
1562             endDayOfWeek = 1 + ((endDayOfWeek+5) % 7); // Back 1 day
1563         }
1564         while (endTime >= millisPerDay) {
1565             endTime -= millisPerDay;
1566             endDayOfWeek = 1 + (endDayOfWeek % 7); // Forward 1 day
1567         }
1568     }
1569 
1570     /**
1571      * Pack the start and end rules into an array of bytes.  Only pack
1572      * data which is not preserved by makeRulesCompatible.
1573      */
1574     private byte[] packRules()
1575     {
1576         byte[] rules = new byte[MAX_RULE_NUM];
1577         rules[0] = (byte)startDay;
1578         rules[1] = (byte)startDayOfWeek;
1579         rules[2] = (byte)endDay;
1580         rules[3] = (byte)endDayOfWeek;
1581 
1582         // As of serial version 2, include time modes
1583         rules[4] = (byte)startTimeMode;
1584         rules[5] = (byte)endTimeMode;
1585 
1586         return rules;
1587     }
1588 
1589     /**
1590      * Given an array of bytes produced by packRules, interpret them
1591      * as the start and end rules.
1592      */
1593     private void unpackRules(byte[] rules)
1594     {
1595         startDay       = rules[0];
1596         startDayOfWeek = rules[1];
1597         endDay         = rules[2];
1598         endDayOfWeek   = rules[3];
1599 
1600         // As of serial version 2, include time modes
1601         if (rules.length >= MAX_RULE_NUM) {
1602             startTimeMode = rules[4];
1603             endTimeMode   = rules[5];
1604         }
1605     }
1606 
1607     /**
1608      * Pack the start and end times into an array of bytes.  This is required
1609      * as of serial version 2.
1610      */
1611     private int[] packTimes() {
1612         int[] times = new int[2];
1613         times[0] = startTime;
1614         times[1] = endTime;
1615         return times;
1616     }
1617 
1618     /**
1619      * Unpack the start and end times from an array of bytes.  This is required
1620      * as of serial version 2.
1621      */


1678         if (serialVersionOnStream < 1) {
1679             // Fix a bug in the 1.1 SimpleTimeZone code -- namely,
1680             // startDayOfWeek and endDayOfWeek were usually uninitialized.  We can't do
1681             // too much, so we assume SUNDAY, which actually works most of the time.
1682             if (startDayOfWeek == 0) {
1683                 startDayOfWeek = Calendar.SUNDAY;
1684             }
1685             if (endDayOfWeek == 0) {
1686                 endDayOfWeek = Calendar.SUNDAY;
1687             }
1688 
1689             // The variables dstSavings, startMode, and endMode are post-1.1, so they
1690             // won't be present if we're reading from a 1.1 stream.  Fix them up.
1691             startMode = endMode = DOW_IN_MONTH_MODE;
1692             dstSavings = millisPerHour;
1693         } else {
1694             // For 1.1.4, in addition to the 3 new instance variables, we also
1695             // store the actual rules (which have not be made compatible with 1.1)
1696             // in the optional area.  Read them in here and parse them.
1697             int length = stream.readInt();
1698             if (length <= MAX_RULE_NUM) {
1699                 byte[] rules = new byte[length];
1700                 stream.readFully(rules);
1701                 unpackRules(rules);
1702             } else {
1703                 throw new InvalidObjectException("Too many rules: " + length);
1704             }
1705         }
1706 
1707         if (serialVersionOnStream >= 2) {
1708             int[] times = (int[]) stream.readObject();
1709             unpackTimes(times);
1710         }
1711 
1712         serialVersionOnStream = currentSerialVersion;
1713     }
1714 }
< prev index next >