45 *
46 * * Neither the name of JSR-310 nor the names of its contributors
47 * may be used to endorse or promote products derived from this software
48 * without specific prior written permission.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
54 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
55 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
56 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
57 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
58 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
59 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
60 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61 */
62 package java.time.temporal;
63
64 import java.time.DateTimeException;
65 import java.time.ZoneId;
66 import java.util.Objects;
67
68 /**
69 * Framework-level interface defining read-only access to a temporal object,
70 * such as a date, time, offset or some combination of these.
71 * <p>
72 * This is the base interface type for date, time and offset objects.
73 * It is implemented by those classes that can provide information
74 * as {@linkplain TemporalField fields} or {@linkplain TemporalQuery queries}.
75 * <p>
76 * Most date and time information can be represented as a number.
77 * These are modeled using {@code TemporalField} with the number held using
78 * a {@code long} to handle large values. Year, month and day-of-month are
79 * simple examples of fields, but they also include instant and offsets.
80 * See {@link ChronoField} for the standard set of fields.
81 * <p>
82 * Two pieces of date/time information cannot be represented by numbers,
83 * the {@linkplain java.time.chrono.Chronology chronology} and the {@linkplain ZoneId time-zone}.
84 * These can be accessed via {@linkplain #query(TemporalQuery) queries} using
85 * the static methods defined on {@link TemporalQuery}.
86 * <p>
87 * A sub-interface, {@link Temporal}, extends this definition to one that also
88 * supports adjustment and manipulation on more complete temporal objects.
89 * <p>
90 * This interface is a framework-level interface that should not be widely
91 * used in application code. Instead, applications should create and pass
92 * around instances of concrete types, such as {@code LocalDate}.
93 * There are many reasons for this, part of which is that implementations
94 * of this interface may be in calendar systems other than ISO.
95 * See {@link java.time.chrono.ChronoLocalDate} for a fuller discussion of the issues.
96 *
97 * @implSpec
98 * This interface places no restrictions on the mutability of implementations,
99 * however immutability is strongly recommended.
100 *
101 * @since 1.8
102 */
103 public interface TemporalAccessor {
104
105 /**
106 * Checks if the specified field is supported.
107 * <p>
108 * This checks if the date-time can be queried for the specified field.
109 * If false, then calling the {@link #range(TemporalField) range} and {@link #get(TemporalField) get}
110 * methods will throw an exception.
111 *
112 * @implSpec
113 * Implementations must check and handle all fields defined in {@link ChronoField}.
114 * If the field is supported, then true is returned, otherwise false
115 * <p>
116 * If the field is not a {@code ChronoField}, then the result of this method
117 * is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}
118 * passing {@code this} as the argument.
119 * <p>
120 * Implementations must not alter either this object.
121 *
122 * @param field the field to check, null returns false
123 * @return true if this date-time can be queried for the field, false if not
124 */
125 boolean isSupported(TemporalField field);
126
127 /**
128 * Gets the range of valid values for the specified field.
129 * <p>
130 * All fields can be expressed as a {@code long} integer.
131 * This method returns an object that describes the valid range for that value.
132 * The value of this temporal object is used to enhance the accuracy of the returned range.
133 * If the date-time cannot return the range, because the field is unsupported or for
134 * some other reason, an exception will be thrown.
135 * <p>
136 * Note that the result only describes the minimum and maximum valid values
137 * and it is important not to read too much into them. For example, there
138 * could be values within the range that are invalid for the field.
139 *
140 * @implSpec
141 * Implementations must check and handle all fields defined in {@link ChronoField}.
142 * If the field is supported, then the range of the field must be returned.
143 * If unsupported, then an {@code UnsupportedTemporalTypeException} must be thrown.
144 * <p>
145 * If the field is not a {@code ChronoField}, then the result of this method
146 * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessorl)}
147 * passing {@code this} as the argument.
148 * <p>
149 * Implementations must not alter either this object.
150 * <p>
151 * The default implementation must behave equivalent to this code:
152 * <pre>
153 * if (field instanceof ChronoField) {
154 * if (isSupported(field)) {
155 * return field.range();
156 * }
157 * throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
158 * }
159 * return field.rangeRefinedBy(this);
160 * </pre>
161 *
162 * @param field the field to query the range for, not null
163 * @return the range of valid values for the field, not null
164 * @throws DateTimeException if the range for the field cannot be obtained
165 * @throws UnsupportedTemporalTypeException if the field is not supported
166 */
167 default ValueRange range(TemporalField field) {
168 if (field instanceof ChronoField) {
169 if (isSupported(field)) {
170 return field.range();
171 }
172 throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
173 }
174 Objects.requireNonNull(field, "field");
175 return field.rangeRefinedBy(this);
176 }
177
178 /**
179 * Gets the value of the specified field as an {@code int}.
180 * <p>
181 * This queries the date-time for the value for the specified field.
182 * The returned value will always be within the valid range of values for the field.
183 * If the date-time cannot return the value, because the field is unsupported or for
184 * some other reason, an exception will be thrown.
185 *
186 * @implSpec
187 * Implementations must check and handle all fields defined in {@link ChronoField}.
188 * If the field is supported and has an {@code int} range, then the value of
189 * the field must be returned.
190 * If unsupported, then an {@code UnsupportedTemporalTypeException} must be thrown.
191 * <p>
192 * If the field is not a {@code ChronoField}, then the result of this method
193 * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
194 * passing {@code this} as the argument.
195 * <p>
196 * Implementations must not alter this object.
197 * <p>
198 * The default implementation must behave equivalent to this code:
199 * <pre>
200 * if (range(field).isIntValue()) {
201 * return range(field).checkValidIntValue(getLong(field), field);
202 * }
203 * throw new UnsupportedTemporalTypeException("Invalid field " + field + " + for get() method, use getLong() instead");
204 * </pre>
205 *
206 * @param field the field to get, not null
207 * @return the value for the field, within the valid range of values
208 * @throws DateTimeException if a value for the field cannot be obtained or
209 * the value is outside the range of valid values for the field
210 * @throws UnsupportedTemporalTypeException if the field is not supported or
211 * the range of values exceeds an {@code int}
212 * @throws ArithmeticException if numeric overflow occurs
213 */
214 default int get(TemporalField field) {
215 ValueRange range = range(field);
216 if (range.isIntValue() == false) {
223 return (int) value;
224 }
225
226 /**
227 * Gets the value of the specified field as a {@code long}.
228 * <p>
229 * This queries the date-time for the value for the specified field.
230 * The returned value may be outside the valid range of values for the field.
231 * If the date-time cannot return the value, because the field is unsupported or for
232 * some other reason, an exception will be thrown.
233 *
234 * @implSpec
235 * Implementations must check and handle all fields defined in {@link ChronoField}.
236 * If the field is supported, then the value of the field must be returned.
237 * If unsupported, then an {@code UnsupportedTemporalTypeException} must be thrown.
238 * <p>
239 * If the field is not a {@code ChronoField}, then the result of this method
240 * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
241 * passing {@code this} as the argument.
242 * <p>
243 * Implementations must not alter either this object.
244 *
245 * @param field the field to get, not null
246 * @return the value for the field
247 * @throws DateTimeException if a value for the field cannot be obtained
248 * @throws UnsupportedTemporalTypeException if the field is not supported
249 * @throws ArithmeticException if numeric overflow occurs
250 */
251 long getLong(TemporalField field);
252
253 /**
254 * Queries this date-time.
255 * <p>
256 * This queries this date-time using the specified query strategy object.
257 * <p>
258 * Queries are a key tool for extracting information from date-times.
259 * They exists to externalize the process of querying, permitting different
260 * approaches, as per the strategy design pattern.
261 * Examples might be a query that checks if the date is the day before February 29th
262 * in a leap year, or calculates the number of days to your next birthday.
263 * <p>
274 * }
275 * return query.queryFrom(this);
276 * </pre>
277 * Future versions are permitted to add further queries to the if statement.
278 * <p>
279 * All classes implementing this interface and overriding this method must call
280 * {@code TemporalAccessor.super.query(query)}. JDK classes may avoid calling
281 * super if they provide behavior equivalent to the default behaviour, however
282 * non-JDK classes may not utilize this optimization and must call {@code super}.
283 * <p>
284 * If the implementation can supply a value for one of the queries listed in the
285 * if statement of the default implementation, then it must do so.
286 * For example, an application-defined {@code HourMin} class storing the hour
287 * and minute must override this method as follows:
288 * <pre>
289 * if (query == TemporalQuery.precision()) {
290 * return MINUTES;
291 * }
292 * return TemporalAccessor.super.query(query);
293 * </pre>
294 *
295 * @param <R> the type of the result
296 * @param query the query to invoke, not null
297 * @return the query result, null may be returned (defined by the query)
298 * @throws DateTimeException if unable to query
299 * @throws ArithmeticException if numeric overflow occurs
300 */
301 default <R> R query(TemporalQuery<R> query) {
302 if (query == TemporalQuery.zoneId() || query == TemporalQuery.chronology() || query == TemporalQuery.precision()) {
303 return null;
304 }
305 return query.queryFrom(this);
306 }
307
308 }
|
45 *
46 * * Neither the name of JSR-310 nor the names of its contributors
47 * may be used to endorse or promote products derived from this software
48 * without specific prior written permission.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
54 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
55 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
56 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
57 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
58 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
59 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
60 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61 */
62 package java.time.temporal;
63
64 import java.time.DateTimeException;
65 import java.util.Objects;
66
67 /**
68 * Framework-level interface defining read-only access to a temporal object,
69 * such as a date, time, offset or some combination of these.
70 * <p>
71 * This is the base interface type for date, time and offset objects.
72 * It is implemented by those classes that can provide information
73 * as {@linkplain TemporalField fields} or {@linkplain TemporalQuery queries}.
74 * <p>
75 * Most date and time information can be represented as a number.
76 * These are modeled using {@code TemporalField} with the number held using
77 * a {@code long} to handle large values. Year, month and day-of-month are
78 * simple examples of fields, but they also include instant and offsets.
79 * See {@link ChronoField} for the standard set of fields.
80 * <p>
81 * Two pieces of date/time information cannot be represented by numbers,
82 * the {@linkplain java.time.chrono.Chronology chronology} and the
83 * {@linkplain java.time.ZoneId time-zone}.
84 * These can be accessed via {@linkplain #query(TemporalQuery) queries} using
85 * the static methods defined on {@link TemporalQuery}.
86 * <p>
87 * A sub-interface, {@link Temporal}, extends this definition to one that also
88 * supports adjustment and manipulation on more complete temporal objects.
89 * <p>
90 * This interface is a framework-level interface that should not be widely
91 * used in application code. Instead, applications should create and pass
92 * around instances of concrete types, such as {@code LocalDate}.
93 * There are many reasons for this, part of which is that implementations
94 * of this interface may be in calendar systems other than ISO.
95 * See {@link java.time.chrono.ChronoLocalDate} for a fuller discussion of the issues.
96 *
97 * @implSpec
98 * This interface places no restrictions on the mutability of implementations,
99 * however immutability is strongly recommended.
100 *
101 * @since 1.8
102 */
103 public interface TemporalAccessor {
104
105 /**
106 * Checks if the specified field is supported.
107 * <p>
108 * This checks if the date-time can be queried for the specified field.
109 * If false, then calling the {@link #range(TemporalField) range} and {@link #get(TemporalField) get}
110 * methods will throw an exception.
111 *
112 * @implSpec
113 * Implementations must check and handle all fields defined in {@link ChronoField}.
114 * If the field is supported, then true must be returned, otherwise false must be returned.
115 * <p>
116 * If the field is not a {@code ChronoField}, then the result of this method
117 * is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}
118 * passing {@code this} as the argument.
119 * <p>
120 * Implementations must ensure that no observable state is altered when this
121 * read-only method is invoked.
122 *
123 * @param field the field to check, null returns false
124 * @return true if this date-time can be queried for the field, false if not
125 */
126 boolean isSupported(TemporalField field);
127
128 /**
129 * Gets the range of valid values for the specified field.
130 * <p>
131 * All fields can be expressed as a {@code long} integer.
132 * This method returns an object that describes the valid range for that value.
133 * The value of this temporal object is used to enhance the accuracy of the returned range.
134 * If the date-time cannot return the range, because the field is unsupported or for
135 * some other reason, an exception will be thrown.
136 * <p>
137 * Note that the result only describes the minimum and maximum valid values
138 * and it is important not to read too much into them. For example, there
139 * could be values within the range that are invalid for the field.
140 *
141 * @implSpec
142 * Implementations must check and handle all fields defined in {@link ChronoField}.
143 * If the field is supported, then the range of the field must be returned.
144 * If unsupported, then an {@code UnsupportedTemporalTypeException} must be thrown.
145 * <p>
146 * If the field is not a {@code ChronoField}, then the result of this method
147 * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessorl)}
148 * passing {@code this} as the argument.
149 * <p>
150 * Implementations must ensure that no observable state is altered when this
151 * read-only method is invoked.
152 * <p>
153 * The default implementation must behave equivalent to this code:
154 * <pre>
155 * if (field instanceof ChronoField) {
156 * if (isSupported(field)) {
157 * return field.range();
158 * }
159 * throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
160 * }
161 * return field.rangeRefinedBy(this);
162 * </pre>
163 *
164 * @param field the field to query the range for, not null
165 * @return the range of valid values for the field, not null
166 * @throws DateTimeException if the range for the field cannot be obtained
167 * @throws UnsupportedTemporalTypeException if the field is not supported
168 */
169 default ValueRange range(TemporalField field) {
170 if (field instanceof ChronoField) {
171 if (isSupported(field)) {
172 return field.range();
173 }
174 throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
175 }
176 Objects.requireNonNull(field, "field");
177 return field.rangeRefinedBy(this);
178 }
179
180 /**
181 * Gets the value of the specified field as an {@code int}.
182 * <p>
183 * This queries the date-time for the value for the specified field.
184 * The returned value will always be within the valid range of values for the field.
185 * If the date-time cannot return the value, because the field is unsupported or for
186 * some other reason, an exception will be thrown.
187 *
188 * @implSpec
189 * Implementations must check and handle all fields defined in {@link ChronoField}.
190 * If the field is supported and has an {@code int} range, then the value of
191 * the field must be returned.
192 * If unsupported, then an {@code UnsupportedTemporalTypeException} must be thrown.
193 * <p>
194 * If the field is not a {@code ChronoField}, then the result of this method
195 * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
196 * passing {@code this} as the argument.
197 * <p>
198 * Implementations must ensure that no observable state is altered when this
199 * read-only method is invoked.
200 * <p>
201 * The default implementation must behave equivalent to this code:
202 * <pre>
203 * if (range(field).isIntValue()) {
204 * return range(field).checkValidIntValue(getLong(field), field);
205 * }
206 * throw new UnsupportedTemporalTypeException("Invalid field " + field + " + for get() method, use getLong() instead");
207 * </pre>
208 *
209 * @param field the field to get, not null
210 * @return the value for the field, within the valid range of values
211 * @throws DateTimeException if a value for the field cannot be obtained or
212 * the value is outside the range of valid values for the field
213 * @throws UnsupportedTemporalTypeException if the field is not supported or
214 * the range of values exceeds an {@code int}
215 * @throws ArithmeticException if numeric overflow occurs
216 */
217 default int get(TemporalField field) {
218 ValueRange range = range(field);
219 if (range.isIntValue() == false) {
226 return (int) value;
227 }
228
229 /**
230 * Gets the value of the specified field as a {@code long}.
231 * <p>
232 * This queries the date-time for the value for the specified field.
233 * The returned value may be outside the valid range of values for the field.
234 * If the date-time cannot return the value, because the field is unsupported or for
235 * some other reason, an exception will be thrown.
236 *
237 * @implSpec
238 * Implementations must check and handle all fields defined in {@link ChronoField}.
239 * If the field is supported, then the value of the field must be returned.
240 * If unsupported, then an {@code UnsupportedTemporalTypeException} must be thrown.
241 * <p>
242 * If the field is not a {@code ChronoField}, then the result of this method
243 * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
244 * passing {@code this} as the argument.
245 * <p>
246 * Implementations must ensure that no observable state is altered when this
247 * read-only method is invoked.
248 *
249 * @param field the field to get, not null
250 * @return the value for the field
251 * @throws DateTimeException if a value for the field cannot be obtained
252 * @throws UnsupportedTemporalTypeException if the field is not supported
253 * @throws ArithmeticException if numeric overflow occurs
254 */
255 long getLong(TemporalField field);
256
257 /**
258 * Queries this date-time.
259 * <p>
260 * This queries this date-time using the specified query strategy object.
261 * <p>
262 * Queries are a key tool for extracting information from date-times.
263 * They exists to externalize the process of querying, permitting different
264 * approaches, as per the strategy design pattern.
265 * Examples might be a query that checks if the date is the day before February 29th
266 * in a leap year, or calculates the number of days to your next birthday.
267 * <p>
278 * }
279 * return query.queryFrom(this);
280 * </pre>
281 * Future versions are permitted to add further queries to the if statement.
282 * <p>
283 * All classes implementing this interface and overriding this method must call
284 * {@code TemporalAccessor.super.query(query)}. JDK classes may avoid calling
285 * super if they provide behavior equivalent to the default behaviour, however
286 * non-JDK classes may not utilize this optimization and must call {@code super}.
287 * <p>
288 * If the implementation can supply a value for one of the queries listed in the
289 * if statement of the default implementation, then it must do so.
290 * For example, an application-defined {@code HourMin} class storing the hour
291 * and minute must override this method as follows:
292 * <pre>
293 * if (query == TemporalQuery.precision()) {
294 * return MINUTES;
295 * }
296 * return TemporalAccessor.super.query(query);
297 * </pre>
298 * <p>
299 * Implementations must ensure that no observable state is altered when this
300 * read-only method is invoked.
301 *
302 * @param <R> the type of the result
303 * @param query the query to invoke, not null
304 * @return the query result, null may be returned (defined by the query)
305 * @throws DateTimeException if unable to query
306 * @throws ArithmeticException if numeric overflow occurs
307 */
308 default <R> R query(TemporalQuery<R> query) {
309 if (query == TemporalQuery.zoneId() || query == TemporalQuery.chronology() || query == TemporalQuery.precision()) {
310 return null;
311 }
312 return query.queryFrom(this);
313 }
314
315 }
|