Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/make/src/classes/build/tools/tzdb/ZoneRules.java
32287 views
/*1* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/*26* This file is available under and governed by the GNU General Public27* License version 2 only, as published by the Free Software Foundation.28* However, the following notice accompanied the original version of this29* file:30*31* Copyright (c) 2011-2012, Stephen Colebourne & Michael Nascimento Santos32*33* All rights reserved.34*35* Redistribution and use in source and binary forms, with or without36* modification, are permitted provided that the following conditions are met:37*38* * Redistributions of source code must retain the above copyright notice,39* this list of conditions and the following disclaimer.40*41* * Redistributions in binary form must reproduce the above copyright notice,42* this list of conditions and the following disclaimer in the documentation43* and/or other materials provided with the distribution.44*45* * Neither the name of JSR-310 nor the names of its contributors46* may be used to endorse or promote products derived from this software47* without specific prior written permission.48*49* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS50* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT51* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR52* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR53* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,54* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,55* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR56* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF57* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING58* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS59* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.60*/61package build.tools.tzdb;6263import java.io.DataOutput;64import java.io.IOException;65import java.io.ObjectOutput;66import java.util.Arrays;67import java.util.ArrayList;68import java.util.List;6970/**71* Duplicated code of javax.time.zone.ZoneRules, ZoneOffsetTransitionRule72* and Ser to generate the serialization form output of ZoneRules for73* tzdb.jar.74*75* Implementation here is the copy/paste of ZoneRules, ZoneOffsetTransitionRule76* and Ser in javax.time.zone package. Make sure the code here is synchrionozed77* with the serialization implementation there.78*79* @since 1.880*/8182final class ZoneRules {8384/**85* The transitions between standard offsets (epoch seconds), sorted.86*/87private final long[] standardTransitions;88/**89* The standard offsets.90*/91private final ZoneOffset[] standardOffsets;92/**93* The transitions between instants (epoch seconds), sorted.94*/95private final long[] savingsInstantTransitions;9697/**98* The wall offsets.99*/100private final ZoneOffset[] wallOffsets;101/**102* The last rule.103*/104private final ZoneOffsetTransitionRule[] lastRules;105106/**107* Creates an instance.108*109* @param baseStandardOffset the standard offset to use before legal rules were set, not null110* @param baseWallOffset the wall offset to use before legal rules were set, not null111* @param standardOffsetTransitionList the list of changes to the standard offset, not null112* @param transitionList the list of transitions, not null113* @param lastRules the recurring last rules, size 16 or less, not null114*/115ZoneRules(ZoneOffset baseStandardOffset,116ZoneOffset baseWallOffset,117List<ZoneOffsetTransition> standardOffsetTransitionList,118List<ZoneOffsetTransition> transitionList,119List<ZoneOffsetTransitionRule> lastRules) {120121this.standardTransitions = new long[standardOffsetTransitionList.size()];122123this.standardOffsets = new ZoneOffset[standardOffsetTransitionList.size() + 1];124this.standardOffsets[0] = baseStandardOffset;125for (int i = 0; i < standardOffsetTransitionList.size(); i++) {126this.standardTransitions[i] = standardOffsetTransitionList.get(i).toEpochSecond();127this.standardOffsets[i + 1] = standardOffsetTransitionList.get(i).getOffsetAfter();128}129130// convert savings transitions to locals131List<ZoneOffset> localTransitionOffsetList = new ArrayList<>();132localTransitionOffsetList.add(baseWallOffset);133for (ZoneOffsetTransition trans : transitionList) {134localTransitionOffsetList.add(trans.getOffsetAfter());135}136137this.wallOffsets = localTransitionOffsetList.toArray(new ZoneOffset[localTransitionOffsetList.size()]);138139// convert savings transitions to instants140this.savingsInstantTransitions = new long[transitionList.size()];141for (int i = 0; i < transitionList.size(); i++) {142this.savingsInstantTransitions[i] = transitionList.get(i).toEpochSecond();143}144145// last rules146if (lastRules.size() > 16) {147throw new IllegalArgumentException("Too many transition rules");148}149this.lastRules = lastRules.toArray(new ZoneOffsetTransitionRule[lastRules.size()]);150}151152/** Type for ZoneRules. */153static final byte ZRULES = 1;154155/**156* Writes the state to the stream.157*158* @param out the output stream, not null159* @throws IOException if an error occurs160*/161void writeExternal(DataOutput out) throws IOException {162out.writeByte(ZRULES);163out.writeInt(standardTransitions.length);164for (long trans : standardTransitions) {165writeEpochSec(trans, out);166}167for (ZoneOffset offset : standardOffsets) {168writeOffset(offset, out);169}170out.writeInt(savingsInstantTransitions.length);171for (long trans : savingsInstantTransitions) {172writeEpochSec(trans, out);173}174for (ZoneOffset offset : wallOffsets) {175writeOffset(offset, out);176}177out.writeByte(lastRules.length);178for (ZoneOffsetTransitionRule rule : lastRules) {179writeRule(rule, out);180}181}182183/**184* Writes the state the ZoneOffset to the stream.185*186* @param offset the offset, not null187* @param out the output stream, not null188* @throws IOException if an error occurs189*/190static void writeOffset(ZoneOffset offset, DataOutput out) throws IOException {191final int offsetSecs = offset.getTotalSeconds();192int offsetByte = offsetSecs % 900 == 0 ? offsetSecs / 900 : 127; // compress to -72 to +72193out.writeByte(offsetByte);194if (offsetByte == 127) {195out.writeInt(offsetSecs);196}197}198199/**200* Writes the epoch seconds to the stream.201*202* @param epochSec the epoch seconds, not null203* @param out the output stream, not null204* @throws IOException if an error occurs205*/206static void writeEpochSec(long epochSec, DataOutput out) throws IOException {207if (epochSec >= -4575744000L && epochSec < 10413792000L && epochSec % 900 == 0) { // quarter hours between 1825 and 2300208int store = (int) ((epochSec + 4575744000L) / 900);209out.writeByte((store >>> 16) & 255);210out.writeByte((store >>> 8) & 255);211out.writeByte(store & 255);212} else {213out.writeByte(255);214out.writeLong(epochSec);215}216}217218/**219* Writes the state of the transition rule to the stream.220*221* @param rule the transition rule, not null222* @param out the output stream, not null223* @throws IOException if an error occurs224*/225static void writeRule(ZoneOffsetTransitionRule rule, DataOutput out) throws IOException {226int month = rule.month;227byte dom = rule.dom;228int dow = rule.dow;229LocalTime time = rule.time;230boolean timeEndOfDay = rule.timeEndOfDay;231TimeDefinition timeDefinition = rule.timeDefinition;232ZoneOffset standardOffset = rule.standardOffset;233ZoneOffset offsetBefore = rule.offsetBefore;234ZoneOffset offsetAfter = rule.offsetAfter;235236int timeSecs = (timeEndOfDay ? 86400 : time.toSecondOfDay());237int stdOffset = standardOffset.getTotalSeconds();238int beforeDiff = offsetBefore.getTotalSeconds() - stdOffset;239int afterDiff = offsetAfter.getTotalSeconds() - stdOffset;240int timeByte = (timeSecs % 3600 == 0 ? (timeEndOfDay ? 24 : time.getHour()) : 31);241int stdOffsetByte = (stdOffset % 900 == 0 ? stdOffset / 900 + 128 : 255);242int beforeByte = (beforeDiff == 0 || beforeDiff == 1800 || beforeDiff == 3600 ? beforeDiff / 1800 : 3);243int afterByte = (afterDiff == 0 || afterDiff == 1800 || afterDiff == 3600 ? afterDiff / 1800 : 3);244int dowByte = (dow == -1 ? 0 : dow);245int b = (month << 28) + // 4 bytes246((dom + 32) << 22) + // 6 bytes247(dowByte << 19) + // 3 bytes248(timeByte << 14) + // 5 bytes249(timeDefinition.ordinal() << 12) + // 2 bytes250(stdOffsetByte << 4) + // 8 bytes251(beforeByte << 2) + // 2 bytes252afterByte; // 2 bytes253out.writeInt(b);254if (timeByte == 31) {255out.writeInt(timeSecs);256}257if (stdOffsetByte == 255) {258out.writeInt(stdOffset);259}260if (beforeByte == 3) {261out.writeInt(offsetBefore.getTotalSeconds());262}263if (afterByte == 3) {264out.writeInt(offsetAfter.getTotalSeconds());265}266}267268/**269* Checks if this set of rules equals another.270* <p>271* Two rule sets are equal if they will always result in the same output272* for any given input instant or local date-time.273* Rules from two different groups may return false even if they are in fact the same.274* <p>275* This definition should result in implementations comparing their entire state.276*277* @param otherRules the other rules, null returns false278* @return true if this rules is the same as that specified279*/280@Override281public boolean equals(Object otherRules) {282if (this == otherRules) {283return true;284}285if (otherRules instanceof ZoneRules) {286ZoneRules other = (ZoneRules) otherRules;287return Arrays.equals(standardTransitions, other.standardTransitions) &&288Arrays.equals(standardOffsets, other.standardOffsets) &&289Arrays.equals(savingsInstantTransitions, other.savingsInstantTransitions) &&290Arrays.equals(wallOffsets, other.wallOffsets) &&291Arrays.equals(lastRules, other.lastRules);292}293return false;294}295296/**297* Returns a suitable hash code given the definition of {@code #equals}.298*299* @return the hash code300*/301@Override302public int hashCode() {303return Arrays.hashCode(standardTransitions) ^304Arrays.hashCode(standardOffsets) ^305Arrays.hashCode(savingsInstantTransitions) ^306Arrays.hashCode(wallOffsets) ^307Arrays.hashCode(lastRules);308}309310}311312313