--- /dev/null 2013-01-18 16:17:08.886776012 -0800 +++ new/test/sun/util/calendar/zi/Timezone.java 2013-02-06 22:33:48.000000000 -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 transitions; + + /** + * All offset values in millisecond + * @see sun.util.calendar.ZoneInfo + */ + private List offsets; + + /** + * Indices of GMT offset values (both raw and raw+saving) + * at transitions + */ + private List gmtOffsets; + + /** + * Indices of regular or "direct" saving time values + * at transitions + */ + private List dstOffsets; + + /** + * Zone records of this time zone + */ + private List usedZoneRecs; + + /** + * Rule records referred to by this time zone + */ + private List 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 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 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 getZones() { + return usedZoneRecs; + } + + /** + * @return the transition table (list) + */ + List getTransitions() { + return transitions; + } + + /** + * @return the offsets list + */ + List getOffsets() { + return offsets; + } + + /** + * @return the DST saving offsets list + */ + List getDstOffsets() { + return dstOffsets; + } + + /** + * @return the GMT offsets list + */ + List 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 offset. + * @param offset the GMT offset value in milliseconds + */ + void setRawOffset(int offset) { + rawOffset = offset; + } + + /** + * Sets time zone's GMT offset value to offset. If + * startTime 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(); + offsets = new ArrayList(); + dstOffsets = new ArrayList(); + } + 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(); + } + 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(); + } + // 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 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 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 crc32. + */ + 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(); + } + 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; + } +}