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.EPOCH_DAY; 65 import static java.time.temporal.ChronoField.NANO_OF_DAY; 66 import static java.time.temporal.ChronoField.OFFSET_SECONDS; 67 68 import java.time.LocalDate; 69 import java.time.LocalTime; 70 import java.time.ZoneId; 71 import java.time.ZoneOffset; 72 import java.time.chrono.Chronology; 73 74 /** 75 * Common implementations of {@code TemporalQuery}. 76 * <p> 77 * This class provides common implementations of {@link TemporalQuery}. 78 * These are defined here as they must be constants, and the definition 79 * of lambdas does not guarantee that. By assigning them once here, 80 * they become 'normal' Java constants. 81 * <p> 82 * Queries are a key tool for extracting information from temporal objects. 83 * They exist to externalize the process of querying, permitting different 84 * approaches, as per the strategy design pattern. 85 * Examples might be a query that checks if the date is the day before February 29th 86 * in a leap year, or calculates the number of days to your next birthday. 87 * <p> 88 * The {@link TemporalField} interface provides another mechanism for querying 89 * temporal objects. That interface is limited to returning a {@code long}. 90 * By contrast, queries can return any type. 91 * <p> 92 * There are two equivalent ways of using a {@code TemporalQuery}. 93 * The first is to invoke the method on this interface directly. 94 * The second is to use {@link TemporalAccessor#query(TemporalQuery)}: 95 * <pre> 96 * // these two lines are equivalent, but the second approach is recommended 97 * temporal = thisQuery.queryFrom(temporal); 98 * temporal = temporal.query(thisQuery); 99 * </pre> 100 * It is recommended to use the second approach, {@code query(TemporalQuery)}, 101 * as it is a lot clearer to read in code. 102 * <p> 103 * The most common implementations are method references, such as 104 * {@code LocalDate::from} and {@code ZoneId::from}. 105 * Additional common queries are provided to return: 106 * <ul> 107 * <li> a Chronology, 108 * <li> a LocalDate, 109 * <li> a LocalTime, 110 * <li> a ZoneOffset, 111 * <li> a precision, 112 * <li> a zone, or 113 * <li> a zoneId. 114 * </ul> 115 * 116 * @since 1.8 117 */ 118 public final class TemporalQueries { 119 // note that it is vital that each method supplies a constant, not a 120 // calculated value, as they will be checked for using == 121 // it is also vital that each constant is different (due to the == checking) 122 // as such, alterations to this code must be done with care 123 124 /** 125 * Private constructor since this is a utility class. 126 */ TemporalQueries()127 private TemporalQueries() { 128 } 129 130 //----------------------------------------------------------------------- 131 // special constants should be used to extract information from a TemporalAccessor 132 // that cannot be derived in other ways 133 // Javadoc added here, so as to pretend they are more normal than they really are 134 135 /** 136 * A strict query for the {@code ZoneId}. 137 * <p> 138 * This queries a {@code TemporalAccessor} for the zone. 139 * The zone is only returned if the date-time conceptually contains a {@code ZoneId}. 140 * It will not be returned if the date-time only conceptually has an {@code ZoneOffset}. 141 * Thus a {@link java.time.ZonedDateTime} will return the result of {@code getZone()}, 142 * but an {@link java.time.OffsetDateTime} will return null. 143 * <p> 144 * In most cases, applications should use {@link #zone()} as this query is too strict. 145 * <p> 146 * The result from JDK classes implementing {@code TemporalAccessor} is as follows:<br> 147 * {@code LocalDate} returns null<br> 148 * {@code LocalTime} returns null<br> 149 * {@code LocalDateTime} returns null<br> 150 * {@code ZonedDateTime} returns the associated zone<br> 151 * {@code OffsetTime} returns null<br> 152 * {@code OffsetDateTime} returns null<br> 153 * {@code ChronoLocalDate} returns null<br> 154 * {@code ChronoLocalDateTime} returns null<br> 155 * {@code ChronoZonedDateTime} returns the associated zone<br> 156 * {@code Era} returns null<br> 157 * {@code DayOfWeek} returns null<br> 158 * {@code Month} returns null<br> 159 * {@code Year} returns null<br> 160 * {@code YearMonth} returns null<br> 161 * {@code MonthDay} returns null<br> 162 * {@code ZoneOffset} returns null<br> 163 * {@code Instant} returns null<br> 164 * 165 * @return a query that can obtain the zone ID of a temporal, not null 166 */ zoneId()167 public static TemporalQuery<ZoneId> zoneId() { 168 return TemporalQueries.ZONE_ID; 169 } 170 171 /** 172 * A query for the {@code Chronology}. 173 * <p> 174 * This queries a {@code TemporalAccessor} for the chronology. 175 * If the target {@code TemporalAccessor} represents a date, or part of a date, 176 * then it should return the chronology that the date is expressed in. 177 * As a result of this definition, objects only representing time, such as 178 * {@code LocalTime}, will return null. 179 * <p> 180 * The result from JDK classes implementing {@code TemporalAccessor} is as follows:<br> 181 * {@code LocalDate} returns {@code IsoChronology.INSTANCE}<br> 182 * {@code LocalTime} returns null (does not represent a date)<br> 183 * {@code LocalDateTime} returns {@code IsoChronology.INSTANCE}<br> 184 * {@code ZonedDateTime} returns {@code IsoChronology.INSTANCE}<br> 185 * {@code OffsetTime} returns null (does not represent a date)<br> 186 * {@code OffsetDateTime} returns {@code IsoChronology.INSTANCE}<br> 187 * {@code ChronoLocalDate} returns the associated chronology<br> 188 * {@code ChronoLocalDateTime} returns the associated chronology<br> 189 * {@code ChronoZonedDateTime} returns the associated chronology<br> 190 * {@code Era} returns the associated chronology<br> 191 * {@code DayOfWeek} returns null (shared across chronologies)<br> 192 * {@code Month} returns {@code IsoChronology.INSTANCE}<br> 193 * {@code Year} returns {@code IsoChronology.INSTANCE}<br> 194 * {@code YearMonth} returns {@code IsoChronology.INSTANCE}<br> 195 * {@code MonthDay} returns null {@code IsoChronology.INSTANCE}<br> 196 * {@code ZoneOffset} returns null (does not represent a date)<br> 197 * {@code Instant} returns null (does not represent a date)<br> 198 * <p> 199 * The method {@link java.time.chrono.Chronology#from(TemporalAccessor)} can be used as a 200 * {@code TemporalQuery} via a method reference, {@code Chronology::from}. 201 * That method is equivalent to this query, except that it throws an 202 * exception if a chronology cannot be obtained. 203 * 204 * @return a query that can obtain the chronology of a temporal, not null 205 */ chronology()206 public static TemporalQuery<Chronology> chronology() { 207 return TemporalQueries.CHRONO; 208 } 209 210 /** 211 * A query for the smallest supported unit. 212 * <p> 213 * This queries a {@code TemporalAccessor} for the time precision. 214 * If the target {@code TemporalAccessor} represents a consistent or complete date-time, 215 * date or time then this must return the smallest precision actually supported. 216 * Note that fields such as {@code NANO_OF_DAY} and {@code NANO_OF_SECOND} 217 * are defined to always return ignoring the precision, thus this is the only 218 * way to find the actual smallest supported unit. 219 * For example, were {@code GregorianCalendar} to implement {@code TemporalAccessor} 220 * it would return a precision of {@code MILLIS}. 221 * <p> 222 * The result from JDK classes implementing {@code TemporalAccessor} is as follows:<br> 223 * {@code LocalDate} returns {@code DAYS}<br> 224 * {@code LocalTime} returns {@code NANOS}<br> 225 * {@code LocalDateTime} returns {@code NANOS}<br> 226 * {@code ZonedDateTime} returns {@code NANOS}<br> 227 * {@code OffsetTime} returns {@code NANOS}<br> 228 * {@code OffsetDateTime} returns {@code NANOS}<br> 229 * {@code ChronoLocalDate} returns {@code DAYS}<br> 230 * {@code ChronoLocalDateTime} returns {@code NANOS}<br> 231 * {@code ChronoZonedDateTime} returns {@code NANOS}<br> 232 * {@code Era} returns {@code ERAS}<br> 233 * {@code DayOfWeek} returns {@code DAYS}<br> 234 * {@code Month} returns {@code MONTHS}<br> 235 * {@code Year} returns {@code YEARS}<br> 236 * {@code YearMonth} returns {@code MONTHS}<br> 237 * {@code MonthDay} returns null (does not represent a complete date or time)<br> 238 * {@code ZoneOffset} returns null (does not represent a date or time)<br> 239 * {@code Instant} returns {@code NANOS}<br> 240 * 241 * @return a query that can obtain the precision of a temporal, not null 242 */ precision()243 public static TemporalQuery<TemporalUnit> precision() { 244 return TemporalQueries.PRECISION; 245 } 246 247 //----------------------------------------------------------------------- 248 // non-special constants are standard queries that derive information from other information 249 /** 250 * A lenient query for the {@code ZoneId}, falling back to the {@code ZoneOffset}. 251 * <p> 252 * This queries a {@code TemporalAccessor} for the zone. 253 * It first tries to obtain the zone, using {@link #zoneId()}. 254 * If that is not found it tries to obtain the {@link #offset()}. 255 * Thus a {@link java.time.ZonedDateTime} will return the result of {@code getZone()}, 256 * while an {@link java.time.OffsetDateTime} will return the result of {@code getOffset()}. 257 * <p> 258 * In most cases, applications should use this query rather than {@code #zoneId()}. 259 * <p> 260 * The method {@link ZoneId#from(TemporalAccessor)} can be used as a 261 * {@code TemporalQuery} via a method reference, {@code ZoneId::from}. 262 * That method is equivalent to this query, except that it throws an 263 * exception if a zone cannot be obtained. 264 * 265 * @return a query that can obtain the zone ID or offset of a temporal, not null 266 */ zone()267 public static TemporalQuery<ZoneId> zone() { 268 return TemporalQueries.ZONE; 269 } 270 271 /** 272 * A query for {@code ZoneOffset} returning null if not found. 273 * <p> 274 * This returns a {@code TemporalQuery} that can be used to query a temporal 275 * object for the offset. The query will return null if the temporal 276 * object cannot supply an offset. 277 * <p> 278 * The query implementation examines the {@link ChronoField#OFFSET_SECONDS OFFSET_SECONDS} 279 * field and uses it to create a {@code ZoneOffset}. 280 * <p> 281 * The method {@link java.time.ZoneOffset#from(TemporalAccessor)} can be used as a 282 * {@code TemporalQuery} via a method reference, {@code ZoneOffset::from}. 283 * This query and {@code ZoneOffset::from} will return the same result if the 284 * temporal object contains an offset. If the temporal object does not contain 285 * an offset, then the method reference will throw an exception, whereas this 286 * query will return null. 287 * 288 * @return a query that can obtain the offset of a temporal, not null 289 */ offset()290 public static TemporalQuery<ZoneOffset> offset() { 291 return TemporalQueries.OFFSET; 292 } 293 294 /** 295 * A query for {@code LocalDate} returning null if not found. 296 * <p> 297 * This returns a {@code TemporalQuery} that can be used to query a temporal 298 * object for the local date. The query will return null if the temporal 299 * object cannot supply a local date. 300 * <p> 301 * The query implementation examines the {@link ChronoField#EPOCH_DAY EPOCH_DAY} 302 * field and uses it to create a {@code LocalDate}. 303 * <p> 304 * The method {@link ZoneOffset#from(TemporalAccessor)} can be used as a 305 * {@code TemporalQuery} via a method reference, {@code LocalDate::from}. 306 * This query and {@code LocalDate::from} will return the same result if the 307 * temporal object contains a date. If the temporal object does not contain 308 * a date, then the method reference will throw an exception, whereas this 309 * query will return null. 310 * 311 * @return a query that can obtain the date of a temporal, not null 312 */ localDate()313 public static TemporalQuery<LocalDate> localDate() { 314 return TemporalQueries.LOCAL_DATE; 315 } 316 317 /** 318 * A query for {@code LocalTime} returning null if not found. 319 * <p> 320 * This returns a {@code TemporalQuery} that can be used to query a temporal 321 * object for the local time. The query will return null if the temporal 322 * object cannot supply a local time. 323 * <p> 324 * The query implementation examines the {@link ChronoField#NANO_OF_DAY NANO_OF_DAY} 325 * field and uses it to create a {@code LocalTime}. 326 * <p> 327 * The method {@link ZoneOffset#from(TemporalAccessor)} can be used as a 328 * {@code TemporalQuery} via a method reference, {@code LocalTime::from}. 329 * This query and {@code LocalTime::from} will return the same result if the 330 * temporal object contains a time. If the temporal object does not contain 331 * a time, then the method reference will throw an exception, whereas this 332 * query will return null. 333 * 334 * @return a query that can obtain the time of a temporal, not null 335 */ localTime()336 public static TemporalQuery<LocalTime> localTime() { 337 return TemporalQueries.LOCAL_TIME; 338 } 339 340 //----------------------------------------------------------------------- 341 /** 342 * A strict query for the {@code ZoneId}. 343 */ 344 static final TemporalQuery<ZoneId> ZONE_ID = (temporal) -> 345 temporal.query(TemporalQueries.ZONE_ID); 346 347 /** 348 * A query for the {@code Chronology}. 349 */ 350 static final TemporalQuery<Chronology> CHRONO = (temporal) -> 351 temporal.query(TemporalQueries.CHRONO); 352 353 /** 354 * A query for the smallest supported unit. 355 */ 356 static final TemporalQuery<TemporalUnit> PRECISION = (temporal) -> 357 temporal.query(TemporalQueries.PRECISION); 358 359 //----------------------------------------------------------------------- 360 /** 361 * A query for {@code ZoneOffset} returning null if not found. 362 */ 363 static final TemporalQuery<ZoneOffset> OFFSET = (temporal) -> { 364 if (temporal.isSupported(OFFSET_SECONDS)) { 365 return ZoneOffset.ofTotalSeconds(temporal.get(OFFSET_SECONDS)); 366 } 367 return null; 368 }; 369 370 /** 371 * A lenient query for the {@code ZoneId}, falling back to the {@code ZoneOffset}. 372 */ 373 static final TemporalQuery<ZoneId> ZONE = (temporal) -> { 374 ZoneId zone = temporal.query(ZONE_ID); 375 return (zone != null ? zone : temporal.query(OFFSET)); 376 }; 377 378 /** 379 * A query for {@code LocalDate} returning null if not found. 380 */ 381 static final TemporalQuery<LocalDate> LOCAL_DATE = (temporal) -> { 382 if (temporal.isSupported(EPOCH_DAY)) { 383 return LocalDate.ofEpochDay(temporal.getLong(EPOCH_DAY)); 384 } 385 return null; 386 }; 387 388 /** 389 * A query for {@code LocalTime} returning null if not found. 390 */ 391 static final TemporalQuery<LocalTime> LOCAL_TIME = (temporal) -> { 392 if (temporal.isSupported(NANO_OF_DAY)) { 393 return LocalTime.ofNanoOfDay(temporal.getLong(NANO_OF_DAY)); 394 } 395 return null; 396 }; 397 398 } 399