All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.time4j.tz.ZonalTransition Maven / Gradle / Ivy

There is a newer version: 4.38
Show newest version
/*
 * -----------------------------------------------------------------------
 * Copyright © 2013-2015 Meno Hochschild, 
 * -----------------------------------------------------------------------
 * This file (ZonalTransition.java) is part of project Time4J.
 *
 * Time4J is free software: You can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * Time4J 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Time4J. If not, see .
 * -----------------------------------------------------------------------
 */

package net.time4j.tz;

import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.Serializable;


/**
 * 

Represents the change of a shift of the local time relative to * POSIX-time in any timezone.

* *

This class contains informations about the global timestamp of the * transition and the shifts/offsets before and after the transitions. * A change of a zonal shift can either be caused by special historical * events and political actions (change of standard time) or by establishing * daylight saving-rules (change from winter time to summer time and * reverse - DST). Therefore the total shift {@code getTotalOffset()} is * always the sum of the parts {@code getStandardOffset()} and * {@code getDaylightSavingOffset()}.

* *

Shifts are described on the local timeline in seconds. Following * relationship holds between local time and POSIX-time:

* *

{@code getTotalOffset() = [Local Wall Time] - [POSIX Time]}

* *

A zonal transition induces a gap on the local timeline if the new * shift is greater than the old shift. And an overlap occurs if the new * shift is smaller than the old shift. A local time is not defined within * gaps and ambivalent in overlapping regions.

* * @author Meno Hochschild * @doctags.concurrency {immutable} */ /*[deutsch] *

Beschreibt einen Wechsel der Verschiebung der lokalen Zeit relativ * zur POSIX-Zeit in einer Zeitzone.

* *

Diese Klasse enthält neben dem Zeitpunkt des Übergangs auch * Informationen über die Verschiebung vor und nach dem Wechsel. Ein * Wechsel der Verschiebung kann entweder durch einmalige historische bzw. * politische Änderungen (Änderung der Standardverschiebung der * Zeitzone standard time) oder durch daylight saving-Schemata * bedingt sein, also die Umstellung von Winterzeit auf Sommerzeit und * umgekehrt (DST). Somit ist die Gesamtverschiebung {@code getTotalOffset()} * immer die Summe aus den einzelnen Verschiebungsanteilen * {@code getStandardOffset()} und {@code getDaylightSavingOffset()}.

* *

Verschiebungen werden grundsätzlich auf dem lokalen Zeitstrahl einer * Zeitzone beschrieben. Es gilt somit folgende Beziehung zwischen einer * lokalen Zeit und der POSIX-Zeit (alle Angaben in Sekunden):

* *

{@code getTotalOffset() = [Local Wall Time] - [POSIX Time]}

* *

An einem Übergang tritt eine Lücke auf dem lokalen Zeitstrahl * auf, wenn die neue Verschiebung größer als die alte Verschiebung * ist. Und eine Überlappung tritt auf, wenn die neue Verschiebung kleiner * als die alte Verschiebung ist. Eine lokale Zeitangabe ist auf Lücken * nicht definiert und auf Überlappungen zweideutig.

* * @author Meno Hochschild * @doctags.concurrency {immutable} */ public final class ZonalTransition implements Comparable, Serializable { //~ Statische Felder/Initialisierungen -------------------------------- private static final long serialVersionUID = 4594838367057225304L; //~ Instanzvariablen -------------------------------------------------- /** * @serial POSIX time in seconds since 1970-01-01T00:00:00Z */ /*[deutsch] * @serial POSIX-Zeit in Sekunden seit 1970-01-01T00:00:00Z */ private final long posix; /** * @serial previous total shift in seconds */ /*[deutsch] * @serial alte Gesamtverschiebung in Sekunden */ private final int previous; /** * @serial new total shift in seconds */ /*[deutsch] * @serial neue Gesamtverschiebung in Sekunden */ private final int total; /** * @serial new daylight-saving-shift in seconds (DST) */ /*[deutsch] * @serial neue DST-Verschiebung in Sekunden */ private final int dst; //~ Konstruktoren ----------------------------------------------------- /** *

Creates a new transition between two shifts.

* * @param posixTime POSIX time of transition * @param previousOffset previous total shift in seconds * @param totalOffset new total shift in seconds * @param daylightSavingOffset DST-shift in seconds * @throws IllegalArgumentException if the DST-shift is negative or if any * offset is out of range {@code -18 * 3600 <= total <= 18 * 3600} * @see net.time4j.scale.UniversalTime#getPosixTime() * @see ZonalOffset#getIntegralAmount() */ /*[deutsch] *

Konstruiert einen neuen Übergang zwischen zwei * Verschiebungen.

* * @param posixTime POSIX time of transition * @param previousOffset previous total shift in seconds * @param totalOffset new total shift in seconds * @param daylightSavingOffset DST-shift in seconds * @throws IllegalArgumentException if the DST-shift is negative or if any * offset is out of range {@code -18 * 3600 <= total <= 18 * 3600} * @see net.time4j.scale.UniversalTime#getPosixTime() * @see ZonalOffset#getIntegralAmount() */ public ZonalTransition( long posixTime, int previousOffset, int totalOffset, int daylightSavingOffset ) { this.posix = posixTime; this.previous = previousOffset; this.total = totalOffset; this.dst = daylightSavingOffset; checkRange(previousOffset); checkRange(totalOffset); checkDST(daylightSavingOffset); } //~ Methoden ---------------------------------------------------------- /** *

Returns the global timestamp of this transition from one shift to * another as POSIX-timestamp.

* * @return transition time relative to [1970-01-01T00:00:00] in seconds * (without leap seconds) * @see net.time4j.scale.TimeScale#POSIX */ /*[deutsch] *

Stellt die Zeit des Übergangs von einer Verschiebung zur anderen * als POSIX-Zeit dar.

* * @return transition time relative to [1970-01-01T00:00:00] in seconds * (without leap seconds) * @see net.time4j.scale.TimeScale#POSIX */ public long getPosixTime() { return this.posix; } /** *

Returns the total shift before this transition.

* * @return previous total shift in seconds * @see #getTotalOffset() * @see ZonalOffset#getIntegralAmount() */ /*[deutsch] *

Liefert die Gesamtverschiebung vor diesem Übergang.

* * @return previous total shift in seconds * @see #getTotalOffset() * @see ZonalOffset#getIntegralAmount() */ public int getPreviousOffset() { return this.previous; } /** *

Returns the total shift after this transition.

* * @return new total shift in seconds * @see #getPreviousOffset() * @see #getStandardOffset() * @see #getDaylightSavingOffset() * @see #isDaylightSaving() * @see ZonalOffset#getIntegralAmount() */ /*[deutsch] *

Liefert die Gesamtverschiebung nach diesem Übergang.

* * @return new total shift in seconds * @see #getPreviousOffset() * @see #getStandardOffset() * @see #getDaylightSavingOffset() * @see #isDaylightSaving() * @see ZonalOffset#getIntegralAmount() */ public int getTotalOffset() { return this.total; } /** *

Returns the standard shift after this transition as difference * between total shift and DST-shift (daylight savings).

* *

Negative standard shifts are related to timezones west for * Greenwich, positive to timezones east for Greenwich. The addition * of the standard shift to POSIX-time yields the * standard local time corresponding to winter time.

* * @return raw shift in seconds after transition * @see #getTotalOffset() * @see #getDaylightSavingOffset() * @see #isDaylightSaving() */ /*[deutsch] *

Liefert die aktuelle Standardverschiebung nach diesem Übergang * als Differenz zwischen Gesamtverschiebung und DST-Verschiebung.

* *

Negative Standardverschiebungen beziehen sich auf Zeitzonen westlich * des Nullmeridians von Greenwich, positive auf Zeitzonen östlich * davon. Die Addition dieser Verschiebung zur POSIX-Zeit ergibt die * standard local time, die der Winterzeit entspricht.

* * @return raw shift in seconds after transition * @see #getTotalOffset() * @see #getDaylightSavingOffset() * @see #isDaylightSaving() */ public int getStandardOffset() { return (this.total - this.dst); } /** *

Returns the DST-shift (daylight savings) after this transition that is * the shift induced by change to summer time.

* *

If the method {@code isDaylightSaving()} yields the value {@code false} * then this method will simply yield {@code 0}.

* * @return daylight-saving-shift in seconds after transition * @see #getTotalOffset() * @see #getStandardOffset() * @see #isDaylightSaving() */ /*[deutsch] *

Liefert die DST-Verschiebung nach dem Übergang, also den durch * die Sommerzeit induzierten Versatz.

* *

Wenn die Methode {@code isDaylightSaving()} den Wert {@code false} * ergibt, dann liefert diese Methode einfach nur den Wert {@code 0}.

* * @return daylight-saving-shift in seconds after transition * @see #getTotalOffset() * @see #getStandardOffset() * @see #isDaylightSaving() */ public int getDaylightSavingOffset() { return this.dst; } /** *

Queries if there is any daylight savings after this transition.

* * @return boolean * @see #getDaylightSavingOffset() */ /*[deutsch] *

Liegt nach diesem Übergang Sommerzeit vor?

* * @return boolean * @see #getDaylightSavingOffset() */ public boolean isDaylightSaving() { return (this.dst != 0); } /** *

Gets the difference between new and old total shift as * measure for the size of this transition.

* * @return change of total shift in seconds (negative in case of overlap) */ /*[deutsch] *

Liefert die Differenz zwischen neuer und alter Gesamtverschiebung * als Maß für die Größe des Übergangs.

* * @return change of total shift in seconds (negative in case of overlap) */ public int getSize() { return (this.total - this.previous); } /** *

Queries if this transition represents a gap on the local timeline * where local timestamps are invalid.

* * @return {@code true} if this transition represents a gap (by definition * the new total shift is bigger than the previous one) * else {@code false} */ /*[deutsch] *

Ist dieser Übergang eine Lücke, während der eine * lokale Zeitangabe ungültig ist?

* * @return {@code true} if this transition represents a gap (by definition * the new total shift is bigger than the previous one) * else {@code false} */ public boolean isGap() { return (this.total > this.previous); } /** *

Queries if this transition represents an overlap on the local * timeline where local timestamps are ambivalent.

* * @return {@code true} if this transition represents an overlap (by * definition the new total shift is smaller than the previous * one) else {@code false} */ /*[deutsch] *

Ist dieser Übergang eine Überlappung, während der * eine lokale Zeitangabe nicht mehr eindeutig definiert ist?

* * @return {@code true} if this transition represents an overlap (by * definition the new total shift is smaller than the previous * one) else {@code false} */ public boolean isOverlap() { return (this.total < this.previous); } /** *

Compares preferrably the timeline order based on the global * timestamps of transitions, otherwise the total shift and finally * the DST-shift.

* *

The natural order is consistent with {@code equals()}.

*/ /*[deutsch] *

Beruht bevorzugt auf der zeitlichen Reihenfolge des POSIX-Zeitpunkts * des Übergangs, sonst auf den Gesamtverschiebungen und zuletzt auf * der DST-Verschiebung.

* *

Die natürliche Ordnung ist konsistent mit {@code equals()}.

*/ @Override public int compareTo(ZonalTransition other) { long delta = (this.posix - other.posix); if (delta == 0) { delta = (this.previous - other.previous); if (delta == 0) { delta = (this.total - other.total); if (delta == 0) { delta = (this.dst - other.dst); if (delta == 0) { return 0; } } } } return ((delta < 0) ? -1 : 1); } /** *

Based on the whole state with global POSIX-timestamp and all * internal shifts.

*/ /*[deutsch] *

Basiert auf der POSIX-Zeit und allen Verschiebungen.

*/ @Override public boolean equals(Object obj) { if (this == obj) { return true; } else if (obj instanceof ZonalTransition) { ZonalTransition that = (ZonalTransition) obj; if ( (this.posix == that.posix) && (this.previous == that.previous) && (this.total == that.total) && (this.dst == that.dst) ) { return true; } } return false; } /** *

Based on the POSIX-timestamp of the transition.

*/ /*[deutsch] *

Basiert auf der POSIX-Zeit des Übergangs.

*/ @Override public int hashCode() { return (int) (this.posix ^ (this.posix >>> 32)); } /** *

Supports debugging.

* * @return String */ /*[deutsch] *

Unterstützt Debugging-Ausgaben.

* * @return String */ @Override public String toString() { StringBuilder sb = new StringBuilder(128); sb.append("[POSIX="); sb.append(this.posix); sb.append(", previous-offset="); sb.append(this.previous); sb.append(", total-offset="); sb.append(this.total); sb.append(", dst-offset="); sb.append(this.dst); sb.append(']'); return sb.toString(); } private static void checkRange(int offset) { if ((offset < -18 * 3600) || (offset > 18 * 3600)) { throw new IllegalArgumentException( "Offset out of range: " + offset); } } private static void checkDST(int dst) { if (dst < 0) { throw new IllegalArgumentException("Negative DST: " + dst); } else if (dst > 18 * 3600) { throw new IllegalArgumentException("DST out of range: " + dst); } } /** * @serialData Checks the consistency. * @param in object input stream * @throws IOException in any case of inconsistencies * @throws ClassNotFoundException if class-loading fails */ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); try { checkRange(this.previous); checkRange(this.total); checkDST(this.dst); } catch (IllegalArgumentException iae) { throw new InvalidObjectException(iae.getMessage()); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy