1 | /**
|
2 | * @copyright (c) 2016, Philipp Thürwächter & Pattrick Hüper
|
3 | * @copyright (c) 2007-present, Stephen Colebourne & Michael Nascimento Santos
|
4 | * @license BSD-3-Clause (see LICENSE in the root directory of this source tree)
|
5 | */
|
6 |
|
7 | import {UnsupportedTemporalTypeException} from '../errors';
|
8 |
|
9 | import {ChronoField} from './ChronoField';
|
10 | import {TemporalQueries} from './TemporalQueries';
|
11 |
|
12 | export class TemporalAccessor {
|
13 | /**
|
14 | * Queries this date-time.
|
15 | *
|
16 | * This queries this date-time using the specified query strategy object.
|
17 | *
|
18 | * Queries are a key tool for extracting information from date-times.
|
19 | * They exists to externalize the process of querying, permitting different
|
20 | * approaches, as per the strategy design pattern.
|
21 | * Examples might be a query that checks if the date is the day before February 29th
|
22 | * in a leap year, or calculates the number of days to your next birthday.
|
23 | *
|
24 | * The most common query implementations are method references, such as
|
25 | * {@link LocalDate::from} and {@link ZoneId::from}.
|
26 | * Further implementations are on {@link TemporalQueries}.
|
27 | * Queries may also be defined by applications.
|
28 | *
|
29 | * @implSpec
|
30 | * Implementations of this method must behave as follows:
|
31 | * <pre>
|
32 | if (query == TemporalQueries.zoneId()
|
33 | || query == TemporalQueries.chronology()
|
34 | || query == TemporalQueries.precision()) {
|
35 | return null;
|
36 | }
|
37 | return query.queryFrom(this);
|
38 | * </pre>
|
39 | *
|
40 | * @param {TemporalQuery} query the query to invoke, not null
|
41 | * @return the query result, null may be returned (defined by the query)
|
42 | * @throws DateTimeException if unable to query
|
43 | * @throws ArithmeticException if numeric overflow occurs
|
44 | */
|
45 | query(query) {
|
46 | if (query === TemporalQueries.zoneId()
|
47 | || query === TemporalQueries.chronology()
|
48 | || query === TemporalQueries.precision()) {
|
49 | return null;
|
50 | }
|
51 | return query.queryFrom(this);
|
52 | }
|
53 |
|
54 | /**
|
55 | * Gets the value of the specified field as an `int`.
|
56 | *
|
57 | * This queries the date-time for the value for the specified field.
|
58 | * The returned value will always be within the valid range of values for the field.
|
59 | * If the date-time cannot return the value, because the field is unsupported or for
|
60 | * some other reason, an exception will be thrown.
|
61 | *
|
62 | * ### Specification for implementors
|
63 | *
|
64 | * Implementations must check and handle all fields defined in {@link ChronoField}.
|
65 | * If the field is supported and has an `int` range, then the value of
|
66 | * the field must be returned.
|
67 | * If unsupported, then a {@link DateTimeException} must be thrown.
|
68 | *
|
69 | * If the field is not a {@link ChronoField}, then the result of this method
|
70 | * is obtained by invoking {@link TemporalField.getFrom}
|
71 | * passing `this` as the argument.
|
72 | *
|
73 | * Implementations must not alter either this object.
|
74 | *
|
75 | * @param {TemporalField} field - the field to get, not null
|
76 | * @return {number} the value for the field, within the valid range of values
|
77 | * @throws DateTimeException if a value for the field cannot be obtained
|
78 | * @throws DateTimeException if the range of valid values for the field exceeds an `int`
|
79 | * @throws DateTimeException if the value is outside the range of valid values for the field
|
80 | * @throws ArithmeticException if numeric overflow occurs
|
81 | */
|
82 | get(field) {
|
83 | return this.range(field).checkValidIntValue(this.getLong(field), field);
|
84 | }
|
85 |
|
86 | /**
|
87 | * Gets the range of valid values for the specified field.
|
88 | *
|
89 | * All fields can be expressed as a `long` integer.
|
90 | * This method returns an object that describes the valid range for that value.
|
91 | * The value of this temporal object is used to enhance the accuracy of the returned range.
|
92 | * If the date-time cannot return the range, because the field is unsupported or for
|
93 | * some other reason, an exception will be thrown.
|
94 | *
|
95 | * Note that the result only describes the minimum and maximum valid values
|
96 | * and it is important not to read too much into them. For example, there
|
97 | * could be values within the range that are invalid for the field.
|
98 | *
|
99 | * ### Specification for implementors
|
100 | *
|
101 | * Implementations must check and handle all fields defined in {@link ChronoField}.
|
102 | * If the field is supported, then the range of the field must be returned.
|
103 | * If unsupported, then a {@link DateTimeException} must be thrown.
|
104 | *
|
105 | * If the field is not a {@link ChronoField}, then the result of this method
|
106 | * is obtained by invoking {@link TemporalField.rangeRefinedBy}
|
107 | * passing `this` as the argument.
|
108 | *
|
109 | * Implementations must not alter either this object.
|
110 | *
|
111 | * @param {TemporalField} field the field to query the range for, not null
|
112 | * @return {ValueRange} the range of valid values for the field, not null
|
113 | * @throws DateTimeException if the range for the field cannot be obtained
|
114 | */
|
115 | range(field) {
|
116 | if (field instanceof ChronoField) {
|
117 | if (this.isSupported(field)) {
|
118 | return field.range();
|
119 | }
|
120 | throw new UnsupportedTemporalTypeException('Unsupported field: ' + field);
|
121 | }
|
122 | return field.rangeRefinedBy(this);
|
123 | }
|
124 |
|
125 | }
|