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 static org.threeten.bp.temporal.ChronoField.OFFSET_SECONDS;
035
036import org.threeten.bp.ZoneId;
037import org.threeten.bp.ZoneOffset;
038
039/**
040 * Common implementations of {@code TemporalQuery}.
041 * <p>
042 * This class provides common implementations of {@link TemporalQuery}.
043 * These queries are primarily used as optimizations, allowing the internals
044 * of other objects to be extracted effectively. Note that application code
045 * can also use the {@code from(TemporalAccessor)} method on most temporal
046 * objects as a method reference matching the query interface, such as
047 * {@code LocalDate::from} and {@code ZoneId::from}.
048 * <p>
049 * There are two equivalent ways of using a {@code TemporalQuery}.
050 * The first is to invoke the method on the interface directly.
051 * The second is to use {@link TemporalAccessor#query(TemporalQuery)}:
052 * <pre>
053 *   // these two lines are equivalent, but the second approach is recommended
054 *   dateTime = query.queryFrom(dateTime);
055 *   dateTime = dateTime.query(query);
056 * </pre>
057 * It is recommended to use the second approach, {@code query(TemporalQuery)},
058 * as it is a lot clearer to read in code.
059 *
060 * <h3>Specification for implementors</h3>
061 * This is a thread-safe utility class.
062 * All returned adjusters are immutable and thread-safe.
063 */
064public final class TemporalQueries {
065    // note that it is vital that each method supplies a constant, not a
066    // calculated value, as they will be checked for using ==
067    // it is also vital that each constant is different (due to the == checking)
068
069    /**
070     * Private constructor since this is a utility class.
071     */
072    private TemporalQueries() {
073    }
074
075    //-----------------------------------------------------------------------
076    // special constants should be used to extract information from a TemporalAccessor
077    // that cannot be derived in other ways
078    // Javadoc added here, so as to pretend they are more normal than they really are
079
080    /**
081     * A strict query for the {@code ZoneId}.
082     * <p>
083     * This queries a {@code TemporalAccessor} for the zone.
084     * The zone is only returned if the date-time conceptually contains a {@code ZoneId}.
085     * It will not be returned if the date-time only conceptually has an {@code ZoneOffset}.
086     * Thus a {@link ZonedDateTime} will return the result of
087     * {@code getZone()}, but an {@link OffsetDateTime} will
088     * return null.
089     * <p>
090     * In most cases, applications should use {@link #ZONE} as this query is too strict.
091     * <p>
092     * The result from JDK classes implementing {@code TemporalAccessor} is as follows:<br>
093     * {@code LocalDate} returns null<br>
094     * {@code LocalTime} returns null<br>
095     * {@code LocalDateTime} returns null<br>
096     * {@code ZonedDateTime} returns the associated zone<br>
097     * {@code OffsetDate} returns null<br>
098     * {@code OffsetTime} returns null<br>
099     * {@code OffsetDateTime} returns null<br>
100     * {@code ChronoLocalDate} returns null<br>
101     * {@code ChronoLocalDateTime} returns null<br>
102     * {@code ChronoZonedDateTime} returns the associated zone<br>
103     * {@code Era} returns null<br>
104     * {@code DayOfWeek} returns null<br>
105     * {@code Month} returns null<br>
106     * {@code Year} returns null<br>
107     * {@code YearMonth} returns null<br>
108     * {@code MonthDay} returns null<br>
109     * {@code ZoneOffset} returns null<br>
110     * {@code Instant} returns null<br>
111     * @return a ZoneId, may be null
112     */
113    public static final TemporalQuery<ZoneId> zoneId() {
114        return ZONE_ID;
115    }
116    static final TemporalQuery<ZoneId> ZONE_ID = new TemporalQuery<ZoneId>() {
117        @Override
118        public ZoneId queryFrom(TemporalAccessor temporal) {
119            return temporal.query(this);
120        }
121    };
122
123    /**
124     * A query for the {@code Chrono}.
125     * <p>
126     * This queries a {@code TemporalAccessor} for the chronology.
127     * If the target {@code TemporalAccessor} represents a date, or part of a date,
128     * then it should return the chronology that the date is expressed in.
129     * As a result of this definition, objects only representing time, such as
130     * {@code LocalTime}, will return null.
131     * <p>
132     * The result from JDK classes implementing {@code TemporalAccessor} is as follows:<br>
133     * {@code LocalDate} returns {@code ISOChrono.INSTANCE}<br>
134     * {@code LocalTime} returns null (does not represent a date)<br>
135     * {@code LocalDateTime} returns {@code ISOChrono.INSTANCE}<br>
136     * {@code ZonedDateTime} returns {@code ISOChrono.INSTANCE}<br>
137     * {@code OffsetDate} returns {@code ISOChrono.INSTANCE}<br>
138     * {@code OffsetTime} returns null (does not represent a date)<br>
139     * {@code OffsetDateTime} returns {@code ISOChrono.INSTANCE}<br>
140     * {@code ChronoLocalDate} returns the associated chronology<br>
141     * {@code ChronoLocalDateTime} returns the associated chronology<br>
142     * {@code ChronoZonedDateTime} returns the associated chronology<br>
143     * {@code Era} returns the associated chronology<br>
144     * {@code DayOfWeek} returns null (shared across chronologies)<br>
145     * {@code Month} returns {@code ISOChrono.INSTANCE}<br>
146     * {@code Year} returns {@code ISOChrono.INSTANCE}<br>
147     * {@code YearMonth} returns {@code ISOChrono.INSTANCE}<br>
148     * {@code MonthDay} returns null {@code ISOChrono.INSTANCE}<br>
149     * {@code ZoneOffset} returns null (does not represent a date)<br>
150     * {@code Instant} returns null (does not represent a date)<br>
151     * <p>
152     * The method {@link Chrono#from(TemporalAccessor)} can be used as a
153     * {@code TemporalQuery} via a method reference, {@code Chrono::from}.
154     * That method is equivalent to this query, except that it throws an
155     * exception if a chronology cannot be obtained.
156     * @return a Chrono, may be null
157     */
158    public static final TemporalQuery<Chrono<?>> chrono() {
159        return CHRONO;
160    }
161    static final TemporalQuery<Chrono<?>> CHRONO = new TemporalQuery<Chrono<?>>() {
162        @Override
163        public Chrono<?> queryFrom(TemporalAccessor temporal) {
164            return temporal.query(this);
165        }
166    };
167
168    /**
169     * A query for the smallest supported unit.
170     * <p>
171     * This queries a {@code TemporalAccessor} for the time precision.
172     * If the target {@code TemporalAccessor} represents a consistent or complete date-time,
173     * date or time then this must return the smallest precision actually supported.
174     * Note that fields such as {@code NANO_OF_DAY} and {@code NANO_OF_SECOND}
175     * are defined to always return ignoring the precision, thus this is the only
176     * way to find the actual smallest supported unit.
177     * For example, were {@code GregorianCalendar} to implement {@code TemporalAccessor}
178     * it would return a precision of {@code MILLIS}.
179     * <p>
180     * The result from JDK classes implementing {@code TemporalAccessor} is as follows:<br>
181     * {@code LocalDate} returns {@code DAYS}<br>
182     * {@code LocalTime} returns {@code NANOS}<br>
183     * {@code LocalDateTime} returns {@code NANOS}<br>
184     * {@code ZonedDateTime} returns {@code NANOS}<br>
185     * {@code OffsetDate} returns {@code DAYS}<br>
186     * {@code OffsetTime} returns {@code NANOS}<br>
187     * {@code OffsetDateTime} returns {@code NANOS}<br>
188     * {@code ChronoLocalDate} returns {@code DAYS}<br>
189     * {@code ChronoLocalDateTime} returns {@code NANOS}<br>
190     * {@code ChronoZonedDateTime} returns {@code NANOS}<br>
191     * {@code Era} returns {@code ERAS}<br>
192     * {@code DayOfWeek} returns {@code DAYS}<br>
193     * {@code Month} returns {@code MONTHS}<br>
194     * {@code Year} returns {@code YEARS}<br>
195     * {@code YearMonth} returns {@code MONTHS}<br>
196     * {@code MonthDay} returns null (does not represent a complete date or time)<br>
197     * {@code ZoneOffset} returns null (does not represent a date or time)<br>
198     * {@code Instant} returns {@code NANOS}<br>
199     * @return a ChronoUnit, may be null
200     */
201    public static final TemporalQuery<ChronoUnit> precision() {
202        return PRECISION;
203    }
204    static final TemporalQuery<ChronoUnit> PRECISION = new TemporalQuery<ChronoUnit>() {
205        @Override
206        public ChronoUnit queryFrom(TemporalAccessor temporal) {
207            return temporal.query(this);
208        }
209    };
210
211    //-----------------------------------------------------------------------
212    // non-special constants are standard queries that derive information from other information
213    /**
214     * A lenient query for the {@code ZoneId}, falling back to the {@code ZoneOffset}.
215     * <p>
216     * This queries a {@code TemporalAccessor} for the zone.
217     * It first tries to obtain the zone, using {@link #zoneId()}.
218     * If that is not found it tries to obtain the {@link #offset()}.
219     * <p>
220     * In most cases, applications should use this query rather than {@code #zoneId()}.
221     * <p>
222     * This query examines the {@link ChronoField#OFFSET_SECONDS offset-seconds}
223     * field and uses it to create a {@code ZoneOffset}.
224     * <p>
225     * The method {@link ZoneId#from(TemporalAccessor)} can be used as a
226     * {@code TemporalQuery} via a method reference, {@code ZoneId::from}.
227     * That method is equivalent to this query, except that it throws an
228     * exception if a zone cannot be obtained.
229     * @return a ZoneId, may be null
230     */
231    public static final TemporalQuery<ZoneId> zone() {
232        return ZONE;
233    }
234    static final TemporalQuery<ZoneId> ZONE = new TemporalQuery<ZoneId>() {
235        @Override
236        public ZoneId queryFrom(TemporalAccessor temporal) {
237            ZoneId zone = temporal.query(ZONE_ID);
238            return (zone != null ? zone : temporal.query(OFFSET));
239        }
240    };
241
242    /**
243     * A query for the {@code ZoneOffset}.
244     * <p>
245     * This queries a {@code TemporalAccessor} for the offset.
246     * <p>
247     * This query examines the {@link ChronoField#OFFSET_SECONDS offset-seconds}
248     * field and uses it to create a {@code ZoneOffset}.
249     * <p>
250     * The method {@link ZoneOffset#from(TemporalAccessor)} can be used as a
251     * {@code TemporalQuery} via a method reference, {@code ZoneOffset::from}.
252     * That method is equivalent to this query, except that it throws an
253     * exception if an offset cannot be obtained.
254     * @return a ZoneOffset, may be null
255     */
256    public static final TemporalQuery<ZoneOffset> offset() {
257        return OFFSET;
258    }
259    static final TemporalQuery<ZoneOffset> OFFSET = new TemporalQuery<ZoneOffset>() {
260        @Override
261        public ZoneOffset queryFrom(TemporalAccessor temporal) {
262            if (temporal.isSupported(OFFSET_SECONDS)) {
263                return ZoneOffset.ofTotalSeconds(temporal.get(OFFSET_SECONDS));
264            }
265            return null;
266        }
267    };
268
269}