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;
+    }
 
 }