jdk/test/sun/util/calendar/zi/Timezone.java
changeset 15658 55b829ca2334
child 23010 6dadb192ad81
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/util/calendar/zi/Timezone.java	Tue Feb 12 09:25:43 2013 -0800
@@ -0,0 +1,452 @@
+/*
+ * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Timezone represents all information of a single point of time to
+ * generate its time zone database.
+ *
+ * @since 1.4
+ */
+class Timezone {
+    /**
+     * zone name of this time zone
+     */
+    private String name;
+
+    /**
+     * transition time values in UTC (millisecond)
+     */
+    private List<Long> transitions;
+
+    /**
+     * All offset values in millisecond
+     * @see sun.util.calendar.ZoneInfo
+     */
+    private List<Integer> offsets;
+
+    /**
+     * Indices of GMT offset values (both raw and raw+saving)
+     * at transitions
+     */
+    private List<Integer> gmtOffsets;
+
+    /**
+     * Indices of regular or "direct" saving time values
+     * at transitions
+     */
+    private List<Integer> dstOffsets;
+
+    /**
+     * Zone records of this time zone
+     */
+    private List<ZoneRec> usedZoneRecs;
+
+    /**
+     * Rule records referred to by this time zone
+     */
+    private List<RuleRec> usedRuleRecs;
+
+    /**
+     * Type of DST rules in this time zone
+     */
+    private int dstType;
+    static final int UNDEF_DST = 0;     // DST type not set yet
+    static final int NO_DST = 1;        // never observed DST
+    static final int LAST_DST = 2;      // last rule ends in DST (all year round DST-only)
+    static final int X_DST = 3;         // used to observe DST
+    static final int DST = 4;           // observing DST regularly
+
+    /**
+     * Raw GMT offset of this time zone in the last rule
+     */
+    private int rawOffset;
+
+    /**
+     * The CRC32 value of the transitions data
+     */
+    private int crc32;
+
+    /**
+     * The last ZoneRec
+     */
+    private ZoneRec lastZoneRec;
+
+    /**
+     * The last DST rules. lastRules[0] is the DST start
+     * rule. lastRules[1] is the DST end rules.
+     */
+    private List<RuleRec> lastRules;
+
+    /**
+     * The amount of DST saving value (millisecond) in the last DST
+     * rule.
+     */
+    private int lastSaving;
+
+    /**
+     * true if the raw offset will change in the future time.
+     */
+    private boolean willRawOffsetChange = false;
+
+
+    /**
+     * Constracts a Timezone object with the given zone name.
+     * @param name the zone name
+     */
+    Timezone(String name) {
+        this.name = name;
+    }
+
+    /**
+     * @return the number of transitions
+     */
+    int getNTransitions() {
+        if (transitions == null) {
+            return 0;
+        }
+        return transitions.size();
+    }
+
+    /**
+     * @return the zone name
+     */
+    String getName() {
+        return name;
+    }
+
+    /**
+     * Returns the list of all rule records that have been referred to
+     * by this time zone.
+     * @return the rule records list
+     */
+    List<RuleRec> getRules() {
+        return usedRuleRecs;
+    }
+
+    /**
+     * Returns the list of all zone records that have been referred to
+     * by this time zone.
+     * @return the zone records list
+     */
+    List<ZoneRec> getZones() {
+        return usedZoneRecs;
+    }
+
+    /**
+     * @return the transition table (list)
+     */
+    List<Long> getTransitions() {
+        return transitions;
+    }
+
+    /**
+     * @return the offsets list
+     */
+    List<Integer> getOffsets() {
+        return offsets;
+    }
+
+    /**
+     * @return the DST saving offsets list
+     */
+    List<Integer> getDstOffsets() {
+        return dstOffsets;
+    }
+
+    /**
+     * @return the GMT offsets list
+     */
+    List<Integer> getGmtOffsets() {
+        return gmtOffsets;
+    }
+
+    /**
+     * @return the checksum (crc32) value of the trasition table
+     */
+    int getCRC32() {
+        return crc32;
+    }
+
+    /**
+     * @return true if the GMT offset of this time zone would change
+     * after the time zone database has been generated, false, otherwise.
+     */
+    boolean willGMTOffsetChange() {
+        return willRawOffsetChange;
+    }
+
+    /**
+     * @return the last known GMT offset value in milliseconds
+     */
+    int getRawOffset() {
+        return rawOffset;
+    }
+
+    /**
+     * Sets time zone's GMT offset to <code>offset</code>.
+     * @param offset the GMT offset value in milliseconds
+     */
+    void setRawOffset(int offset) {
+        rawOffset = offset;
+    }
+
+    /**
+     * Sets time zone's GMT offset value to <code>offset</code>. If
+     * <code>startTime</code> is future time, then the {@link
+     * #willRawOffsetChange} value is set to true.
+     * @param offset the GMT offset value in milliseconds
+     * @param startTime the UTC time at which the GMT offset is in effective
+     */
+    void setRawOffset(int offset, long startTime) {
+        // if this rawOffset is for the future time, let the run-time
+        // look for the current GMT offset.
+        if (startTime > Time.getCurrentTime()) {
+            willRawOffsetChange = true;
+        }
+        setRawOffset(offset);
+    }
+
+    /**
+     * Adds the specified transition information to the end of the transition table.
+     * @param time the UTC time at which this transition happens
+     * @param offset the total amount of the offset from GMT in milliseconds
+     * @param dstOffset the amount of time in milliseconds saved at this transition
+     */
+    void addTransition(long time, int offset, int dstOffset) {
+        if (transitions == null) {
+            transitions = new ArrayList<Long>();
+            offsets = new ArrayList<Integer>();
+            dstOffsets = new ArrayList<Integer>();
+        }
+        transitions.add(time);
+        offsets.add(offset);
+        dstOffsets.add(dstOffset);
+    }
+
+    /**
+     * Sets the type of historical daylight saving time
+     * observation. For example, China used to observed daylight
+     * saving time, but it no longer does. Then, X_DST is set to the
+     * China time zone.
+     * @param type the type of daylight saving time
+     */
+    void setDSTType(int type) {
+        dstType = type;
+    }
+
+    /**
+     * @return the type of historical daylight saving time
+     * observation.
+     */
+    int getDSTType() {
+        return dstType;
+    }
+
+    /**
+     * Adds the specified zone record to the zone records list.
+     * @param rec the zone record
+     */
+    void addUsedRec(ZoneRec rec) {
+        if (usedZoneRecs == null) {
+            usedZoneRecs = new ArrayList<ZoneRec>();
+        }
+        usedZoneRecs.add(rec);
+    }
+
+    /**
+     * Adds the specified rule record to the rule records list.
+     * @param rec the rule record
+     */
+    void addUsedRec(RuleRec rec) {
+        if (usedRuleRecs == null) {
+            usedRuleRecs = new ArrayList<RuleRec>();
+        }
+        // if the last used rec is the same as the given rec, avoid
+        // putting the same rule.
+        int n = usedRuleRecs.size();
+        for (int i = 0; i < n; i++) {
+            if (usedRuleRecs.get(i).equals(rec)) {
+                return;
+            }
+        }
+        usedRuleRecs.add(rec);
+    }
+
+    /**
+     * Sets the last zone record for this time zone.
+     * @param the last zone record
+     */
+    void setLastZoneRec(ZoneRec zrec) {
+        lastZoneRec = zrec;
+    }
+
+    /**
+     * @return the last zone record for this time zone.
+     */
+    ZoneRec getLastZoneRec() {
+        return lastZoneRec;
+    }
+
+    /**
+     * Sets the last rule records for this time zone. Those are used
+     * for generating SimpleTimeZone parameters.
+     * @param rules the last rule records
+     */
+    void setLastRules(List<RuleRec> rules) {
+        int n = rules.size();
+        if (n > 0) {
+            lastRules = rules;
+            RuleRec rec = rules.get(0);
+            int offset = rec.getSave();
+            if (offset > 0) {
+                setLastDSTSaving(offset);
+            } else {
+                System.err.println("\t    No DST starting rule in the last rules.");
+            }
+        }
+    }
+
+    /**
+     * @return the last rule records for this time zone.
+     */
+    List<RuleRec> getLastRules() {
+        return lastRules;
+    }
+
+    /**
+     * Sets the last daylight saving amount.
+     * @param the daylight saving amount
+     */
+    void setLastDSTSaving(int offset) {
+        lastSaving = offset;
+    }
+
+    /**
+     * @return the last daylight saving amount.
+     */
+    int getLastDSTSaving() {
+        return lastSaving;
+    }
+
+    /**
+     * Calculates the CRC32 value from the transition table and sets
+     * the value to <code>crc32</code>.
+     */
+    void checksum() {
+        if (transitions == null) {
+            crc32 = 0;
+            return;
+        }
+        Checksum sum = new Checksum();
+        for (int i = 0; i < transitions.size(); i++) {
+            int offset = offsets.get(i);
+            // adjust back to make the transition in local time
+            sum.update(transitions.get(i) + offset);
+            sum.update(offset);
+            sum.update(dstOffsets.get(i));
+        }
+        crc32 = (int)sum.getValue();
+    }
+
+    /**
+     * Removes unnecessary transitions for Java time zone support.
+     */
+    void optimize() {
+        // if there is only one offset, delete all transitions. This
+        // could happen if only time zone abbreviations changed.
+        if (gmtOffsets.size() == 1) {
+            transitions = null;
+            usedRuleRecs =  null;
+            setDSTType(NO_DST);
+            return;
+        }
+        for (int i = 0; i < (transitions.size() - 2); i++) { // don't remove the last one
+            if (transitions.get(i) == transitions.get(i+1)) {
+                transitions.remove(i);
+                offsets.remove(i);
+                dstOffsets.remove(i);
+                i--;
+            }
+        }
+
+        for (int i = 0; i < (transitions.size() - 2); i++) { // don't remove the last one
+            if (offsets.get(i) == offsets.get(i+1)
+                && dstOffsets.get(i) == dstOffsets.get(i+1)) {
+                transitions.remove(i+1);
+                offsets.remove(i+1);
+                dstOffsets.remove(i+1);
+                i--;
+            }
+        }
+    }
+
+    /**
+     * Stores the specified offset value from GMT in the GMT offsets
+     * table and returns its index. The offset value includes the base
+     * GMT offset and any additional daylight saving if applicable. If
+     * the same value as the specified offset is already in the table,
+     * its index is returned.
+     * @param offset the offset value in milliseconds
+     * @return the index to the offset value in the GMT offsets table.
+     */
+    int getOffsetIndex(int offset) {
+        return getOffsetIndex(offset, 0);
+    }
+
+    /**
+     * Stores the specified daylight saving value in the GMT offsets
+     * table and returns its index. If the same value as the specified
+     * offset is already in the table, its index is returned. If 0 is
+     * specified, it's not stored in the table and -1 is returned.
+     * @param offset the offset value in milliseconds
+     * @return the index to the specified offset value in the GMT
+     * offsets table, or -1 if 0 is specified.
+     */
+    int getDstOffsetIndex(int offset) {
+        if (offset == 0) {
+            return -1;
+        }
+        return getOffsetIndex(offset, 1);
+    }
+
+    private int getOffsetIndex(int offset, int index) {
+        if (gmtOffsets == null) {
+            gmtOffsets = new ArrayList<Integer>();
+        }
+        for (int i = index; i < gmtOffsets.size(); i++) {
+            if (offset == gmtOffsets.get(i)) {
+                return i;
+            }
+        }
+        if (gmtOffsets.size() < index) {
+            gmtOffsets.add(0);
+        }
+        gmtOffsets.add(offset);
+        return gmtOffsets.size() - 1;
+    }
+}