001/*
002 * Copyright (c) 2007-2013, Stephen Colebourne & Michael Nascimento Santos
003 *
004 * All rights reserved.
005 *
006 * Redistribution and use in source and binary forms, with or without
007 * modification, are permitted provided that the following conditions are met:
008 *
009 *  * Redistributions of source code must retain the above copyright notice,
010 *    this list of conditions and the following disclaimer.
011 *
012 *  * Redistributions in binary form must reproduce the above copyright notice,
013 *    this list of conditions and the following disclaimer in the documentation
014 *    and/or other materials provided with the distribution.
015 *
016 *  * Neither the name of JSR-310 nor the names of its contributors
017 *    may be used to endorse or promote products derived from this software
018 *    without specific prior written permission.
019 *
020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
021 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
022 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
023 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
024 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
025 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
026 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
027 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
028 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
029 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
030 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
031 */
032package org.threeten.bp.temporal;
033
034import java.util.Comparator;
035
036import org.threeten.bp.DateTimeException;
037import org.threeten.bp.format.DateTimeBuilder;
038
039/**
040 * A field of date-time, such as month-of-year or hour-of-minute.
041 * <p>
042 * Date and time is expressed using fields which partition the time-line into something
043 * meaningful for humans. Implementations of this interface represent those fields.
044 * <p>
045 * The most commonly used units are defined in {@link ChronoField}.
046 * Further fields are supplied in {@link ISOFields}, {@link WeekFields} and {@link JulianFields}.
047 * Fields can also be written by application code by implementing this interface.
048 * <p>
049 * The field works using double dispatch. Client code calls methods on a date-time like
050 * {@code LocalDateTime} which check if the field is a {@code ChronoField}.
051 * If it is, then the date-time must handle it.
052 * Otherwise, the method call is re-dispatched to the matching method in this interface.
053 *
054 * <h3>Specification for implementors</h3>
055 * This interface must be implemented with care to ensure other classes operate correctly.
056 * All implementations that can be instantiated must be final, immutable and thread-safe.
057 * It is recommended to use an enum where possible.
058 */
059public interface TemporalField extends Comparator<TemporalAccessor> {
060
061    /**
062     * Gets a descriptive name for the field.
063     * <p>
064     * The should be of the format 'BaseOfRange', such as 'MonthOfYear',
065     * unless the field has a range of {@code FOREVER}, when only
066     * the base unit is mentioned, such as 'Year' or 'Era'.
067     *
068     * @return the name, not null
069     */
070    String getName();
071
072    /**
073     * Gets the unit that the field is measured in.
074     * <p>
075     * The unit of the field is the period that varies within the range.
076     * For example, in the field 'MonthOfYear', the unit is 'Months'.
077     * See also {@link #getRangeUnit()}.
078     *
079     * @return the period unit defining the base unit of the field, not null
080     */
081    TemporalUnit getBaseUnit();
082
083    /**
084     * Gets the range that the field is bound by.
085     * <p>
086     * The range of the field is the period that the field varies within.
087     * For example, in the field 'MonthOfYear', the range is 'Years'.
088     * See also {@link #getBaseUnit()}.
089     * <p>
090     * The range is never null. For example, the 'Year' field is shorthand for
091     * 'YearOfForever'. It therefore has a unit of 'Years' and a range of 'Forever'.
092     *
093     * @return the period unit defining the range of the field, not null
094     */
095    TemporalUnit getRangeUnit();
096
097    //-----------------------------------------------------------------------
098    /**
099     * Compares the value of this field in two temporal objects.
100     * <p>
101     * All fields implement {@link Comparator} on {@link TemporalAccessor}.
102     * This allows a list of date-times to be compared using the value of a field.
103     * For example, you could sort a list of arbitrary temporal objects by the value of
104     * the month-of-year field - {@code Collections.sort(list, MONTH_OF_YEAR)}
105     *
106     * @param temporal1  the first temporal object to compare, not null
107     * @param temporal2  the second temporal object to compare, not null
108     * @throws DateTimeException if unable to obtain the value for this field
109     */
110    int compare(TemporalAccessor temporal1, TemporalAccessor temporal2);
111
112    /**
113     * Gets the range of valid values for the field.
114     * <p>
115     * All fields can be expressed as a {@code long} integer.
116     * This method returns an object that describes the valid range for that value.
117     * This method is generally only applicable to the ISO-8601 calendar system.
118     * <p>
119     * Note that the result only describes the minimum and maximum valid values
120     * and it is important not to read too much into them. For example, there
121     * could be values within the range that are invalid for the field.
122     *
123     * @return the range of valid values for the field, not null
124     */
125    ValueRange range();
126
127    //-----------------------------------------------------------------------
128    /**
129     * Checks if this field is supported by the temporal object.
130     * <p>
131     * This determines whether the temporal accessor supports this field.
132     * If this returns false, the the temporal cannot be queried for this field.
133     * <p>
134     * There are two equivalent ways of using this method.
135     * The first is to invoke this method directly.
136     * The second is to use {@link TemporalAccessor#isSupported(TemporalField)}:
137     * <pre>
138     *   // these two lines are equivalent, but the second approach is recommended
139     *   temporal = thisField.doIsSupported(temporal);
140     *   temporal = temporal.isSupported(thisField);
141     * </pre>
142     * It is recommended to use the second approach, {@code isSupported(TemporalField)},
143     * as it is a lot clearer to read in code.
144     * <p>
145     * Implementations should determine whether they are supported using the fields
146     * available in {@link ChronoField}.
147     *
148     * @param temporal  the temporal object to query, not null
149     * @return true if the date-time can be queried for this field, false if not
150     */
151    boolean doIsSupported(TemporalAccessor temporal);
152
153    /**
154     * Get the range of valid values for this field using the temporal object to
155     * refine the result.
156     * <p>
157     * This uses the temporal object to find the range of valid values for the field.
158     * This is similar to {@link #range()}, however this method refines the result
159     * using the temporal. For example, if the field is {@code DAY_OF_MONTH} the
160     * {@code range} method is not accurate as there are four possible month lengths,
161     * 28, 29, 30 and 31 days. Using this method with a date allows the range to be
162     * accurate, returning just one of those four options.
163     * <p>
164     * There are two equivalent ways of using this method.
165     * The first is to invoke this method directly.
166     * The second is to use {@link TemporalAccessor#range(TemporalField)}:
167     * <pre>
168     *   // these two lines are equivalent, but the second approach is recommended
169     *   temporal = thisField.doRange(temporal);
170     *   temporal = temporal.range(thisField);
171     * </pre>
172     * It is recommended to use the second approach, {@code range(TemporalField)},
173     * as it is a lot clearer to read in code.
174     * <p>
175     * Implementations should perform any queries or calculations using the fields
176     * available in {@link ChronoField}.
177     * If the field is not supported a {@code DateTimeException} must be thrown.
178     *
179     * @param temporal  the temporal object used to refine the result, not null
180     * @return the range of valid values for this field, not null
181     * @throws DateTimeException if the range for the field cannot be obtained
182     */
183    ValueRange doRange(TemporalAccessor temporal);
184
185    /**
186     * Gets the value of this field from the specified temporal object.
187     * <p>
188     * This queries the temporal object for the value of this field.
189     * <p>
190     * There are two equivalent ways of using this method.
191     * The first is to invoke this method directly.
192     * The second is to use {@link TemporalAccessor#getLong(TemporalField)}
193     * (or {@link TemporalAccessor#get(TemporalField)}):
194     * <pre>
195     *   // these two lines are equivalent, but the second approach is recommended
196     *   temporal = thisField.doGet(temporal);
197     *   temporal = temporal.getLong(thisField);
198     * </pre>
199     * It is recommended to use the second approach, {@code getLong(TemporalField)},
200     * as it is a lot clearer to read in code.
201     * <p>
202     * Implementations should perform any queries or calculations using the fields
203     * available in {@link ChronoField}.
204     * If the field is not supported a {@code DateTimeException} must be thrown.
205     *
206     * @param temporal  the temporal object to query, not null
207     * @return the value of this field, not null
208     * @throws DateTimeException if a value for the field cannot be obtained
209     */
210    long doGet(TemporalAccessor temporal);
211
212    /**
213     * Returns a copy of the specified temporal object with the value of this field set.
214     * <p>
215     * This returns a new temporal object based on the specified one with the value for
216     * this field changed. For example, on a {@code LocalDate}, this could be used to
217     * set the year, month or day-of-month.
218     * The returned object has the same observable type as the specified object.
219     * <p>
220     * In some cases, changing a field is not fully defined. For example, if the target object is
221     * a date representing the 31st January, then changing the month to February would be unclear.
222     * In cases like this, the implementation is responsible for resolving the result.
223     * Typically it will choose the previous valid date, which would be the last valid
224     * day of February in this example.
225     * <p>
226     * There are two equivalent ways of using this method.
227     * The first is to invoke this method directly.
228     * The second is to use {@link Temporal#with(TemporalField, long)}:
229     * <pre>
230     *   // these two lines are equivalent, but the second approach is recommended
231     *   temporal = thisField.doWith(temporal);
232     *   temporal = temporal.with(thisField);
233     * </pre>
234     * It is recommended to use the second approach, {@code with(TemporalField)},
235     * as it is a lot clearer to read in code.
236     * <p>
237     * Implementations should perform any queries or calculations using the fields
238     * available in {@link ChronoField}.
239     * If the field is not supported a {@code DateTimeException} must be thrown.
240     * <p>
241     * Implementations must not alter the specified temporal object.
242     * Instead, an adjusted copy of the original must be returned.
243     * This provides equivalent, safe behavior for immutable and mutable implementations.
244     *
245     * @param <R>  the type of the Temporal object
246     * @param temporal the temporal object to adjust, not null
247     * @param newValue the new value of the field
248     * @return the adjusted temporal object, not null
249     * @throws DateTimeException if the field cannot be set
250     */
251    <R extends Temporal> R doWith(R temporal, long newValue);
252
253    /**
254     * Resolves the date/time information in the builder
255     * <p>
256     * This method is invoked during the resolve of the builder.
257     * Implementations should combine the associated field with others to form
258     * objects like {@code LocalDate}, {@code LocalTime} and {@code LocalDateTime}
259     *
260     * @param builder  the builder to resolve, not null
261     * @param value  the value of the associated field
262     * @return true if builder has been changed, false otherwise
263     * @throws DateTimeException if unable to resolve
264     */
265    boolean resolve(DateTimeBuilder builder, long value);
266
267}