Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/make/src/classes/build/tools/tzdb/ZoneOffsetTransition.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) 2009-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.util.Arrays;64import java.util.Collections;65import java.util.List;66import java.util.Objects;6768/**69* A transition between two offsets caused by a discontinuity in the local time-line.70*71* @since 1.872*/73final class ZoneOffsetTransition implements Comparable<ZoneOffsetTransition> {7475/**76* The local transition date-time at the transition.77*/78private final LocalDateTime transition;79/**80* The offset before transition.81*/82private final ZoneOffset offsetBefore;83/**84* The offset after transition.85*/86private final ZoneOffset offsetAfter;8788/**89* Creates an instance defining a transition between two offsets.90*91* @param transition the transition date-time with the offset before the transition, not null92* @param offsetBefore the offset before the transition, not null93* @param offsetAfter the offset at and after the transition, not null94*/95ZoneOffsetTransition(LocalDateTime transition, ZoneOffset offsetBefore, ZoneOffset offsetAfter) {96Objects.requireNonNull(transition, "transition");97Objects.requireNonNull(offsetBefore, "offsetBefore");98Objects.requireNonNull(offsetAfter, "offsetAfter");99if (offsetBefore.equals(offsetAfter)) {100throw new IllegalArgumentException("Offsets must not be equal");101}102this.transition = transition;103this.offsetBefore = offsetBefore;104this.offsetAfter = offsetAfter;105}106107/**108* Creates an instance from epoch-second and offsets.109*110* @param epochSecond the transition epoch-second111* @param offsetBefore the offset before the transition, not null112* @param offsetAfter the offset at and after the transition, not null113*/114ZoneOffsetTransition(long epochSecond, ZoneOffset offsetBefore, ZoneOffset offsetAfter) {115this.transition = LocalDateTime.ofEpochSecond(epochSecond, 0, offsetBefore);116this.offsetBefore = offsetBefore;117this.offsetAfter = offsetAfter;118}119120/**121* Gets the transition instant as an epoch second.122*123* @return the transition epoch second124*/125public long toEpochSecond() {126return transition.toEpochSecond(offsetBefore);127}128129/**130* Gets the local transition date-time, as would be expressed with the 'before' offset.131* <p>132* This is the date-time where the discontinuity begins expressed with the 'before' offset.133* At this instant, the 'after' offset is actually used, therefore the combination of this134* date-time and the 'before' offset will never occur.135* <p>136* The combination of the 'before' date-time and offset represents the same instant137* as the 'after' date-time and offset.138*139* @return the transition date-time expressed with the before offset, not null140*/141public LocalDateTime getDateTimeBefore() {142return transition;143}144145/**146* Gets the local transition date-time, as would be expressed with the 'after' offset.147* <p>148* This is the first date-time after the discontinuity, when the new offset applies.149* <p>150* The combination of the 'before' date-time and offset represents the same instant151* as the 'after' date-time and offset.152*153* @return the transition date-time expressed with the after offset, not null154*/155public LocalDateTime getDateTimeAfter() {156return transition.plusSeconds(getDurationSeconds());157}158159/**160* Gets the offset before the transition.161* <p>162* This is the offset in use before the instant of the transition.163*164* @return the offset before the transition, not null165*/166public ZoneOffset getOffsetBefore() {167return offsetBefore;168}169170/**171* Gets the offset after the transition.172* <p>173* This is the offset in use on and after the instant of the transition.174*175* @return the offset after the transition, not null176*/177public ZoneOffset getOffsetAfter() {178return offsetAfter;179}180181/**182* Gets the duration of the transition in seconds.183*184* @return the duration in seconds185*/186private int getDurationSeconds() {187return getOffsetAfter().getTotalSeconds() - getOffsetBefore().getTotalSeconds();188}189190/**191* Does this transition represent a gap in the local time-line.192* <p>193* Gaps occur where there are local date-times that simply do not not exist.194* An example would be when the offset changes from {@code +01:00} to {@code +02:00}.195* This might be described as 'the clocks will move forward one hour tonight at 1am'.196*197* @return true if this transition is a gap, false if it is an overlap198*/199public boolean isGap() {200return getOffsetAfter().getTotalSeconds() > getOffsetBefore().getTotalSeconds();201}202203/**204* Does this transition represent a gap in the local time-line.205* <p>206* Overlaps occur where there are local date-times that exist twice.207* An example would be when the offset changes from {@code +02:00} to {@code +01:00}.208* This might be described as 'the clocks will move back one hour tonight at 2am'.209*210* @return true if this transition is an overlap, false if it is a gap211*/212public boolean isOverlap() {213return getOffsetAfter().getTotalSeconds() < getOffsetBefore().getTotalSeconds();214}215216/**217* Checks if the specified offset is valid during this transition.218* <p>219* This checks to see if the given offset will be valid at some point in the transition.220* A gap will always return false.221* An overlap will return true if the offset is either the before or after offset.222*223* @param offset the offset to check, null returns false224* @return true if the offset is valid during the transition225*/226public boolean isValidOffset(ZoneOffset offset) {227return isGap() ? false : (getOffsetBefore().equals(offset) || getOffsetAfter().equals(offset));228}229230/**231* Gets the valid offsets during this transition.232* <p>233* A gap will return an empty list, while an overlap will return both offsets.234*235* @return the list of valid offsets236*/237List<ZoneOffset> getValidOffsets() {238if (isGap()) {239return Collections.emptyList();240}241return Arrays.asList(getOffsetBefore(), getOffsetAfter());242}243244/**245* Compares this transition to another based on the transition instant.246* <p>247* This compares the instants of each transition.248* The offsets are ignored, making this order inconsistent with equals.249*250* @param transition the transition to compare to, not null251* @return the comparator value, negative if less, positive if greater252*/253@Override254public int compareTo(ZoneOffsetTransition transition) {255return Long.compare(this.toEpochSecond(), transition.toEpochSecond());256}257258/**259* Checks if this object equals another.260* <p>261* The entire state of the object is compared.262*263* @param other the other object to compare to, null returns false264* @return true if equal265*/266@Override267public boolean equals(Object other) {268if (other == this) {269return true;270}271if (other instanceof ZoneOffsetTransition) {272ZoneOffsetTransition d = (ZoneOffsetTransition) other;273return transition.equals(d.transition) &&274offsetBefore.equals(d.offsetBefore) && offsetAfter.equals(d.offsetAfter);275}276return false;277}278279/**280* Returns a suitable hash code.281*282* @return the hash code283*/284@Override285public int hashCode() {286return transition.hashCode() ^ offsetBefore.hashCode() ^ Integer.rotateLeft(offsetAfter.hashCode(), 16);287}288289}290291292