src/share/classes/java/time/temporal/TemporalField.java
Print this page
@@ -60,32 +60,33 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package java.time.temporal;
import java.time.DateTimeException;
-import java.time.format.DateTimeBuilder;
import java.util.Comparator;
+import java.util.Map;
/**
* A field of date-time, such as month-of-year or hour-of-minute.
* <p>
* Date and time is expressed using fields which partition the time-line into something
* meaningful for humans. Implementations of this interface represent those fields.
* <p>
* The most commonly used units are defined in {@link ChronoField}.
- * Further fields are supplied in {@link ISOFields}, {@link WeekFields} and {@link JulianFields}.
+ * Further fields are supplied in {@link IsoFields}, {@link WeekFields} and {@link JulianFields}.
* Fields can also be written by application code by implementing this interface.
* <p>
* The field works using double dispatch. Client code calls methods on a date-time like
* {@code LocalDateTime} which check if the field is a {@code 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.
*
* <h3>Specification for implementors</h3>
* This interface must be implemented with care to ensure other classes operate correctly.
* All implementations that can be instantiated must be final, immutable and thread-safe.
- * It is recommended to use an enum where possible.
+ * Implementations should be {@code Serializable} where possible.
+ * An enum is as effective implementation choice.
*
* @since 1.8
*/
public interface TemporalField extends Comparator<TemporalAccessor> {
@@ -172,11 +173,11 @@
* 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(TemporalField)}:
* <pre>
* // these two lines are equivalent, but the second approach is recommended
- * temporal = thisField.doIsSupported(temporal);
+ * temporal = thisField.isSupportedBy(temporal);
* temporal = temporal.isSupported(thisField);
* </pre>
* It is recommended to use the second approach, {@code isSupported(TemporalField)},
* as it is a lot clearer to read in code.
* <p>
@@ -184,11 +185,11 @@
* available in {@link ChronoField}.
*
* @param temporal the temporal object to query, not null
* @return true if the date-time can be queried for this field, false if not
*/
- boolean doIsSupported(TemporalAccessor temporal);
+ boolean isSupportedBy(TemporalAccessor temporal);
/**
* Get the range of valid values for this field using the temporal object to
* refine the result.
* <p>
@@ -202,11 +203,11 @@
* 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(TemporalField)}:
* <pre>
* // these two lines are equivalent, but the second approach is recommended
- * temporal = thisField.doRange(temporal);
+ * temporal = thisField.rangeRefinedBy(temporal);
* temporal = temporal.range(thisField);
* </pre>
* It is recommended to use the second approach, {@code range(TemporalField)},
* as it is a lot clearer to read in code.
* <p>
@@ -216,11 +217,11 @@
*
* @param temporal the temporal object used to refine the result, not null
* @return the range of valid values for this field, not null
* @throws DateTimeException if the range for the field cannot be obtained
*/
- ValueRange doRange(TemporalAccessor temporal);
+ ValueRange rangeRefinedBy(TemporalAccessor temporal);
/**
* Gets the value of this field from the specified temporal object.
* <p>
* This queries the temporal object for the value of this field.
@@ -229,11 +230,11 @@
* The first is to invoke this method directly.
* The second is to use {@link TemporalAccessor#getLong(TemporalField)}
* (or {@link TemporalAccessor#get(TemporalField)}):
* <pre>
* // these two lines are equivalent, but the second approach is recommended
- * temporal = thisField.doGet(temporal);
+ * temporal = thisField.getFrom(temporal);
* temporal = temporal.getLong(thisField);
* </pre>
* It is recommended to use the second approach, {@code getLong(TemporalField)},
* as it is a lot clearer to read in code.
* <p>
@@ -242,12 +243,13 @@
* If the field is not supported a {@code DateTimeException} must be thrown.
*
* @param temporal the temporal object to query, not null
* @return the value of this field, not null
* @throws DateTimeException if a value for the field cannot be obtained
+ * @throws ArithmeticException if numeric overflow occurs
*/
- long doGet(TemporalAccessor temporal);
+ long getFrom(TemporalAccessor temporal);
/**
* Returns a copy of the specified temporal object with the value of this field set.
* <p>
* This returns a new temporal object based on the specified one with the value for
@@ -264,11 +266,11 @@
* 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(TemporalField, long)}:
* <pre>
* // these two lines are equivalent, but the second approach is recommended
- * temporal = thisField.doWith(temporal);
+ * temporal = thisField.adjustInto(temporal);
* temporal = temporal.with(thisField);
* </pre>
* It is recommended to use the second approach, {@code with(TemporalField)},
* as it is a lot clearer to read in code.
* <p>
@@ -283,23 +285,47 @@
* @param <R> the type of the Temporal object
* @param temporal the temporal object to adjust, not null
* @param newValue the new value of the field
* @return the adjusted temporal object, not null
* @throws DateTimeException if the field cannot be set
+ * @throws ArithmeticException if numeric overflow occurs
*/
- <R extends Temporal> R doWith(R temporal, long newValue);
+ <R extends Temporal> R adjustInto(R temporal, long newValue);
/**
- * Resolves the date/time information in the builder
+ * Resolves this field to provide a simpler alternative.
* <p>
- * This method is invoked during the resolve of the builder.
- * Implementations should combine the associated field with others to form
- * objects like {@code LocalDate}, {@code LocalTime} and {@code LocalDateTime}
- *
- * @param builder the builder to resolve, not null
- * @param value the value of the associated field
- * @return true if builder has been changed, false otherwise
- * @throws DateTimeException if unable to resolve
+ * This method is invoked during the resolve phase of parsing.
+ * It is designed to allow application defined fields to be simplified into
+ * more standard fields, such as those on {@code ChronoField}.
+ * <p>
+ * The method will only be invoked if the specified temporal supports this field.
+ * The value of this field is provided.
+ * <p>
+ * The temporal must be queried using the methods of {@code TemporalAccessor},
+ * not using {@code getFrom}, {@code isSupportedBy} or {@code rangeRefinedBy}.
+ * Before querying any field, implementations must ensure it is supported, as
+ * exceptions of this type would negatively affect the calculation of a parsed result.
+ * <p>
+ * If this field can resolve, it must return a map, if not it must return null.
+ * The returned map contains the changes to be made to the temporal, expressed
+ * as field-value pairs. If the value for a field is null, the field is to be
+ * removed from the temporal. A null key must not be added to the result map.
+ * <p>
+ * If the result is non-null, this field will be removed from the temporal.
+ * This field should not be added to the result map.
+ * <p>
+ * The default implementation must return null.
+ *
+ * @param temporal the temporal to resolve, not null
+ * @param value the value of this field
+ * @return a map of fields to update in the temporal, with a mapping to null
+ * indicating a deletion. The whole map must be null if no resolving occurred
+ * @throws DateTimeException if resolving results in an error. This must not be thrown
+ * by querying a field on the temporal without first checking if it is supported
+ * @throws ArithmeticException if numeric overflow occurs
*/
- boolean resolve(DateTimeBuilder builder, long value);
+ public default Map<TemporalField, Long> resolve(TemporalAccessor temporal, long value) {
+ return null;
+ }
}