1 /* 2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /* 27 * This file is available under and governed by the GNU General Public 28 * License version 2 only, as published by the Free Software Foundation. 29 * However, the following notice accompanied the original version of this 30 * file: 31 * 32 * Copyright (c) 2007-2012, Stephen Colebourne & Michael Nascimento Santos 33 * 34 * All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions are met: 38 * 39 * * Redistributions of source code must retain the above copyright notice, 40 * this list of conditions and the following disclaimer. 41 * 42 * * Redistributions in binary form must reproduce the above copyright notice, 43 * this list of conditions and the following disclaimer in the documentation 44 * and/or other materials provided with the distribution. 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 static java.time.temporal.ChronoField.OFFSET_SECONDS; 65 66 import java.time.ZoneId; 67 import java.time.ZoneOffset; 68 69 /** 70 * Common implementations of {@code TemporalQuery}. 71 * <p> 72 * This class provides common implementations of {@link TemporalQuery}. 73 * These queries are primarily used as optimizations, allowing the internals 74 * of other objects to be extracted effectively. Note that application code 75 * can also use the {@code from(TemporalAccessor)} method on most temporal 76 * objects as a method reference matching the query interface, such as 77 * {@code LocalDate::from} and {@code ZoneId::from}. 78 * <p> 79 * There are two equivalent ways of using a {@code TemporalQuery}. 80 * The first is to invoke the method on the interface directly. 81 * The second is to use {@link TemporalAccessor#query(TemporalQuery)}: 82 * <pre> 83 * // these two lines are equivalent, but the second approach is recommended 84 * dateTime = query.queryFrom(dateTime); 85 * dateTime = dateTime.query(query); 86 * </pre> 87 * It is recommended to use the second approach, {@code query(TemporalQuery)}, 88 * as it is a lot clearer to read in code. 89 * 90 * <h3>Specification for implementors</h3> 91 * This is a thread-safe utility class. 92 * All returned adjusters are immutable and thread-safe. 93 * 94 * @since 1.8 95 */ 96 public final class Queries { 97 // note that it is vital that each method supplies a constant, not a 98 // calculated value, as they will be checked for using == 99 // it is also vital that each constant is different (due to the == checking) 100 // as such, alterations to use lambdas must be done with extreme care 101 102 /** 103 * Private constructor since this is a utility class. 104 */ 105 private Queries() { 106 } 107 108 //----------------------------------------------------------------------- 109 // special constants should be used to extract information from a TemporalAccessor 110 // that cannot be derived in other ways 111 // Javadoc added here, so as to pretend they are more normal than they really are 112 113 /** 114 * A strict query for the {@code ZoneId}. 115 * <p> 116 * This queries a {@code TemporalAccessor} for the zone. 117 * The zone is only returned if the date-time conceptually contains a {@code ZoneId}. 118 * It will not be returned if the date-time only conceptually has an {@code ZoneOffset}. 119 * Thus a {@link java.time.ZonedDateTime ZonedDateTime} will return the result of 120 * {@code getZone()}, but an {@link java.time.temporal.OffsetDateTime OffsetDateTime} will 121 * return null. 122 * <p> 123 * In most cases, applications should use {@link #ZONE} as this query is too strict. 124 * <p> 125 * The result from JDK classes implementing {@code TemporalAccessor} is as follows:<br> 126 * {@code LocalDate} returns null<br> 127 * {@code LocalTime} returns null<br> 128 * {@code LocalDateTime} returns null<br> 129 * {@code ZonedDateTime} returns the associated zone<br> 130 * {@code OffsetDate} returns null<br> 131 * {@code OffsetTime} returns null<br> 132 * {@code OffsetDateTime} returns null<br> 133 * {@code ChronoLocalDate} returns null<br> 134 * {@code ChronoLocalDateTime} returns null<br> 135 * {@code ChronoZonedDateTime} returns the associated zone<br> 136 * {@code Era} returns null<br> 137 * {@code DayOfWeek} returns null<br> 138 * {@code Month} returns null<br> 139 * {@code Year} returns null<br> 140 * {@code YearMonth} returns null<br> 141 * {@code MonthDay} returns null<br> 142 * {@code ZoneOffset} returns null<br> 143 * {@code Instant} returns null<br> 144 * @return a ZoneId, may be null 145 */ 146 public static final TemporalQuery<ZoneId> zoneId() { 147 return ZONE_ID; 148 } 149 static final TemporalQuery<ZoneId> ZONE_ID = new TemporalQuery<ZoneId>() { 150 @Override 151 public ZoneId queryFrom(TemporalAccessor temporal) { 152 return temporal.query(this); 153 } 154 }; 155 156 /** 157 * A query for the {@code Chrono}. 158 * <p> 159 * This queries a {@code TemporalAccessor} for the chronology. 160 * If the target {@code TemporalAccessor} represents a date, or part of a date, 161 * then it should return the chronology that the date is expressed in. 162 * As a result of this definition, objects only representing time, such as 163 * {@code LocalTime}, will return null. 164 * <p> 165 * The result from JDK classes implementing {@code TemporalAccessor} is as follows:<br> 166 * {@code LocalDate} returns {@code ISOChrono.INSTANCE}<br> 167 * {@code LocalTime} returns null (does not represent a date)<br> 168 * {@code LocalDateTime} returns {@code ISOChrono.INSTANCE}<br> 169 * {@code ZonedDateTime} returns {@code ISOChrono.INSTANCE}<br> 170 * {@code OffsetDate} returns {@code ISOChrono.INSTANCE}<br> 171 * {@code OffsetTime} returns null (does not represent a date)<br> 172 * {@code OffsetDateTime} returns {@code ISOChrono.INSTANCE}<br> 173 * {@code ChronoLocalDate} returns the associated chronology<br> 174 * {@code ChronoLocalDateTime} returns the associated chronology<br> 175 * {@code ChronoZonedDateTime} returns the associated chronology<br> 176 * {@code Era} returns the associated chronology<br> 177 * {@code DayOfWeek} returns null (shared across chronologies)<br> 178 * {@code Month} returns {@code ISOChrono.INSTANCE}<br> 179 * {@code Year} returns {@code ISOChrono.INSTANCE}<br> 180 * {@code YearMonth} returns {@code ISOChrono.INSTANCE}<br> 181 * {@code MonthDay} returns null {@code ISOChrono.INSTANCE}<br> 182 * {@code ZoneOffset} returns null (does not represent a date)<br> 183 * {@code Instant} returns null (does not represent a date)<br> 184 * <p> 185 * The method {@link Chrono#from(TemporalAccessor)} can be used as a 186 * {@code TemporalQuery} via a method reference, {@code Chrono::from}. 187 * That method is equivalent to this query, except that it throws an 188 * exception if a chronology cannot be obtained. 189 * @return a Chrono, may be null 190 */ 191 public static final TemporalQuery<Chrono<?>> chrono() { 192 return CHRONO; 193 } 194 static final TemporalQuery<Chrono<?>> CHRONO = new TemporalQuery<Chrono<?>>() { 195 @Override 196 public Chrono<?> queryFrom(TemporalAccessor temporal) { 197 return temporal.query(this); 198 } 199 }; 200 201 /** 202 * A query for the smallest supported unit. 203 * <p> 204 * This queries a {@code TemporalAccessor} for the time precision. 205 * If the target {@code TemporalAccessor} represents a consistent or complete date-time, 206 * date or time then this must return the smallest precision actually supported. 207 * Note that fields such as {@code NANO_OF_DAY} and {@code NANO_OF_SECOND} 208 * are defined to always return ignoring the precision, thus this is the only 209 * way to find the actual smallest supported unit. 210 * For example, were {@code GregorianCalendar} to implement {@code TemporalAccessor} 211 * it would return a precision of {@code MILLIS}. 212 * <p> 213 * The result from JDK classes implementing {@code TemporalAccessor} is as follows:<br> 214 * {@code LocalDate} returns {@code DAYS}<br> 215 * {@code LocalTime} returns {@code NANOS}<br> 216 * {@code LocalDateTime} returns {@code NANOS}<br> 217 * {@code ZonedDateTime} returns {@code NANOS}<br> 218 * {@code OffsetDate} returns {@code DAYS}<br> 219 * {@code OffsetTime} returns {@code NANOS}<br> 220 * {@code OffsetDateTime} returns {@code NANOS}<br> 221 * {@code ChronoLocalDate} returns {@code DAYS}<br> 222 * {@code ChronoLocalDateTime} returns {@code NANOS}<br> 223 * {@code ChronoZonedDateTime} returns {@code NANOS}<br> 224 * {@code Era} returns {@code ERAS}<br> 225 * {@code DayOfWeek} returns {@code DAYS}<br> 226 * {@code Month} returns {@code MONTHS}<br> 227 * {@code Year} returns {@code YEARS}<br> 228 * {@code YearMonth} returns {@code MONTHS}<br> 229 * {@code MonthDay} returns null (does not represent a complete date or time)<br> 230 * {@code ZoneOffset} returns null (does not represent a date or time)<br> 231 * {@code Instant} returns {@code NANOS}<br> 232 * @return a ChronoUnit, may be null 233 */ 234 public static final TemporalQuery<ChronoUnit> precision() { 235 return PRECISION; 236 } 237 static final TemporalQuery<ChronoUnit> PRECISION = new TemporalQuery<ChronoUnit>() { 238 @Override 239 public ChronoUnit queryFrom(TemporalAccessor temporal) { 240 return temporal.query(this); 241 } 242 }; 243 244 //----------------------------------------------------------------------- 245 // non-special constants are standard queries that derive information from other information 246 /** 247 * A lenient query for the {@code ZoneId}, falling back to the {@code ZoneOffset}. 248 * <p> 249 * This queries a {@code TemporalAccessor} for the zone. 250 * It first tries to obtain the zone, using {@link #zoneId()}. 251 * If that is not found it tries to obtain the {@link #offset()}. 252 * <p> 253 * In most cases, applications should use this query rather than {@code #zoneId()}. 254 * <p> 255 * This query examines the {@link java.time.temporal.ChronoField#OFFSET_SECONDS offset-seconds} 256 * field and uses it to create a {@code ZoneOffset}. 257 * <p> 258 * The method {@link ZoneId#from(TemporalAccessor)} can be used as a 259 * {@code TemporalQuery} via a method reference, {@code ZoneId::from}. 260 * That method is equivalent to this query, except that it throws an 261 * exception if a zone cannot be obtained. 262 * @return a ZoneId, may be null 263 */ 264 public static final TemporalQuery<ZoneId> zone() { 265 return ZONE; 266 } 267 static final TemporalQuery<ZoneId> ZONE = new TemporalQuery<ZoneId>() { 268 @Override 269 public ZoneId queryFrom(TemporalAccessor temporal) { 270 ZoneId zone = temporal.query(ZONE_ID); 271 return (zone != null ? zone : temporal.query(OFFSET)); 272 } 273 }; 274 275 /** 276 * A query for the {@code ZoneOffset}. 277 * <p> 278 * This queries a {@code TemporalAccessor} for the offset. 279 * <p> 280 * This query examines the {@link java.time.temporal.ChronoField#OFFSET_SECONDS offset-seconds} 281 * field and uses it to create a {@code ZoneOffset}. 282 * <p> 283 * The method {@link ZoneOffset#from(TemporalAccessor)} can be used as a 284 * {@code TemporalQuery} via a method reference, {@code ZoneOffset::from}. 285 * That method is equivalent to this query, except that it throws an 286 * exception if an offset cannot be obtained. 287 * @return a ZoneOffset, may be null 288 */ 289 public static final TemporalQuery<ZoneOffset> offset() { 290 return OFFSET; 291 } 292 static final TemporalQuery<ZoneOffset> OFFSET = new TemporalQuery<ZoneOffset>() { 293 @Override 294 public ZoneOffset queryFrom(TemporalAccessor temporal) { 295 if (temporal.isSupported(OFFSET_SECONDS)) { 296 return ZoneOffset.ofTotalSeconds(temporal.get(OFFSET_SECONDS)); 297 } 298 return null; 299 } 300 }; 301 302 }