home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 November / Chip_1998-11_cd.bin / tema / Cafe / main.bin / SimpleTimeZone.java < prev    next >
Text File  |  1997-10-01  |  16KB  |  395 lines

  1. /*
  2.  * @(#)SimpleTimeZone.java    1.13 97/07/15
  3.  *
  4.  * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
  5.  * (C) Copyright IBM Corp. 1996 - All Rights Reserved
  6.  *
  7.  * Portions copyright (c) 1996 Sun Microsystems, Inc. All Rights Reserved.
  8.  *
  9.  *   The original version of this source code and documentation is copyrighted
  10.  * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  11.  * materials are provided under terms of a License Agreement between Taligent
  12.  * and Sun. This technology is protected by multiple US and International
  13.  * patents. This notice and attribution to Taligent may not be removed.
  14.  *   Taligent is a registered trademark of Taligent, Inc.
  15.  *
  16.  * Permission to use, copy, modify, and distribute this software
  17.  * and its documentation for NON-COMMERCIAL purposes and without
  18.  * fee is hereby granted provided that this copyright notice
  19.  * appears in all copies. Please refer to the file "copyright.html"
  20.  * for further important copyright and licensing information.
  21.  *
  22.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  23.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  24.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  25.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  26.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  27.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  28.  *
  29.  */
  30.  
  31. package java.util;
  32.  
  33. import java.io.ObjectInputStream;
  34. import java.io.IOException;
  35.  
  36. /**
  37.  * <code>SimpleTimeZone</code> is a concrete subclass of <code>TimeZone</code>
  38.  * that represents a time zone for use with a Gregorian
  39.  * calendar. This simple class does not handle historical
  40.  * changes, and has limited rules.
  41.  *
  42.  * <P>
  43.  * Use a negative value for <code>dayOfWeekInMonth</code> to indicate that
  44.  * <code>SimpleTimeZone</code> should count from the end of the month backwards.
  45.  * For example, Daylight Savings Time ends at the last
  46.  * (dayOfWeekInMonth = -1) Sunday in October, at 2 AM in standard time.
  47.  *
  48.  * @see          Calendar
  49.  * @see          GregorianCalendar
  50.  * @see          TimeZone
  51.  * @version      1.13 07/15/97
  52.  * @author       David Goldsmith, Mark Davis, Chen-Lieh Huang, Alan Liu
  53.  */
  54. public class SimpleTimeZone extends TimeZone {
  55.     /**
  56.      * Constructs a SimpleTimeZone with the given base time zone offset
  57.      * from GMT and time zone ID. Timezone IDs can be obtained from
  58.      * TimeZone.getAvailableIDs. Normally you should use TimeZone.getDefault
  59.      * to construct a TimeZone.
  60.      * @param rawOffset the given base time zone offset to GMT.
  61.      * @param ID the time zone ID which is obtained from
  62.      * TimeZone.getAvailableIDs.
  63.      */
  64.     public SimpleTimeZone(int rawOffset, String ID)
  65.     {
  66.         this.rawOffset = rawOffset;
  67.         setID (ID);
  68.     }
  69.  
  70.     /**
  71.      * Constructs a SimpleTimeZone with the given base time zone offset
  72.      * from GMT, time zone ID, time to start and end the daylight time.
  73.      * Timezone IDs can be obtained from TimeZone.getAvailableIDs.
  74.      * Normally you should use TimeZone.getDefault to create a TimeZone.
  75.      * For a time zone that does not use daylight saving time, do not
  76.      * use this constructor; instead you should use
  77.      * SimpleTimeZone(rawOffset, ID).
  78.      * @param rawOffset the given base time zone offset to GMT.
  79.      * @param ID the time zone ID which is obtained from
  80.      * TimeZone.getAvailableIDs.
  81.      * @param startMonth the daylight savings starting month. Month is 0-based.
  82.      * eg, 0 for January.
  83.      * @param startDayOfWeekInMonth the daylight savings starting
  84.      * day-of-week-in-month. Please see the member description for an example.
  85.      * @param startDayOfWeek the daylight savings starting day-of-week.
  86.      * Please see the member description for an example.
  87.      * @param startTime the daylight savings starting time. Please see the
  88.      * member description for an example.
  89.      * @param endMonth the daylight savings ending month. Month is 0-based.
  90.      * eg, 0 for January.
  91.      * @param endDayOfWeekInMonth the daylight savings ending
  92.      * day-of-week-in-month. Please see the member description for an example.
  93.      * @param endDayOfWeek the daylight savings ending day-of-week. Please see
  94.      * the member description for an example.
  95.      * @param endTime the daylight savings ending time. Please see the member
  96.      * description for an example.
  97.      */
  98.     public SimpleTimeZone(int rawOffset, String ID, int startMonth,
  99.               int startDayOfWeekInMonth, int startDayOfWeek, int startTime,
  100.               int endMonth, int endDayOfWeekInMonth, int endDayOfWeek, int endTime)
  101.     {
  102.         setID (ID);
  103.         this.rawOffset = rawOffset;
  104.         this.startMonth = startMonth;
  105.         this.startDay = startDayOfWeekInMonth;
  106.         this.startDayOfWeek = startDayOfWeek;
  107.         this.startTime = startTime;
  108.         this.endMonth = endMonth;
  109.         this.endDay = endDayOfWeekInMonth;
  110.         this.endDayOfWeek = endDayOfWeek;
  111.         this.endTime = endTime;
  112.         this.useDaylight = true;
  113.     }
  114.  
  115.     /**
  116.      * Sets the daylight savings starting year.
  117.      * @param year the daylight savings starting year.
  118.      */
  119.     public void setStartYear(int year)
  120.     {
  121.         startYear = year;
  122.         useDaylight = true;
  123.     }
  124.  
  125.     /**
  126.      * Sets the daylight savings starting rule. For example, Daylight Savings
  127.      * Time starts at the first Sunday in April, at 2 AM in standard time.
  128.      * Therefore, you can set the start rule by calling:
  129.      * setStartRule(TimeFields.APRIL, 1, TimeFields.SUNDAY, 2*60*60*1000);
  130.      * @param month the daylight savings starting month. Month is 0-based.
  131.      * eg, 0 for January.
  132.      * @param dayOfWeekInMonth the daylight savings starting
  133.      * day-of-week-in-month. Please see the member description for an example.
  134.      * @param dayOfWeek the daylight savings starting day-of-week. Please see
  135.      * the member description for an example.
  136.      * @param time the daylight savings starting time. Please see the member
  137.      * description for an example.
  138.      */
  139.     public void setStartRule(int month, int dayOfWeekInMonth, int dayOfWeek,
  140.                              int time)
  141.     {
  142.         startMonth = month;
  143.         startDay = dayOfWeekInMonth;
  144.         startDayOfWeek = dayOfWeek;
  145.         startTime = time;
  146.         useDaylight = true;
  147.     }
  148.  
  149.     /**
  150.      * Sets the daylight savings ending rule. For example, Daylight Savings
  151.      * Time ends at the last (-1) Sunday in October, at 2 AM in standard time.
  152.      * Therefore, you can set the end rule by calling:
  153.      * setEndRule(TimeFields.OCTOBER, -1, TimeFields.SUNDAY, 2*60*60*1000);
  154.      * @param month the daylight savings ending month. Month is 0-based.
  155.      * eg, 0 for January.
  156.      * @param dayOfWeekInMonth the daylight savings ending
  157.      * day-of-week-in-month. Please see the member description for an example.
  158.      * @param dayOfWeek the daylight savings ending day-of-week. Please see
  159.      * the member description for an example.
  160.      * @param time the daylight savings ending time. Please see the member
  161.      * description for an example.
  162.      */
  163.     public void setEndRule(int month, int dayOfWeekInMonth, int dayOfWeek,
  164.                            int time)
  165.     {
  166.         endMonth = month;
  167.         endDay = dayOfWeekInMonth;
  168.         endDayOfWeek = dayOfWeek;
  169.         endTime = time;
  170.         useDaylight = true;
  171.     }
  172.  
  173.     /**
  174.      * Overrides TimeZone
  175.      * Gets the time zone offset, for current date, modified in case of
  176.      * daylight savings. This is the offset to add *to* UTC to get local time.
  177.      *
  178.      * Please see TimeZone.getOffset for descriptions of parameters.
  179.      * @see TimeZone#getOffset
  180.      */
  181.     public int getOffset(int era, int year, int month, int day, int dayOfWeek,
  182.                          int millis)
  183.     {
  184.         int result = rawOffset;
  185.  
  186.         // Bail out if we are before the onset of daylight savings time
  187.         if (year < startYear || era != GregorianCalendar.AD)
  188.             return result;
  189.  
  190.         // Check for southern hemisphere.  We assume that the start and end
  191.         // month are different.
  192.         boolean southern = (startMonth > endMonth);
  193.  
  194.         // Compare the date to the starting and ending rules.  For the ending
  195.         // rule comparison, we add an hour to the millis passed in to convert
  196.         // them from standard to daylight.  +1 = date>rule, -1 = date<rule, 0 =
  197.         // date==rule.
  198.         int startCompare = compareToRule(month, day, dayOfWeek, millis,
  199.                          startMonth, startDayOfWeek, startDay, startTime);
  200.         int endCompare = compareToRule(month, day, dayOfWeek, millis + millisPerHour,
  201.                            endMonth, endDayOfWeek, endDay, endTime);
  202.  
  203.         // Check for both the northern and southern hemisphere cases.  We
  204.         // assume that in the northern hemisphere, the start rule is before the
  205.         // end rule within the calendar year, and vice versa for the southern
  206.         // hemisphere.
  207.         if ((!southern && (startCompare >= 0 && endCompare < 0)) ||
  208.                 (southern && (startCompare >= 0 || endCompare < 0)))
  209.             result += millisPerHour;
  210.  
  211.         return result;
  212.     }
  213.  
  214.     /**
  215.      * Compare a given date in the year to a rule.  Return 1, 0, or -1, depending
  216.      * on whether the date is after, equal to, or before the rule date.  The millis
  217.      * are compared directly against the ruleMillis, so any standard-daylight adjustments
  218.      * must be handled by the caller.  Assume that no rule references the end of
  219.      * February (e.g., last Sunday in February).
  220.      * @return 1 if the date is after the rule date, -1 if the date is before the
  221.      * rule date, or 0 if the date is equal to the rule date.
  222.      */
  223.     private static int compareToRule(int month, int dayOfMonth, int dayOfWeek, int millis,
  224.                      int ruleMonth, int ruleDayOfWeek, int ruleDOWinMonth, int ruleMillis)
  225.     {
  226.         if (month < ruleMonth)
  227.             return -1;
  228.         else if (month > ruleMonth)
  229.             return 1;
  230.  
  231.         int monthLen = staticMonthLength[month];
  232.  
  233.         int ruleDayOfMonth;
  234.         if (ruleDOWinMonth > 0)
  235.             ruleDayOfMonth = 1 + (ruleDOWinMonth - 1) * 7 +
  236.                     (7 + ruleDayOfWeek - (dayOfWeek - dayOfMonth + 1)) % 7;
  237.         else // Assume ruleDOWinMonth < 0 here
  238.             ruleDayOfMonth = monthLen + (ruleDOWinMonth + 1) * 7 -
  239.                     (7 + (dayOfWeek + monthLen - dayOfMonth) - ruleDayOfWeek) % 7;
  240.  
  241.         if (dayOfMonth < ruleDayOfMonth)
  242.             return -1;
  243.         else if (dayOfMonth > ruleDayOfMonth)
  244.             return 1;
  245.  
  246.         if (millis < ruleMillis)
  247.             return -1;
  248.         else if (millis > ruleMillis)
  249.             return 1;
  250.         else
  251.             return 0;
  252.     }
  253.  
  254.     /**
  255.      * Overrides TimeZone
  256.      * Gets the GMT offset for this time zone.
  257.      */
  258.     public int getRawOffset()
  259.     {
  260.         // The given date will be taken into account while
  261.         // we have the historical time zone data in place.
  262.         return rawOffset;
  263.     }
  264.  
  265.     /**
  266.      * Overrides TimeZone
  267.      * Sets the base time zone offset to GMT.
  268.      * This is the offset to add *to* UTC to get local time.
  269.      * Please see TimeZone.setRawOffset for descriptions on the parameter.
  270.      */
  271.     public void setRawOffset(int offsetMillis)
  272.     {
  273.         this.rawOffset = offsetMillis;
  274.     }
  275.  
  276.     /**
  277.      * Overrides TimeZone
  278.      * Queries if this time zone uses Daylight Savings Time.
  279.      */
  280.     public boolean useDaylightTime()
  281.     {
  282.         return useDaylight;
  283.     }
  284.  
  285.     /**
  286.      * Overrides TimeZone
  287.      * Queries if the given date is in Daylight Savings Time.
  288.      */
  289.     public boolean inDaylightTime(Date date)
  290.     {
  291.         GregorianCalendar gc = new GregorianCalendar(this);
  292.         gc.setTime(date);
  293.         return gc.inDaylightTime();
  294.    }
  295.  
  296.     /**
  297.      * Overrides Cloneable
  298.      */
  299.     public Object clone()
  300.     {
  301.         return super.clone();
  302.         // other fields are bit-copied
  303.     }
  304.  
  305.     /**
  306.      * Override hashCode.
  307.      * Generates the hash code for the SimpleDateFormat object
  308.      */
  309.     public synchronized int hashCode()
  310.     {
  311.         return startMonth ^ startDay ^ startDayOfWeek ^ startTime ^
  312.                endMonth ^ endDay ^ endDayOfWeek ^ endTime ^ rawOffset;
  313.     }
  314.  
  315.     /**
  316.      * Compares the equality of two SimpleTimeZone objects.
  317.      * @param obj the SimpleTimeZone object to be compared with.
  318.      * @return true if the given obj is the same as this SimpleTimeZone
  319.      * object; false otherwise.
  320.      */
  321.     public boolean equals(Object obj)
  322.     {
  323.         if (this == obj)
  324.             return true;
  325.         if (!(obj instanceof SimpleTimeZone))
  326.             return false;
  327.  
  328.         SimpleTimeZone that = (SimpleTimeZone) obj;
  329.  
  330.         if (!this.getID().equals(that.getID()))
  331.             return false;
  332.         if (this.startMonth != that.startMonth)
  333.             return false;
  334.         if (this.startDay != that.startDay)
  335.             return false;
  336.         if (this.startDayOfWeek != that.startDayOfWeek)
  337.             return false;
  338.         if (this.startTime != that.startTime)
  339.             return false;
  340.         if (this.endMonth != that.endMonth)
  341.             return false;
  342.         if (this.endDay != that.endDay)
  343.             return false;
  344.         if (this.endDayOfWeek != that.endDayOfWeek)
  345.             return false;
  346.         if (this.endTime != that.endTime)
  347.             return false;
  348.         if (this.startYear != that.startYear)
  349.             return false;
  350.         if (this.rawOffset != that.rawOffset)
  351.             return false;
  352.         if (this.useDaylight != that.useDaylight)
  353.             return false;
  354.         return true;
  355.     }
  356.  
  357.     // =======================privates===============================
  358.  
  359.     private int startMonth, startDay, startDayOfWeek, startTime;
  360.     private int endMonth, endDay, endDayOfWeek, endTime;
  361.     private int startYear;
  362.     private int rawOffset;
  363.     private boolean useDaylight=false; // indicate if this time zone uses DST
  364.     private static final int millisPerHour = 60*60*1000;
  365.     // WARNING: assumes that no rule is measured from the end of February,
  366.     // since we don't handle leap years. Could handle assuming always
  367.     // Gregorian, since we know they didn't have daylight time when
  368.     // Gregorian calendar started.
  369.     // monthLength was non-static in JDK 1.1, so we have to keep it that way
  370.     // to maintain serialization compatibility. However, there's no need to
  371.     // recreate the array each time we create a new time zone.
  372.     private final byte monthLength[] = staticMonthLength;
  373.     private final static byte staticMonthLength[] = {31,28,31,30,31,30,31,31,30,31,30,31};
  374.  
  375.     /**
  376.      * Read this object back from a serialization stream.
  377.      */
  378.     private void readObject(ObjectInputStream stream)
  379.         throws IOException, ClassNotFoundException
  380.     {
  381.         stream.defaultReadObject();
  382.  
  383.         // Now we fix up a bug in the 1.1 SimpleTimeZone code -- namely,
  384.         // startDayOfWeek and endDayOfWeek were usually uninitialized.  We can't do
  385.         // too much, so we assume SUNDAY, which works most of the time.
  386.         if (startDayOfWeek == 0)
  387.             startDayOfWeek = Calendar.SUNDAY;
  388.         if (endDayOfWeek == 0)
  389.             endDayOfWeek = Calendar.SUNDAY;
  390.     }
  391.  
  392.     // Proclaim compatibility with 1.1
  393.     static final long serialVersionUID = -403250971215465050L;
  394. }
  395.