/* * ----------------------------------------------------------------------- * Copyright © 2013-2016 Meno Hochschild, <http://www.menodata.de/> * ----------------------------------------------------------------------- * This file (Years.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.range; import net.time4j.CalendarUnit; import net.time4j.IsoDateUnit; import net.time4j.Weekcycle; import net.time4j.base.MathUtils; import net.time4j.engine.TimePoint; import java.text.ParseException; /** * <p>Represents a time span in gregorian or week-based years. </p> * * @param <U> generic type of year units * @author Meno Hochschild * @since 3.21/4.17 * @doctags.concurrency {immutable} */ /*[deutsch] * <p>Repräsentiert eine Zeitspanne in gregorianischen oder wochenbasierten Jahren. </p> * * @param <U> generic type of year units * @author Meno Hochschild * @since 3.21/4.17 * @doctags.concurrency {immutable} */ public final class Years<U extends IsoDateUnit> extends SingleUnitTimeSpan<U, Years<U>> { //~ Statische Felder/Initialisierungen -------------------------------- /** * <p>Constant for zero gregorian years. </p> */ /*[deutsch] * <p>Konstante für null gregorianische Jahre. </p> */ public static final Years<CalendarUnit> ZERO = new Years<>(0, CalendarUnit.YEARS); /** * <p>Constant for exactly one gregorian year. </p> */ /*[deutsch] * <p>Konstante für genau ein gregorianisches Jahr. </p> */ public static final Years<CalendarUnit> ONE = new Years<>(1, CalendarUnit.YEARS); private static final long serialVersionUID = 6288717039772347252L; //~ Konstruktoren ----------------------------------------------------- private Years( int amount, U unit ) { super(amount, unit); } //~ Methoden ---------------------------------------------------------- /** * <p>Obtains a time span in given gregorian years. </p> * * @param years count of gregorian years, maybe negative * @return time span in years * @see CalendarUnit#YEARS */ /*[deutsch] * <p>Erhält eine Zeitspanne in den angegebenen gregorianischen Jahren. </p> * * @param years count of gregorian years, maybe negative * @return time span in years * @see CalendarUnit#YEARS */ public static Years<CalendarUnit> ofGregorian(int years) { return ((years == 0) ? ZERO : (years == 1) ? ONE : new Years<>(years, CalendarUnit.YEARS)); } /** * <p>Obtains a time span in given week-based years. </p> * * <p>Week-based years have a length of either 364 or 371 days. </p> * * @param years count of week-based years, maybe negative * @return time span in years * @see CalendarUnit#weekBasedYears() */ /*[deutsch] * <p>Erhält eine Zeitspanne in den angegebenen wochenbasierten Jahren. </p> * * <p>Wochenbasierte Jahre haben eine Länge von entweder 364 oder 371 Tagen. </p> * * @param years count of week-based years, maybe negative * @return time span in years * @see CalendarUnit#weekBasedYears() */ public static Years<Weekcycle> ofWeekBased(int years) { return new Years<>(years, Weekcycle.YEARS); } /** * <p>Determines the temporal distance between given dates/time-points in gregorian years. </p> * * @param <T> generic type of time-points * @param t1 first time-point * @param t2 second time-point * @return result of year difference * @see net.time4j.PlainDate * @see net.time4j.PlainTimestamp */ /*[deutsch] * <p>Bestimmt die gregorianische Jahresdifferenz zwischen den angegebenen Zeitpunkten. </p> * * @param <T> generic type of time-points * @param t1 first time-point * @param t2 second time-point * @return result of year difference * @see net.time4j.PlainDate * @see net.time4j.PlainTimestamp */ public static <T extends TimePoint<? super CalendarUnit, T>> Years<CalendarUnit> between(T t1, T t2) { long delta = CalendarUnit.YEARS.between(t1, t2); return Years.ofGregorian(MathUtils.safeCast(delta)); } /** * <p>Determines the difference in years between given calendar years. </p> * * @param y1 first calendar year * @param y2 second calendar year * @return year difference */ /*[deutsch] * <p>Bestimmt die Jahresdifferenz zwischen den angegebenen Kalenderjahren. </p> * * @param y1 first calendar year * @param y2 second calendar year * @return year difference */ public static Years<CalendarUnit> between(CalendarYear y1, CalendarYear y2) { return Years.ofGregorian(y2.getValue() - y1.getValue()); } /** * <p>Determines the difference in years between given quarter years. </p> * * @param q1 first quarter year * @param q2 second quarter year * @return year difference */ /*[deutsch] * <p>Bestimmt die Jahresdifferenz zwischen den angegebenen Quartalen. </p> * * @param q1 first quarter year * @param q2 second quarter year * @return year difference */ public static Years<CalendarUnit> between(CalendarQuarter q1, CalendarQuarter q2) { int delta = q2.getYear() - q1.getYear(); if (delta > 0) { if (q2.getQuarter().compareTo(q1.getQuarter()) < 0) { delta--; } } else if (delta < 0) { if (q2.getQuarter().compareTo(q1.getQuarter()) > 0) { delta++; } } return Years.ofGregorian(delta); } /** * <p>Determines the difference in years between given calendar months. </p> * * @param m1 first calendar month * @param m2 second calendar month * @return year difference */ /*[deutsch] * <p>Bestimmt die Jahresdifferenz zwischen den angegebenen Kalendermonaten. </p> * * @param m1 first calendar month * @param m2 second calendar month * @return year difference */ public static Years<CalendarUnit> between(CalendarMonth m1, CalendarMonth m2) { int delta = m1.getYear() - m2.getYear(); if (delta > 0) { if (m2.getMonth().compareTo(m1.getMonth()) < 0) { delta--; } } else if (delta < 0) { if (m2.getMonth().compareTo(m1.getMonth()) > 0) { delta++; } } return Years.ofGregorian(delta); } /** * <p>Determines the difference in years between given calendar weeks. </p> * * @param w1 first calendar week * @param w2 second calendar week * @return year difference */ /*[deutsch] * <p>Bestimmt die Jahresdifferenz zwischen den angegebenen Kalenderwochen. </p> * * @param w1 first calendar week * @param w2 second calendar week * @return year difference */ public static Years<Weekcycle> between(CalendarWeek w1, CalendarWeek w2) { int delta = w2.getYear() - w1.getYear(); if (delta > 0) { if (w2.getWeek() < w1.getWeek()) { delta--; } } else if (delta < 0) { if (w2.getWeek() > w1.getWeek()) { delta++; } } return Years.ofWeekBased(delta); } /** * <p>Parses the canonical ISO-8601-format "PnY" with possible preceding minus-char. </p> * * @param period the formatted string to be parsed * @return parsed instance * @throws ParseException if given argument cannot be parsed */ /*[deutsch] * <p>Interpretiert das kanonische ISO-8601-Format "PnY" mit optionalem vorangehenden Minus-Zeichen. </p> * * @param period the formatted string to be parsed * @return parsed instance * @throws ParseException if given argument cannot be parsed */ public static Years<CalendarUnit> parseGregorian(String period) throws ParseException { int amount = SingleUnitTimeSpan.parsePeriod(period, 'Y'); return Years.ofGregorian(amount); } /** * <p>Like {@code parseGregorian(period)} but interpretes years as week-based. </p> * * @param period the formatted string to be parsed * @return parsed instance * @throws ParseException if given argument cannot be parsed * @see #parseGregorian(String) * @see CalendarUnit#weekBasedYears() */ /*[deutsch] * <p>Wie {@code parseGregorian(period)}, aber mit wochenbasierten Jahren. </p> * * @param period the formatted string to be parsed * @return parsed instance * @throws ParseException if given argument cannot be parsed * @see #parseGregorian(String) * @see CalendarUnit#weekBasedYears() */ public static Years<Weekcycle> parseWeekBased(String period) throws ParseException { int amount = SingleUnitTimeSpan.parsePeriod(period, 'Y'); return Years.ofWeekBased(amount); } @Override Years<U> with(int amount) { return new Years<>(amount, this.getUnit()); } @Override Years<U> self() { return this; } @Override void checkConsistency(U unit) { if (!unit.equals(CalendarUnit.YEARS) && !unit.equals(Weekcycle.YEARS)) { throw new IllegalArgumentException("Invalid year unit: " + unit); } } }