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}