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.chrono; 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.ChronoUnit.NANOS; 67 68 import java.time.DateTimeException; 69 import java.time.Instant; 70 import java.time.LocalDateTime; 71 import java.time.LocalTime; 72 import java.time.ZoneId; 73 import java.time.ZoneOffset; 74 import java.time.format.DateTimeFormatter; 75 import java.time.temporal.ChronoField; 76 import java.time.temporal.Queries; 77 import java.time.temporal.Temporal; 78 import java.time.temporal.TemporalAccessor; 79 import java.time.temporal.TemporalAdjuster; 80 import java.time.temporal.TemporalAmount; 81 import java.time.temporal.TemporalField; 82 import java.time.temporal.TemporalQuery; 83 import java.time.temporal.TemporalUnit; 84 import java.time.zone.ZoneRules; 85 import java.util.Comparator; 86 import java.util.Objects; 87 88 /** 89 * A date-time without a time-zone in an arbitrary chronology, intended 90 * for advanced globalization use cases. 91 * <p> 92 * <b>Most applications should declare method signatures, fields and variables 93 * as {@link LocalDateTime}, not this interface.</b> 94 * <p> 95 * A {@code ChronoLocalDateTime} is the abstract representation of a local date-time 96 * where the {@code Chronology chronology}, or calendar system, is pluggable. 97 * The date-time is defined in terms of fields expressed by {@link TemporalField}, 98 * where most common implementations are defined in {@link ChronoField}. 99 * The chronology defines how the calendar system operates and the meaning of 100 * the standard fields. 101 * 102 * <h3>When to use this interface</h3> 103 * The design of the API encourages the use of {@code LocalDateTime} rather than this 104 * interface, even in the case where the application needs to deal with multiple 105 * calendar systems. The rationale for this is explored in detail in {@link ChronoLocalDate}. 106 * <p> 107 * Ensure that the discussion in {@code ChronoLocalDate} has been read and understood 108 * before using this interface. 109 * 110 * <h3>Specification for implementors</h3> 111 * This interface must be implemented with care to ensure other classes operate correctly. 112 * All implementations that can be instantiated must be final, immutable and thread-safe. 113 * Subclasses should be Serializable wherever possible. 114 * 115 * @param <D> the concrete type for the date of this date-time 116 * @since 1.8 117 */ 118 public interface ChronoLocalDateTime<D extends ChronoLocalDate<D>> 119 extends Temporal, TemporalAdjuster, Comparable<ChronoLocalDateTime<?>> { 120 121 /** 122 * Comparator for two {@code ChronoLocalDateTime} instances ignoring the chronology. 123 * <p> 124 * This method differs from the comparison in {@link #compareTo} in that it 125 * only compares the underlying date and not the chronology. 126 * This allows dates in different calendar systems to be compared based 127 * on the time-line position. 128 * 129 * @see #isAfter 130 * @see #isBefore 131 * @see #isEqual 132 */ 133 Comparator<ChronoLocalDateTime<?>> DATE_TIME_COMPARATOR = 134 new Comparator<ChronoLocalDateTime<?>>() { 135 @Override 136 public int compare(ChronoLocalDateTime<?> datetime1, ChronoLocalDateTime<?> datetime2) { 137 int cmp = Long.compare(datetime1.toLocalDate().toEpochDay(), datetime2.toLocalDate().toEpochDay()); 138 if (cmp == 0) { 139 cmp = Long.compare(datetime1.toLocalTime().toNanoOfDay(), datetime2.toLocalTime().toNanoOfDay()); 140 } 141 return cmp; 142 } 143 }; 144 145 /** 146 * Gets the local date part of this date-time. 147 * <p> 148 * This returns a local date with the same year, month and day 149 * as this date-time. 150 * 151 * @return the date part of this date-time, not null 152 */ 153 D toLocalDate() ; 154 155 /** 156 * Gets the local time part of this date-time. 157 * <p> 158 * This returns a local time with the same hour, minute, second and 159 * nanosecond as this date-time. 160 * 161 * @return the time part of this date-time, not null 162 */ 163 LocalTime toLocalTime(); 164 165 @Override // Override to provide javadoc 166 public boolean isSupported(TemporalField field); 167 168 //----------------------------------------------------------------------- 169 // override for covariant return type 170 /** 171 * {@inheritDoc} 172 * @throws DateTimeException {@inheritDoc} 173 * @throws ArithmeticException {@inheritDoc} 174 */ 175 @Override 176 public default ChronoLocalDateTime<D> with(TemporalAdjuster adjuster) { 177 return (ChronoLocalDateTime<D>)(toLocalDate().getChronology().ensureChronoLocalDateTime(Temporal.super.with(adjuster))); 178 } 179 180 /** 181 * {@inheritDoc} 182 * @throws DateTimeException {@inheritDoc} 183 * @throws ArithmeticException {@inheritDoc} 184 */ 185 @Override 186 ChronoLocalDateTime<D> with(TemporalField field, long newValue); 187 188 /** 189 * {@inheritDoc} 190 * @throws DateTimeException {@inheritDoc} 191 * @throws ArithmeticException {@inheritDoc} 192 */ 193 @Override 194 public default ChronoLocalDateTime<D> plus(TemporalAmount amount) { 195 return (ChronoLocalDateTime<D>)(toLocalDate().getChronology().ensureChronoLocalDateTime(Temporal.super.plus(amount))); 196 } 197 198 /** 199 * {@inheritDoc} 200 * @throws DateTimeException {@inheritDoc} 201 * @throws ArithmeticException {@inheritDoc} 202 */ 203 @Override 204 ChronoLocalDateTime<D> plus(long amountToAdd, TemporalUnit unit); 205 206 /** 207 * {@inheritDoc} 208 * @throws DateTimeException {@inheritDoc} 209 * @throws ArithmeticException {@inheritDoc} 210 */ 211 @Override 212 public default ChronoLocalDateTime<D> minus(TemporalAmount amount) { 213 return (ChronoLocalDateTime<D>)(toLocalDate().getChronology().ensureChronoLocalDateTime(Temporal.super.minus(amount))); 214 } 215 216 /** 217 * {@inheritDoc} 218 * @throws DateTimeException {@inheritDoc} 219 * @throws ArithmeticException {@inheritDoc} 220 */ 221 @Override 222 public default ChronoLocalDateTime<D> minus(long amountToSubtract, TemporalUnit unit) { 223 return (ChronoLocalDateTime<D>)(toLocalDate().getChronology().ensureChronoLocalDateTime(Temporal.super.minus(amountToSubtract, unit))); 224 } 225 226 //----------------------------------------------------------------------- 227 /** 228 * Queries this date-time using the specified query. 229 * <p> 230 * This queries this date-time using the specified query strategy object. 231 * The {@code TemporalQuery} object defines the logic to be used to 232 * obtain the result. Read the documentation of the query to understand 233 * what the result of this method will be. 234 * <p> 235 * The result of this method is obtained by invoking the 236 * {@link java.time.temporal.TemporalQuery#queryFrom(TemporalAccessor)} method on the 237 * specified query passing {@code this} as the argument. 238 * 239 * @param <R> the type of the result 240 * @param query the query to invoke, not null 241 * @return the query result, null may be returned (defined by the query) 242 * @throws DateTimeException if unable to query (defined by the query) 243 * @throws ArithmeticException if numeric overflow occurs (defined by the query) 244 */ 245 @SuppressWarnings("unchecked") 246 @Override 247 public default <R> R query(TemporalQuery<R> query) { 248 if (query == Queries.zoneId() || query == Queries.zone() || query == Queries.offset()) { 249 return null; 250 } else if (query == Queries.localTime()) { 251 return (R) toLocalTime(); 252 } else if (query == Queries.chronology()) { 253 return (R) toLocalDate().getChronology(); 254 } else if (query == Queries.precision()) { 255 return (R) NANOS; 256 } 257 // inline TemporalAccessor.super.query(query) as an optimization 258 // non-JDK classes are not permitted to make this optimization 259 return query.queryFrom(this); 260 } 261 262 /** 263 * Adjusts the specified temporal object to have the same date and time as this object. 264 * <p> 265 * This returns a temporal object of the same observable type as the input 266 * with the date and time changed to be the same as this. 267 * <p> 268 * The adjustment is equivalent to using {@link Temporal#with(TemporalField, long)} 269 * twice, passing {@link ChronoField#EPOCH_DAY} and 270 * {@link ChronoField#NANO_OF_DAY} as the fields. 271 * <p> 272 * In most cases, it is clearer to reverse the calling pattern by using 273 * {@link Temporal#with(TemporalAdjuster)}: 274 * <pre> 275 * // these two lines are equivalent, but the second approach is recommended 276 * temporal = thisLocalDateTime.adjustInto(temporal); 277 * temporal = temporal.with(thisLocalDateTime); 278 * </pre> 279 * <p> 280 * This instance is immutable and unaffected by this method call. 281 * 282 * @param temporal the target object to be adjusted, not null 283 * @return the adjusted object, not null 284 * @throws DateTimeException if unable to make the adjustment 285 * @throws ArithmeticException if numeric overflow occurs 286 */ 287 @Override 288 public default Temporal adjustInto(Temporal temporal) { 289 return temporal 290 .with(EPOCH_DAY, toLocalDate().toEpochDay()) 291 .with(NANO_OF_DAY, toLocalTime().toNanoOfDay()); 292 } 293 294 //----------------------------------------------------------------------- 295 /** 296 * Combines this time with a time-zone to create a {@code ChronoZonedDateTime}. 297 * <p> 298 * This returns a {@code ChronoZonedDateTime} formed from this date-time at the 299 * specified time-zone. The result will match this date-time as closely as possible. 300 * Time-zone rules, such as daylight savings, mean that not every local date-time 301 * is valid for the specified zone, thus the local date-time may be adjusted. 302 * <p> 303 * The local date-time is resolved to a single instant on the time-line. 304 * This is achieved by finding a valid offset from UTC/Greenwich for the local 305 * date-time as defined by the {@link ZoneRules rules} of the zone ID. 306 *<p> 307 * In most cases, there is only one valid offset for a local date-time. 308 * In the case of an overlap, where clocks are set back, there are two valid offsets. 309 * This method uses the earlier offset typically corresponding to "summer". 310 * <p> 311 * In the case of a gap, where clocks jump forward, there is no valid offset. 312 * Instead, the local date-time is adjusted to be later by the length of the gap. 313 * For a typical one hour daylight savings change, the local date-time will be 314 * moved one hour later into the offset typically corresponding to "summer". 315 * <p> 316 * To obtain the later offset during an overlap, call 317 * {@link ChronoZonedDateTime#withLaterOffsetAtOverlap()} on the result of this method. 318 * 319 * @param zone the time-zone to use, not null 320 * @return the zoned date-time formed from this date-time, not null 321 */ 322 ChronoZonedDateTime<D> atZone(ZoneId zone); 323 324 //----------------------------------------------------------------------- 325 /** 326 * Converts this date-time to an {@code Instant}. 327 * <p> 328 * This combines this local date-time and the specified offset to form 329 * an {@code Instant}. 330 * <p> 331 * This default implementation calculates from the epoch-day of the date and the 332 * second-of-day of the time. 333 * 334 * @param offset the offset to use for the conversion, not null 335 * @return an {@code Instant} representing the same instant, not null 336 */ 337 public default Instant toInstant(ZoneOffset offset) { 338 return Instant.ofEpochSecond(toEpochSecond(offset), toLocalTime().getNano()); 339 } 340 341 /** 342 * Converts this date-time to the number of seconds from the epoch 343 * of 1970-01-01T00:00:00Z. 344 * <p> 345 * This combines this local date-time and the specified offset to calculate the 346 * epoch-second value, which is the number of elapsed seconds from 1970-01-01T00:00:00Z. 347 * Instants on the time-line after the epoch are positive, earlier are negative. 348 * <p> 349 * This default implementation calculates from the epoch-day of the date and the 350 * second-of-day of the time. 351 * 352 * @param offset the offset to use for the conversion, not null 353 * @return the number of seconds from the epoch of 1970-01-01T00:00:00Z 354 */ 355 public default long toEpochSecond(ZoneOffset offset) { 356 Objects.requireNonNull(offset, "offset"); 357 long epochDay = toLocalDate().toEpochDay(); 358 long secs = epochDay * 86400 + toLocalTime().toSecondOfDay(); 359 secs -= offset.getTotalSeconds(); 360 return secs; 361 } 362 363 //----------------------------------------------------------------------- 364 /** 365 * Compares this date-time to another date-time, including the chronology. 366 * <p> 367 * The comparison is based first on the underlying time-line date-time, then 368 * on the chronology. 369 * It is "consistent with equals", as defined by {@link Comparable}. 370 * <p> 371 * For example, the following is the comparator order: 372 * <ol> 373 * <li>{@code 2012-12-03T12:00 (ISO)}</li> 374 * <li>{@code 2012-12-04T12:00 (ISO)}</li> 375 * <li>{@code 2555-12-04T12:00 (ThaiBuddhist)}</li> 376 * <li>{@code 2012-12-05T12:00 (ISO)}</li> 377 * </ol> 378 * Values #2 and #3 represent the same date-time on the time-line. 379 * When two values represent the same date-time, the chronology ID is compared to distinguish them. 380 * This step is needed to make the ordering "consistent with equals". 381 * <p> 382 * If all the date-time objects being compared are in the same chronology, then the 383 * additional chronology stage is not required and only the local date-time is used. 384 * <p> 385 * This default implementation performs the comparison defined above. 386 * 387 * @param other the other date-time to compare to, not null 388 * @return the comparator value, negative if less, positive if greater 389 */ 390 @Override 391 public default int compareTo(ChronoLocalDateTime<?> other) { 392 int cmp = toLocalDate().compareTo(other.toLocalDate()); 393 if (cmp == 0) { 394 cmp = toLocalTime().compareTo(other.toLocalTime()); 395 if (cmp == 0) { 396 cmp = toLocalDate().getChronology().compareTo(other.toLocalDate().getChronology()); 397 } 398 } 399 return cmp; 400 } 401 402 /** 403 * Checks if this date-time is after the specified date-time ignoring the chronology. 404 * <p> 405 * This method differs from the comparison in {@link #compareTo} in that it 406 * only compares the underlying date-time and not the chronology. 407 * This allows dates in different calendar systems to be compared based 408 * on the time-line position. 409 * <p> 410 * This default implementation performs the comparison based on the epoch-day 411 * and nano-of-day. 412 * 413 * @param other the other date-time to compare to, not null 414 * @return true if this is after the specified date-time 415 */ 416 public default boolean isAfter(ChronoLocalDateTime<?> other) { 417 long thisEpDay = this.toLocalDate().toEpochDay(); 418 long otherEpDay = other.toLocalDate().toEpochDay(); 419 return thisEpDay > otherEpDay || 420 (thisEpDay == otherEpDay && this.toLocalTime().toNanoOfDay() > other.toLocalTime().toNanoOfDay()); 421 } 422 423 /** 424 * Checks if this date-time is before the specified date-time ignoring the chronology. 425 * <p> 426 * This method differs from the comparison in {@link #compareTo} in that it 427 * only compares the underlying date-time and not the chronology. 428 * This allows dates in different calendar systems to be compared based 429 * on the time-line position. 430 * <p> 431 * This default implementation performs the comparison based on the epoch-day 432 * and nano-of-day. 433 * 434 * @param other the other date-time to compare to, not null 435 * @return true if this is before the specified date-time 436 */ 437 public default boolean isBefore(ChronoLocalDateTime<?> other) { 438 long thisEpDay = this.toLocalDate().toEpochDay(); 439 long otherEpDay = other.toLocalDate().toEpochDay(); 440 return thisEpDay < otherEpDay || 441 (thisEpDay == otherEpDay && this.toLocalTime().toNanoOfDay() < other.toLocalTime().toNanoOfDay()); 442 } 443 444 /** 445 * Checks if this date-time is equal to the specified date-time ignoring the chronology. 446 * <p> 447 * This method differs from the comparison in {@link #compareTo} in that it 448 * only compares the underlying date and time and not the chronology. 449 * This allows date-times in different calendar systems to be compared based 450 * on the time-line position. 451 * <p> 452 * This default implementation performs the comparison based on the epoch-day 453 * and nano-of-day. 454 * 455 * @param other the other date-time to compare to, not null 456 * @return true if the underlying date-time is equal to the specified date-time on the timeline 457 */ 458 public default boolean isEqual(ChronoLocalDateTime<?> other) { 459 // Do the time check first, it is cheaper than computing EPOCH day. 460 return this.toLocalTime().toNanoOfDay() == other.toLocalTime().toNanoOfDay() && 461 this.toLocalDate().toEpochDay() == other.toLocalDate().toEpochDay(); 462 } 463 464 /** 465 * Checks if this date-time is equal to another date-time, including the chronology. 466 * <p> 467 * Compares this date-time with another ensuring that the date-time and chronology are the same. 468 * 469 * @param obj the object to check, null returns false 470 * @return true if this is equal to the other date 471 */ 472 @Override 473 boolean equals(Object obj); 474 475 /** 476 * A hash code for this date-time. 477 * 478 * @return a suitable hash code 479 */ 480 @Override 481 int hashCode(); 482 483 //----------------------------------------------------------------------- 484 /** 485 * Outputs this date-time as a {@code String}. 486 * <p> 487 * The output will include the full local date-time and the chronology ID. 488 * 489 * @return a string representation of this date-time, not null 490 */ 491 @Override 492 String toString(); 493 494 /** 495 * Outputs this date-time as a {@code String} using the formatter. 496 * <p> 497 * The default implementation must behave as follows: 498 * <pre> 499 * return formatter.format(this); 500 * </pre> 501 * 502 * @param formatter the formatter to use, not null 503 * @return the formatted date-time string, not null 504 * @throws DateTimeException if an error occurs during printing 505 */ 506 public default String toString(DateTimeFormatter formatter) { 507 Objects.requireNonNull(formatter, "formatter"); 508 return formatter.format(this); 509 } 510 }