/* * ----------------------------------------------------------------------- * Copyright © 2013-2015 Meno Hochschild, <http://www.menodata.de/> * ----------------------------------------------------------------------- * This file (DaylightSavingRule.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 <http://www.gnu.org/licenses/>. * ----------------------------------------------------------------------- */ package net.time4j.tz.model; import net.time4j.ClockUnit; import net.time4j.PlainDate; import net.time4j.PlainTime; import net.time4j.base.GregorianDate; import net.time4j.format.CalendarType; /** * <p>Defines a yearly pattern when and how there is a switch from winter * to summer time and vice versa. </p> * * <p>This rule describes when such a switch happens. It also determines * the DST-offset. For every rule instance, a {@code ZonalTransition} can * be created just by indicating the appropriate year and standard offset. * The change from winter to summer time and back is usually expressed * by two rule instances. </p> * * <p>Note: The term "year" denotes the year in any calendar which * is not necessarily the gregorian one. Subclasses need to define the * calendar type and some calendar-specific year conversions. If subclasses * also want to be serializable then they have to apply the * <i>serialization proxy pattern</i> described by Joshua Bloch. </p> * * @author Meno Hochschild * @since 2.2 */ /*[deutsch] * <p>Definiert ein jährliches Muster, wann und wie im Jahr eine Umstellung * von Winter- zu Sommerzeit oder zurück stattfindet. </p> * * <p>Dieses Muster beschreibt zum einen, wie ein solcher Umstellungszeitpunkt * festgelegt werden kann. Außerdem wird ein DST-Offset festgelegt. * Somit kann nur mit der zusätzlichen Angabe eines Standard-Offsets pro * Jahr genau eine {@code ZonalTransition} erzeugt werden. Der Wechsel von * Winter- zu Sommerzeit und zurück wird im allgemeinen durch zwei * Instanzen dieser Klasse ausgedrückt. </p> * * <p>Hinweis: Der Begriff "year" zeigt das Jahr in irgendeinem * Kalender an, der nicht notwendig der gregorianische Kalender sein muß. * Subklassen müssen den Kalendertyp und einige kalenderspezifische * Jahreskonversionen definieren. Wenn Subklassen auch serialisierbar sein * wollen, müssen sie das <i>serialization proxy pattern</i> realisieren, * das von Joshua Bloch beschrieben worden ist. </p> * * @author Meno Hochschild * @since 2.2 */ public abstract class DaylightSavingRule { //~ Instanzvariablen -------------------------------------------------- private transient final PlainTime timeOfDay; private transient final OffsetIndicator indicator; private transient final int savings; //~ Konstruktoren ----------------------------------------------------- /** * <p>For non-standard subclasses only. </p> * * @param timeOfDay time of day when the rule switches the offset * @param indicator offset indicator * @param savings daylight saving offset in effect after this rule * @throws IllegalArgumentException if the last argument is negative */ /*[deutsch] * <p>Nur für nicht-standardisierte Subklassen. </p> * * @param timeOfDay time of day when the rule switches the offset * @param indicator offset indicator * @param savings daylight saving offset in effect after this rule * @throws IllegalArgumentException if the last argument is negative */ protected DaylightSavingRule( PlainTime timeOfDay, OffsetIndicator indicator, int savings ) { super(); if (timeOfDay == null) { throw new NullPointerException("Missing time of day."); } else if (indicator == null) { throw new NullPointerException("Missing offset indicator."); } else if (savings < 0) { throw new IllegalArgumentException( "Negative daylight saving offset: " + savings); } this.timeOfDay = timeOfDay.with(PlainTime.PRECISION, ClockUnit.SECONDS); this.indicator = indicator; this.savings = savings; } //~ Methoden ---------------------------------------------------------- /** * <p>Determines the date of time switch dependent on given year. </p> * * <p>The result must be interpreted by mean of {@link #getIndicator()} * in order to calculate the UTC date. </p> * * @param year reference year when a time switch happens * @return calendar date of time switch * @throws IllegalArgumentException if given year does not fit to this rule * @since 2.2 */ /*[deutsch] * <p>Liefert das Datum der Zeitumstellung in Abhängigkeit * vom angegebenen Jahr. </p> * * <p>Das Ergebnis ist mittels {@link #getIndicator()} geeignet * zu interpretieren, um das UTC-Datum zu bestimmen. </p> * * @param year Bezugsjahr, in dem eine Winter- oder * Sommerzeitumstellung stattfindet * @return Datum der Umstellung * @throws IllegalArgumentException wenn das Jahr nicht passt * @since 2.2 */ public abstract PlainDate getDate(int year); /** * <p>Determines the clock time when the switch from winter time to * summer time happens or vice versa. </p> * * <p>The result must be interpreted by mean of {@link #getIndicator()} * in order to calculate the UTC time. </p> * * @return clock time of time switch in second precision * @since 2.2 */ /*[deutsch] * <p>Liefert die Uhrzeit der Zeitumstellung. </p> * * <p>Das Ergebnis ist mittels {@link #getIndicator()} geeignet * zu interpretieren, um die UTC-Zeit zu bestimmen. </p> * * @return Uhrzeit der Umstellung in second precision * @since 2.2 */ public PlainTime getTimeOfDay() { return this.timeOfDay; } /** * <p>Yields the offset indicator which must be consulted when interpreting * the date and time of time switch in terms of UTC. </p> * * @return OffsetIndicator * @since 2.2 */ /*[deutsch] * <p>Liefert den Offset-Indikator, der zur Interpretation des Datums * und der Uhrzeit der Zeitumstellung im UTC-Kontext dient. </p> * * @return OffsetIndicator * @since 2.2 */ public OffsetIndicator getIndicator() { return this.indicator; } /** * <p>Yields the daylight saving amount after the time switch * in seconds. </p> * * @return DST-Offset in seconds (without standard offset) * @since 2.2 */ /*[deutsch] * <p>Liefert den DST-Offset nach der Umstellung in Sekunden. </p> * * @return reiner DST-Offset in Sekunden (ohne Standard-Offset) * @since 2.2 */ public int getSavings() { return this.savings; } /** * <p>Extracts the year from given epoch days. </p> * * @param mjd modified julian date * @return year (maybe in a non-gregorian calendar) * @since 2.2 */ /*[deutsch] * <p>Ermittelt das kalenderspezifische Jahr auf Basis der angegebenen * Epochentage. </p> * * @param mjd modified julian date * @return year (maybe in a non-gregorian calendar) * @since 2.2 */ protected abstract int toCalendarYear(long mjd); /** * <p>Extracts the year from given gregorian date. </p> * * @param date gregorian calendar date * @return year (maybe in a non-gregorian calendar) * @since 2.2 */ /*[deutsch] * <p>Ermittelt das kalenderspezifische Jahr auf Basis des angegebenen * gregorianischen Kalenderdatums. </p> * * @param date gregorian calendar date * @return year (maybe in a non-gregorian calendar) * @since 2.2 */ protected abstract int toCalendarYear(GregorianDate date); /** * <p>Determines the underlying calendar system. </p> * * @return String describing the calendar * @throws IllegalStateException if the subclass does not have any * annotation of type {@link net.time4j.format.CalendarType} * @since 2.2 */ /*[deutsch] * <p>Bestimmt das zugrundeliegende Kalendersystem. </p> * * @return String describing the calendar * @throws IllegalStateException if the subclass does not have any * annotation of type {@link net.time4j.format.CalendarType} * @since 2.2 */ protected String getCalendarType() { CalendarType ct = this.getClass().getAnnotation(CalendarType.class); if (ct == null) { throw new IllegalStateException( "Cannot find calendar type annotation: " + this.getClass()); } return ct.value(); } // benutzt in der Serialisierung int getType() { return 0; // default value for unknown type } }