UNPKG

@js-joda/core

Version:

a date and time library for javascript

249 lines (235 loc) 9.9 kB
import { abstractMethodFail } from '../assert'; /** * @copyright (c) 2016, Philipp Thürwächter & Pattrick Hüper * @copyright (c) 2007-present, Stephen Colebourne & Michael Nascimento Santos * @license BSD-3-Clause (see LICENSE in the root directory of this source tree) */ /** * A field of date-time, such as month-of-year or hour-of-minute. * * Date and time is expressed using fields which partition the time-line into something * meaningful for humans. Implementations of this interface represent those fields. * * The most commonly used units are defined in {@link ChronoField}. * Further fields are supplied in {@link IsoFields}, {@link WeekFields} and {@link JulianFields}. * Fields can also be written by application code by implementing this interface. * * The field works using double dispatch. Client code calls methods on a date-time like * {@link LocalDateTime} which check if the field is a {@link ChronoField}. * If it is, then the date-time must handle it. * Otherwise, the method call is re-dispatched to the matching method in this interface. * * @interface */ export class TemporalField { /** * Checks if this field represents a component of a date. * * @return {boolean} `true` if it is a component of a date, `false` otherwise. */ isDateBased() { abstractMethodFail('isDateBased'); } /** * Checks if this field represents a component of a time. * * @return {boolean} `true` if it is a component of a time, `false` otherwise. */ isTimeBased() { abstractMethodFail('isTimeBased'); } /** * Gets the unit that the field is measured in. * * The unit of the field is the period that varies within the range. * For example, in the field 'MonthOfYear', the unit is 'Months'. * See also {@link rangeUnit}. * * @return {TemporalUnit} the period unit defining the base unit of the field. */ baseUnit() { abstractMethodFail('baseUnit'); } /** * Gets the range that the field is bound by. * * The range of the field is the period that the field varies within. * For example, in the field 'MonthOfYear', the range is 'Years'. * See also {@link baseUnit}. * * The range is never null. For example, the 'Year' field is shorthand for * 'YearOfForever'. It therefore has a unit of 'Years' and a range of 'Forever'. * * @return {TemporalUnit} the period unit defining the range of the field. */ rangeUnit() { abstractMethodFail('rangeUnit'); } /** * Gets the range of valid values for the field. * * All fields can be expressed as an integer. * This method returns an object that describes the valid range for that value. * This method is generally only applicable to the ISO-8601 calendar system. * * Note that the result only describes the minimum and maximum valid values * and it is important not to read too much into them. For example, there * could be values within the range that are invalid for the field. * * @return {ValueRange} the range of valid values for the field. */ range() { abstractMethodFail('range'); } /** * Get the range of valid values for this field using the temporal object to * refine the result. * * This uses the temporal object to find the range of valid values for the field. * This is similar to {@link range}, however this method refines the result * using the temporal. For example, if the field is {@link DAY_OF_MONTH} the * {@link range} method is not accurate as there are four possible month lengths, * 28, 29, 30 and 31 days. Using this method with a date allows the range to be * accurate, returning just one of those four options. * * There are two equivalent ways of using this method. * The first is to invoke this method directly. * The second is to use {@link TemporalAccessor#range}: * <pre> * // these two lines are equivalent, but the second approach is recommended * temporal = thisField.rangeRefinedBy(temporal); * temporal = temporal.range(thisField); * </pre> * It is recommended to use the second approach, {@link range}, * as it is a lot clearer to read in code. * * Implementations should perform any queries or calculations using the fields * available in {@link ChronoField}. * If the field is not supported a {@link DateTimeException} must be thrown. * * @param {!TemporalAccessor} temporal the temporal object used to refine the result. * @return {ValueRange} the range of valid values for this field. * @throws {DateTimeException} if the range for the field cannot be obtained. * */ // eslint-disable-next-line no-unused-vars rangeRefinedBy(temporal) { abstractMethodFail('rangeRefinedBy'); } /** * Gets the value of this field from the specified temporal object. * * This queries the temporal object for the value of this field. * * There are two equivalent ways of using this method. * The first is to invoke this method directly. * The second is to use {@link TemporalAccessor#get}: * <pre> * // these two lines are equivalent, but the second approach is recommended * temporal = thisField.getFrom(temporal); * temporal = temporal.get(thisField); * </pre> * It is recommended to use the second approach, as it is a lot clearer to read in code. * * Implementations should perform any queries or calculations using the fields * available in {@link ChronoField}. * If the field is not supported a {@link DateTimeException} must be thrown. * * @param {!TemporalAccesor} temporal the temporal object to query. * @return {number} the value of this field. * @throws {DateTimeException} if a value for the field cannot be obtained. */ // eslint-disable-next-line no-unused-vars getFrom(temporal) { abstractMethodFail('getFrom'); } /** * Returns a copy of the specified temporal object with the value of this field set. * * This returns a new temporal object based on the specified one with the value for * this field changed. For example, on a {@link LocalDate}, this could be used to * set the year, month or day-of-month. * The returned object has the same observable type as the specified object. * * In some cases, changing a field is not fully defined. For example, if the target object is * a date representing the 31st January, then changing the month to February would be unclear. * In cases like this, the implementation is responsible for resolving the result. * Typically it will choose the previous valid date, which would be the last valid * day of February in this example. * * There are two equivalent ways of using this method. * The first is to invoke this method directly. * The second is to use {@link Temporal#with}: * <pre> * // these two lines are equivalent, but the second approach is recommended * temporal = thisField.adjustInto(temporal); * temporal = temporal.with(thisField); * </pre> * It is recommended to use the second approach, `with(temporal)`, * as it is a lot clearer to read in code. * * Implementations should perform any queries or calculations using the fields * available in {@link ChronoField}. * If the field is not supported a {@link DateTimeException} must be thrown. * * Implementations must not alter the specified temporal object. * Instead, an adjusted copy of the original must be returned. * This provides equivalent, safe behavior for immutable and mutable implementations. * * @param {!Temporal} temporal the temporal object to adjust. * @param {!number} newValue the new value of the field. * @return {Temporal} the adjusted temporal object. * @throws {DateTimeException} if the field cannot be set. */ // eslint-disable-next-line no-unused-vars adjustInto(temporal, newValue) { abstractMethodFail('adjustInto'); } /** * Checks if this field is supported by the temporal object. * * This determines whether the temporal accessor supports this field. * If this returns false, the the temporal cannot be queried for this field. * * There are two equivalent ways of using this method. * The first is to invoke this method directly. * The second is to use {@link TemporalAccessor#isSupported}: * <pre> * // these two lines are equivalent, but the second approach is recommended * temporal = thisField.isSupportedBy(temporal); * temporal = temporal.isSupported(thisField); * </pre> * It is recommended to use the second approach, `isSupported(temporal)`, * as it is a lot clearer to read in code. * * Implementations should determine whether they are supported using the fields * available in {@link ChronoField}. * * @param {!TemporalAccesor} temporal the temporal object to query. * @return {boolean} `true` if the date-time can be queried for this field, `false` if not. */ // eslint-disable-next-line no-unused-vars isSupportedBy(temporal) { abstractMethodFail('isSupportedBy'); } /** * @return {string} */ displayName(/* TODO: locale */) { abstractMethodFail('displayName'); } /** * @param {*} other * @returns {boolean} */ // eslint-disable-next-line no-unused-vars equals(other) { abstractMethodFail('equals'); } /** * @returns {string} */ name() { abstractMethodFail('name'); } }