/*
* -----------------------------------------------------------------------
* Copyright © 2013-2014 Meno Hochschild, <http://www.menodata.de/>
* -----------------------------------------------------------------------
* This file (ProportionalElement.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;
import net.time4j.engine.ChronoEntity;
import net.time4j.engine.ChronoFunction;
import net.time4j.engine.ChronoOperator;
import java.math.BigDecimal;
/**
* <p>Defines an element which can interprete its value as proportional
* value. </p>
*
* @param <V> generic number type of element values
* @param <T> generic type of target entity an operator is applied to
* @author Meno Hochschild
*/
/*[deutsch]
* <p>Definiert ein Element, das seinen Wert als Proportionalwert
* interpretieren kann. </p>
*
* @param <V> generic number type of element values
* @param <T> generic type of target entity an operator is applied to
* @author Meno Hochschild
*/
public interface ProportionalElement<V extends Number, T>
extends AdjustableElement<V, T> {
//~ Methoden ----------------------------------------------------------
/**
* <p>Defines a query which interpretes the value of this element as
* proportional rational number within the range between minimum and
* maximum. </p>
*
* <p>Smaller elements with greater precision are not taken in account.
* Following expression serves as formula for internal calculation:
* {@code (value - min) / (max - min + 1)}. Example: </p>
*
* <pre>
* import static net.time4j.PlainTime.MINUTE_OF_HOUR;
*
* PlainTime time = PlainTime.of(12, 45, 30); // T12:45:30
* System.out.println(time.get(MINUTE_OF_HOUR.ratio()));
* // output: 0.75 [= (45 - 0) / (59 - 0 + 1)]
* </pre>
*
* <p>Note: In timezone-related timestamps possible jumps in local time
* will be conserved. That means that minimum and maximum do not take
* in account if they fall into a daylight saving gap or if there is
* any kind of offset shift between them. </p>
*
* @return query for proportional value
*/
/*[deutsch]
* <p>Definiert eine Abfrage, die den Wert dieses Elements als
* Verhältniszahl innerhalb seines Bereichs zwischen Minimum
* und Maximum interpretiert. </p>
*
* <p>Kleinere Elemente mit größerer Genauigkeit werden in der
* Berechnung nicht berücksichtigt. Als Formel wird der Ausdruck
* {@code (value - min) / (max - min + 1)} verwendet. Beispiel: </p>
*
* <pre>
* import static net.time4j.PlainTime.MINUTE_OF_HOUR;
*
* PlainTime time = PlainTime.of(12, 45, 30); // T12:45:30
* System.out.println(time.get(MINUTE_OF_HOUR.ratio()));
* // Ausgabe: 0.75 [= (45 - 0) / (59 - 0 + 1)]
* </pre>
*
* <p>Zu beachten: In zeitzonen-bezogenen Zeitstempeln bleiben eventuelle
* Zeitzonensprünge erhalten. Das bedeutet, daß Minimum und
* Maximum nicht berücksichtigen, ob sie in eine Lücke fallen
* oder zwischen ihnen ein Offset-Sprung existiert. </p>
*
* @return query for proportional value
*/
ChronoFunction<ChronoEntity<?>, BigDecimal> ratio();
/**
* <p>Adjusts any kind of entity such that this element will be set to
* the given value in lenient mode. </p>
*
* <pre>
* import static net.time4j.PlainDate.MONTH_OF_YEAR;
*
* System.out.println(
* PlainDate.of(2011, 5, 31).with(MONTH_OF_YEAR.setLenient(13)));
* // output: 2012-01-31 (addition of 13 - 5 = 8 Monaten)
* </pre>
*
* <p>Leniency does not always prevent exceptions. For example setting
* of extreme values like {@code Long.MIN_VALUE} can cause an
* {@code ArithmeticException}. Furthermore, moving the value of
* {@code SECOND_OF_MINUTE} to the past applied on a {@code Moment}
* can trigger a {@code ChronoException} if this action changes to
* the pre-UTC-era before 1972. </p>
*
* @param value new value to be set in lenient way
* @return operator directly applicable also on {@code PlainTimestamp}
*/
/*[deutsch]
* <p>Passt eine beliebige Entität so an, daß dieses Element
* auf den angegebenen Wert im Nachsichtigkeitsmodus gesetzt wird. </p>
*
* <pre>
* import static net.time4j.PlainDate.MONTH_OF_YEAR;
*
* System.out.println(
* PlainDate.of(2011, 5, 31).with(MONTH_OF_YEAR.setLenient(13)));
* // Ausgabe: 2012-01-31 (Addition von 13 - 5 = 8 Monaten)
* </pre>
*
* <p>Nachsichtigkeit bedeutet nicht, daß eine Ausnahme
* unmöglich ist. Zum Beispiel kann das Setzen von extremen Werten
* wie {@code Long.MIN_VALUE} eine {@code ArithmeticException} verursachen.
* Auch kann etwa das Setzen des Elements {@code SECOND_OF_MINUTE}
* auf einen {@code Moment} angewandt eine {@code ChronoException}
* auslösen, wenn damit ein Wechsel von der UTC-Ära in die
* UT-Ära vor 1972 verbunden ist. </p>
*
* @param value new value to be set in lenient way
* @return operator directly applicable also on {@code PlainTimestamp}
*/
ElementOperator<T> setLenient(V value);
/**
* <p>Rounds this chronological element up and makes its numerical
* value an integral multiple of given step width if possible. </p>
*
* <pre>
* import static net.time4j.PlainTime.MINUTE_OF_HOUR;
*
* System.out.println(
* PlainTime.of(18, 38).with(MINUTE_OF_HOUR.roundedUp(15)));
* // output: T18:45
* </pre>
*
* <p>The new element value will always be set in lenient mode.
* Example: </p>
*
* <pre>
* import static net.time4j.PlainTime.MINUTE_OF_HOUR;
*
* System.out.println(
* PlainTime.of(18, 49).with(MINUTE_OF_HOUR.roundedUp(15)));
* // output: T19 corresponding to T18:60 (60 as multiple of 15)
* </pre>
*
* @param stepwidth controls the limits within the rounding will occur
* @return rounding operator in ceiling mode
* @see #roundedDown(int)
*/
/*[deutsch]
* <p>Rundet dieses chronologische Element so auf, daß sein
* numerischer Wert möglichst ein ganzzahliges Vielfaches der
* angegebenen Schrittweite annimmt. </p>
*
* <pre>
* import static net.time4j.PlainTime.MINUTE_OF_HOUR;
*
* System.out.println(
* PlainTime.of(18, 38).with(MINUTE_OF_HOUR.roundedUp(15)));
* // Ausgabe: T18:45
* </pre>
*
* <p>Der neu errechnete Elementwert wird immer nachsichtig mittels
* {@link #setLenient(Number)} gesetzt. Beispiel: </p>
*
* <pre>
* import static net.time4j.PlainTime.MINUTE_OF_HOUR;
*
* System.out.println(
* PlainTime.of(18, 49).with(MINUTE_OF_HOUR.roundedUp(15)));
* // Ausgabe: T19 entsprechend T18:60 (60 als Vielfaches von 15)
* </pre>
*
* @param stepwidth controls the limits within the rounding will occur
* @return rounding operator in ceiling mode
* @see #roundedDown(int)
*/
ChronoOperator<T> roundedUp(int stepwidth);
/**
* <p>Rounds this chronological element up or down and makes its
* numerical value an integral multiple of given step width if
* possible. </p>
*
* <pre>
* import static net.time4j.PlainTime.MINUTE_OF_HOUR;
*
* System.out.println(
* PlainTime.of(18, 38).with(MINUTE_OF_HOUR.roundedHalf(15)));
* // output: T18:45
* System.out.println(
* PlainTime.of(18, 37).with(MINUTE_OF_HOUR.roundedHalf(15)));
* // output: T18:30
* </pre>
*
* <p>The new element value will always be set in lenient mode. Is the
* current value nearer to the lower limit then this function will
* round down else round up. </p>
*
* @param stepwidth controls the limits within the rounding will occur
* @return rounding operator in ceiling or floor mode dependent on
* actual element value
* @see #roundedUp(int)
* @see #roundedDown(int)
*/
/*[deutsch]
* <p>Rundet dieses chronologische Element auf oder ab und stellt
* sicher, daß sein numerischer Wert möglichst ein
* ganzzahliges Vielfaches der angegebenen Schrittweite annimmt. </p>
*
* <pre>
* import static net.time4j.PlainTime.MINUTE_OF_HOUR;
*
* System.out.println(
* PlainTime.of(18, 38).with(MINUTE_OF_HOUR.roundedHalf(15)));
* // Ausgabe: T18:45
* System.out.println(
* PlainTime.of(18, 37).with(MINUTE_OF_HOUR.roundedHalf(15)));
* // Ausgabe: T18:30
* </pre>
*
* <p>Der neu errechnete Elementwert wird immer nachsichtig mittels
* {@link #setLenient(Number)} gesetzt. Ist der aktuelle Wert näher
* an der unteren Grenze, dann wird abgerundet, sonst aufgerundet. </p>
*
* @param stepwidth controls the limits within the rounding will occur
* @return rounding operator in ceiling or floor mode dependent on
* actual element value
* @see #roundedUp(int)
* @see #roundedDown(int)
*/
ChronoOperator<T> roundedHalf(int stepwidth);
/**
* <p>Rounds this chronological element down and makes its numerical
* value an integral multiple of given step width if possible. </p>
*
* <pre>
* import static net.time4j.PlainTime.MINUTE_OF_HOUR;
*
* System.out.println(
* PlainTime.of(18, 38).with(MINUTE_OF_HOUR.roundedDown(15)));
* // output: T18:30
* </pre>
*
* <p>The new element value will always be set in lenient mode.
* Example: </p>
*
* <pre>
* import static net.time4j.PlainTime.CLOCK_HOUR_OF_DAY;
*
* System.out.println(
* PlainTime.of(2, 30).with(CLOCK_HOUR_OF_DAY.roundedDown(3)));
* // output: T0
* </pre>
*
* @param stepwidth controls the limits within the rounding will occur
* @return rounding operator in floor mode
* @see #roundedUp(int)
*/
/*[deutsch]
* <p>Rundet dieses chronologische Element so ab, daß sein
* numerischer Wert möglichst ein ganzzahliges Vielfaches der
* angegebenen Schrittweite annimmt. </p>
*
* <pre>
* import static net.time4j.PlainTime.MINUTE_OF_HOUR;
*
* System.out.println(
* PlainTime.of(18, 38).with(MINUTE_OF_HOUR.roundedDown(15)));
* // Ausgabe: T18:30
* </pre>
*
* <p>Der neu errechnete Elementwert wird immer nachsichtig mittels
* {@link #setLenient(Number)} gesetzt. Beispiel: </p>
*
* <pre>
* import static net.time4j.PlainTime.CLOCK_HOUR_OF_DAY;
*
* System.out.println(
* PlainTime.of(2, 30).with(CLOCK_HOUR_OF_DAY.roundedDown(3)));
* // Ausgabe: T0
* </pre>
*
* @param stepwidth controls the limits within the rounding will occur
* @return rounding operator in floor mode
* @see #roundedUp(int)
*/
ChronoOperator<T> roundedDown(int stepwidth);
}