1/* 2 * Copyright (c) 2012, 2015, 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 */ 62package java.time; 63 64import static java.time.temporal.ChronoField.EPOCH_DAY; 65import static java.time.temporal.ChronoField.INSTANT_SECONDS; 66import static java.time.temporal.ChronoField.NANO_OF_DAY; 67import static java.time.temporal.ChronoField.OFFSET_SECONDS; 68import static java.time.temporal.ChronoUnit.FOREVER; 69import static java.time.temporal.ChronoUnit.NANOS; 70 71import java.io.IOException; 72import java.io.ObjectInput; 73import java.io.ObjectOutput; 74import java.io.InvalidObjectException; 75import java.io.ObjectInputStream; 76import java.io.Serializable; 77import java.time.chrono.IsoChronology; 78import java.time.format.DateTimeFormatter; 79import java.time.format.DateTimeParseException; 80import java.time.temporal.ChronoField; 81import java.time.temporal.ChronoUnit; 82import java.time.temporal.Temporal; 83import java.time.temporal.TemporalAccessor; 84import java.time.temporal.TemporalAdjuster; 85import java.time.temporal.TemporalAmount; 86import java.time.temporal.TemporalField; 87import java.time.temporal.TemporalQueries; 88import java.time.temporal.TemporalQuery; 89import java.time.temporal.TemporalUnit; 90import java.time.temporal.UnsupportedTemporalTypeException; 91import java.time.temporal.ValueRange; 92import java.time.zone.ZoneRules; 93import java.util.Comparator; 94import java.util.Objects; 95 96// Android-changed: removed ValueBased paragraph. 97/** 98 * A date-time with an offset from UTC/Greenwich in the ISO-8601 calendar system, 99 * such as {@code 2007-12-03T10:15:30+01:00}. 100 * <p> 101 * {@code OffsetDateTime} is an immutable representation of a date-time with an offset. 102 * This class stores all date and time fields, to a precision of nanoseconds, 103 * as well as the offset from UTC/Greenwich. For example, the value 104 * "2nd October 2007 at 13:45.30.123456789 +02:00" can be stored in an {@code OffsetDateTime}. 105 * <p> 106 * {@code OffsetDateTime}, {@link java.time.ZonedDateTime} and {@link java.time.Instant} all store an instant 107 * on the time-line to nanosecond precision. 108 * {@code Instant} is the simplest, simply representing the instant. 109 * {@code OffsetDateTime} adds to the instant the offset from UTC/Greenwich, which allows 110 * the local date-time to be obtained. 111 * {@code ZonedDateTime} adds full time-zone rules. 112 * <p> 113 * It is intended that {@code ZonedDateTime} or {@code Instant} is used to model data 114 * in simpler applications. This class may be used when modeling date-time concepts in 115 * more detail, or when communicating to a database or in a network protocol. 116 * 117 * @implSpec 118 * This class is immutable and thread-safe. 119 * 120 * @since 1.8 121 */ 122public final class OffsetDateTime 123 implements Temporal, TemporalAdjuster, Comparable<OffsetDateTime>, Serializable { 124 125 /** 126 * The minimum supported {@code OffsetDateTime}, '-999999999-01-01T00:00:00+18:00'. 127 * This is the local date-time of midnight at the start of the minimum date 128 * in the maximum offset (larger offsets are earlier on the time-line). 129 * This combines {@link LocalDateTime#MIN} and {@link ZoneOffset#MAX}. 130 * This could be used by an application as a "far past" date-time. 131 */ 132 public static final OffsetDateTime MIN = LocalDateTime.MIN.atOffset(ZoneOffset.MAX); 133 /** 134 * The maximum supported {@code OffsetDateTime}, '+999999999-12-31T23:59:59.999999999-18:00'. 135 * This is the local date-time just before midnight at the end of the maximum date 136 * in the minimum offset (larger negative offsets are later on the time-line). 137 * This combines {@link LocalDateTime#MAX} and {@link ZoneOffset#MIN}. 138 * This could be used by an application as a "far future" date-time. 139 */ 140 public static final OffsetDateTime MAX = LocalDateTime.MAX.atOffset(ZoneOffset.MIN); 141 142 /** 143 * Gets a comparator that compares two {@code OffsetDateTime} instances 144 * based solely on the instant. 145 * <p> 146 * This method differs from the comparison in {@link #compareTo} in that it 147 * only compares the underlying instant. 148 * 149 * @return a comparator that compares in time-line order 150 * 151 * @see #isAfter 152 * @see #isBefore 153 * @see #isEqual 154 */ 155 public static Comparator<OffsetDateTime> timeLineOrder() { 156 return OffsetDateTime::compareInstant; 157 } 158 159 /** 160 * Compares this {@code OffsetDateTime} to another date-time. 161 * The comparison is based on the instant. 162 * 163 * @param datetime1 the first date-time to compare, not null 164 * @param datetime2 the other date-time to compare to, not null 165 * @return the comparator value, negative if less, positive if greater 166 */ 167 private static int compareInstant(OffsetDateTime datetime1, OffsetDateTime datetime2) { 168 if (datetime1.getOffset().equals(datetime2.getOffset())) { 169 return datetime1.toLocalDateTime().compareTo(datetime2.toLocalDateTime()); 170 } 171 int cmp = Long.compare(datetime1.toEpochSecond(), datetime2.toEpochSecond()); 172 if (cmp == 0) { 173 cmp = datetime1.toLocalTime().getNano() - datetime2.toLocalTime().getNano(); 174 } 175 return cmp; 176 } 177 178 /** 179 * Serialization version. 180 */ 181 private static final long serialVersionUID = 2287754244819255394L; 182 183 /** 184 * The local date-time. 185 */ 186 private final LocalDateTime dateTime; 187 /** 188 * The offset from UTC/Greenwich. 189 */ 190 private final ZoneOffset offset; 191 192 //----------------------------------------------------------------------- 193 /** 194 * Obtains the current date-time from the system clock in the default time-zone. 195 * <p> 196 * This will query the {@link Clock#systemDefaultZone() system clock} in the default 197 * time-zone to obtain the current date-time. 198 * The offset will be calculated from the time-zone in the clock. 199 * <p> 200 * Using this method will prevent the ability to use an alternate clock for testing 201 * because the clock is hard-coded. 202 * 203 * @return the current date-time using the system clock, not null 204 */ 205 public static OffsetDateTime now() { 206 return now(Clock.systemDefaultZone()); 207 } 208 209 /** 210 * Obtains the current date-time from the system clock in the specified time-zone. 211 * <p> 212 * This will query the {@link Clock#system(ZoneId) system clock} to obtain the current date-time. 213 * Specifying the time-zone avoids dependence on the default time-zone. 214 * The offset will be calculated from the specified time-zone. 215 * <p> 216 * Using this method will prevent the ability to use an alternate clock for testing 217 * because the clock is hard-coded. 218 * 219 * @param zone the zone ID to use, not null 220 * @return the current date-time using the system clock, not null 221 */ 222 public static OffsetDateTime now(ZoneId zone) { 223 return now(Clock.system(zone)); 224 } 225 226 /** 227 * Obtains the current date-time from the specified clock. 228 * <p> 229 * This will query the specified clock to obtain the current date-time. 230 * The offset will be calculated from the time-zone in the clock. 231 * <p> 232 * Using this method allows the use of an alternate clock for testing. 233 * The alternate clock may be introduced using {@link Clock dependency injection}. 234 * 235 * @param clock the clock to use, not null 236 * @return the current date-time, not null 237 */ 238 public static OffsetDateTime now(Clock clock) { 239 Objects.requireNonNull(clock, "clock"); 240 final Instant now = clock.instant(); // called once 241 return ofInstant(now, clock.getZone().getRules().getOffset(now)); 242 } 243 244 //----------------------------------------------------------------------- 245 /** 246 * Obtains an instance of {@code OffsetDateTime} from a date, time and offset. 247 * <p> 248 * This creates an offset date-time with the specified local date, time and offset. 249 * 250 * @param date the local date, not null 251 * @param time the local time, not null 252 * @param offset the zone offset, not null 253 * @return the offset date-time, not null 254 */ 255 public static OffsetDateTime of(LocalDate date, LocalTime time, ZoneOffset offset) { 256 LocalDateTime dt = LocalDateTime.of(date, time); 257 return new OffsetDateTime(dt, offset); 258 } 259 260 /** 261 * Obtains an instance of {@code OffsetDateTime} from a date-time and offset. 262 * <p> 263 * This creates an offset date-time with the specified local date-time and offset. 264 * 265 * @param dateTime the local date-time, not null 266 * @param offset the zone offset, not null 267 * @return the offset date-time, not null 268 */ 269 public static OffsetDateTime of(LocalDateTime dateTime, ZoneOffset offset) { 270 return new OffsetDateTime(dateTime, offset); 271 } 272 273 /** 274 * Obtains an instance of {@code OffsetDateTime} from a year, month, day, 275 * hour, minute, second, nanosecond and offset. 276 * <p> 277 * This creates an offset date-time with the seven specified fields. 278 * <p> 279 * This method exists primarily for writing test cases. 280 * Non test-code will typically use other methods to create an offset time. 281 * {@code LocalDateTime} has five additional convenience variants of the 282 * equivalent factory method taking fewer arguments. 283 * They are not provided here to reduce the footprint of the API. 284 * 285 * @param year the year to represent, from MIN_YEAR to MAX_YEAR 286 * @param month the month-of-year to represent, from 1 (January) to 12 (December) 287 * @param dayOfMonth the day-of-month to represent, from 1 to 31 288 * @param hour the hour-of-day to represent, from 0 to 23 289 * @param minute the minute-of-hour to represent, from 0 to 59 290 * @param second the second-of-minute to represent, from 0 to 59 291 * @param nanoOfSecond the nano-of-second to represent, from 0 to 999,999,999 292 * @param offset the zone offset, not null 293 * @return the offset date-time, not null 294 * @throws DateTimeException if the value of any field is out of range, or 295 * if the day-of-month is invalid for the month-year 296 */ 297 public static OffsetDateTime of( 298 int year, int month, int dayOfMonth, 299 int hour, int minute, int second, int nanoOfSecond, ZoneOffset offset) { 300 LocalDateTime dt = LocalDateTime.of(year, month, dayOfMonth, hour, minute, second, nanoOfSecond); 301 return new OffsetDateTime(dt, offset); 302 } 303 304 //----------------------------------------------------------------------- 305 /** 306 * Obtains an instance of {@code OffsetDateTime} from an {@code Instant} and zone ID. 307 * <p> 308 * This creates an offset date-time with the same instant as that specified. 309 * Finding the offset from UTC/Greenwich is simple as there is only one valid 310 * offset for each instant. 311 * 312 * @param instant the instant to create the date-time from, not null 313 * @param zone the time-zone, which may be an offset, not null 314 * @return the offset date-time, not null 315 * @throws DateTimeException if the result exceeds the supported range 316 */ 317 public static OffsetDateTime ofInstant(Instant instant, ZoneId zone) { 318 Objects.requireNonNull(instant, "instant"); 319 Objects.requireNonNull(zone, "zone"); 320 ZoneRules rules = zone.getRules(); 321 ZoneOffset offset = rules.getOffset(instant); 322 LocalDateTime ldt = LocalDateTime.ofEpochSecond(instant.getEpochSecond(), instant.getNano(), offset); 323 return new OffsetDateTime(ldt, offset); 324 } 325 326 //----------------------------------------------------------------------- 327 /** 328 * Obtains an instance of {@code OffsetDateTime} from a temporal object. 329 * <p> 330 * This obtains an offset date-time based on the specified temporal. 331 * A {@code TemporalAccessor} represents an arbitrary set of date and time information, 332 * which this factory converts to an instance of {@code OffsetDateTime}. 333 * <p> 334 * The conversion will first obtain a {@code ZoneOffset} from the temporal object. 335 * It will then try to obtain a {@code LocalDateTime}, falling back to an {@code Instant} if necessary. 336 * The result will be the combination of {@code ZoneOffset} with either 337 * with {@code LocalDateTime} or {@code Instant}. 338 * Implementations are permitted to perform optimizations such as accessing 339 * those fields that are equivalent to the relevant objects. 340 * <p> 341 * This method matches the signature of the functional interface {@link TemporalQuery} 342 * allowing it to be used as a query via method reference, {@code OffsetDateTime::from}. 343 * 344 * @param temporal the temporal object to convert, not null 345 * @return the offset date-time, not null 346 * @throws DateTimeException if unable to convert to an {@code OffsetDateTime} 347 */ 348 public static OffsetDateTime from(TemporalAccessor temporal) { 349 if (temporal instanceof OffsetDateTime) { 350 return (OffsetDateTime) temporal; 351 } 352 try { 353 ZoneOffset offset = ZoneOffset.from(temporal); 354 LocalDate date = temporal.query(TemporalQueries.localDate()); 355 LocalTime time = temporal.query(TemporalQueries.localTime()); 356 if (date != null && time != null) { 357 return OffsetDateTime.of(date, time, offset); 358 } else { 359 Instant instant = Instant.from(temporal); 360 return OffsetDateTime.ofInstant(instant, offset); 361 } 362 } catch (DateTimeException ex) { 363 throw new DateTimeException("Unable to obtain OffsetDateTime from TemporalAccessor: " + 364 temporal + " of type " + temporal.getClass().getName(), ex); 365 } 366 } 367 368 //----------------------------------------------------------------------- 369 /** 370 * Obtains an instance of {@code OffsetDateTime} from a text string 371 * such as {@code 2007-12-03T10:15:30+01:00}. 372 * <p> 373 * The string must represent a valid date-time and is parsed using 374 * {@link java.time.format.DateTimeFormatter#ISO_OFFSET_DATE_TIME}. 375 * 376 * @param text the text to parse such as "2007-12-03T10:15:30+01:00", not null 377 * @return the parsed offset date-time, not null 378 * @throws DateTimeParseException if the text cannot be parsed 379 */ 380 public static OffsetDateTime parse(CharSequence text) { 381 return parse(text, DateTimeFormatter.ISO_OFFSET_DATE_TIME); 382 } 383 384 /** 385 * Obtains an instance of {@code OffsetDateTime} from a text string using a specific formatter. 386 * <p> 387 * The text is parsed using the formatter, returning a date-time. 388 * 389 * @param text the text to parse, not null 390 * @param formatter the formatter to use, not null 391 * @return the parsed offset date-time, not null 392 * @throws DateTimeParseException if the text cannot be parsed 393 */ 394 public static OffsetDateTime parse(CharSequence text, DateTimeFormatter formatter) { 395 Objects.requireNonNull(formatter, "formatter"); 396 return formatter.parse(text, OffsetDateTime::from); 397 } 398 399 //----------------------------------------------------------------------- 400 /** 401 * Constructor. 402 * 403 * @param dateTime the local date-time, not null 404 * @param offset the zone offset, not null 405 */ 406 private OffsetDateTime(LocalDateTime dateTime, ZoneOffset offset) { 407 this.dateTime = Objects.requireNonNull(dateTime, "dateTime"); 408 this.offset = Objects.requireNonNull(offset, "offset"); 409 } 410 411 /** 412 * Returns a new date-time based on this one, returning {@code this} where possible. 413 * 414 * @param dateTime the date-time to create with, not null 415 * @param offset the zone offset to create with, not null 416 */ 417 private OffsetDateTime with(LocalDateTime dateTime, ZoneOffset offset) { 418 if (this.dateTime == dateTime && this.offset.equals(offset)) { 419 return this; 420 } 421 return new OffsetDateTime(dateTime, offset); 422 } 423 424 //----------------------------------------------------------------------- 425 /** 426 * Checks if the specified field is supported. 427 * <p> 428 * This checks if this date-time can be queried for the specified field. 429 * If false, then calling the {@link #range(TemporalField) range}, 430 * {@link #get(TemporalField) get} and {@link #with(TemporalField, long)} 431 * methods will throw an exception. 432 * <p> 433 * If the field is a {@link ChronoField} then the query is implemented here. 434 * The supported fields are: 435 * <ul> 436 * <li>{@code NANO_OF_SECOND} 437 * <li>{@code NANO_OF_DAY} 438 * <li>{@code MICRO_OF_SECOND} 439 * <li>{@code MICRO_OF_DAY} 440 * <li>{@code MILLI_OF_SECOND} 441 * <li>{@code MILLI_OF_DAY} 442 * <li>{@code SECOND_OF_MINUTE} 443 * <li>{@code SECOND_OF_DAY} 444 * <li>{@code MINUTE_OF_HOUR} 445 * <li>{@code MINUTE_OF_DAY} 446 * <li>{@code HOUR_OF_AMPM} 447 * <li>{@code CLOCK_HOUR_OF_AMPM} 448 * <li>{@code HOUR_OF_DAY} 449 * <li>{@code CLOCK_HOUR_OF_DAY} 450 * <li>{@code AMPM_OF_DAY} 451 * <li>{@code DAY_OF_WEEK} 452 * <li>{@code ALIGNED_DAY_OF_WEEK_IN_MONTH} 453 * <li>{@code ALIGNED_DAY_OF_WEEK_IN_YEAR} 454 * <li>{@code DAY_OF_MONTH} 455 * <li>{@code DAY_OF_YEAR} 456 * <li>{@code EPOCH_DAY} 457 * <li>{@code ALIGNED_WEEK_OF_MONTH} 458 * <li>{@code ALIGNED_WEEK_OF_YEAR} 459 * <li>{@code MONTH_OF_YEAR} 460 * <li>{@code PROLEPTIC_MONTH} 461 * <li>{@code YEAR_OF_ERA} 462 * <li>{@code YEAR} 463 * <li>{@code ERA} 464 * <li>{@code INSTANT_SECONDS} 465 * <li>{@code OFFSET_SECONDS} 466 * </ul> 467 * All other {@code ChronoField} instances will return false. 468 * <p> 469 * If the field is not a {@code ChronoField}, then the result of this method 470 * is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)} 471 * passing {@code this} as the argument. 472 * Whether the field is supported is determined by the field. 473 * 474 * @param field the field to check, null returns false 475 * @return true if the field is supported on this date-time, false if not 476 */ 477 @Override 478 public boolean isSupported(TemporalField field) { 479 return field instanceof ChronoField || (field != null && field.isSupportedBy(this)); 480 } 481 482 /** 483 * Checks if the specified unit is supported. 484 * <p> 485 * This checks if the specified unit can be added to, or subtracted from, this date-time. 486 * If false, then calling the {@link #plus(long, TemporalUnit)} and 487 * {@link #minus(long, TemporalUnit) minus} methods will throw an exception. 488 * <p> 489 * If the unit is a {@link ChronoUnit} then the query is implemented here. 490 * The supported units are: 491 * <ul> 492 * <li>{@code NANOS} 493 * <li>{@code MICROS} 494 * <li>{@code MILLIS} 495 * <li>{@code SECONDS} 496 * <li>{@code MINUTES} 497 * <li>{@code HOURS} 498 * <li>{@code HALF_DAYS} 499 * <li>{@code DAYS} 500 * <li>{@code WEEKS} 501 * <li>{@code MONTHS} 502 * <li>{@code YEARS} 503 * <li>{@code DECADES} 504 * <li>{@code CENTURIES} 505 * <li>{@code MILLENNIA} 506 * <li>{@code ERAS} 507 * </ul> 508 * All other {@code ChronoUnit} instances will return false. 509 * <p> 510 * If the unit is not a {@code ChronoUnit}, then the result of this method 511 * is obtained by invoking {@code TemporalUnit.isSupportedBy(Temporal)} 512 * passing {@code this} as the argument. 513 * Whether the unit is supported is determined by the unit. 514 * 515 * @param unit the unit to check, null returns false 516 * @return true if the unit can be added/subtracted, false if not 517 */ 518 @Override // override for Javadoc 519 public boolean isSupported(TemporalUnit unit) { 520 if (unit instanceof ChronoUnit) { 521 return unit != FOREVER; 522 } 523 return unit != null && unit.isSupportedBy(this); 524 } 525 526 //----------------------------------------------------------------------- 527 /** 528 * Gets the range of valid values for the specified field. 529 * <p> 530 * The range object expresses the minimum and maximum valid values for a field. 531 * This date-time is used to enhance the accuracy of the returned range. 532 * If it is not possible to return the range, because the field is not supported 533 * or for some other reason, an exception is thrown. 534 * <p> 535 * If the field is a {@link ChronoField} then the query is implemented here. 536 * The {@link #isSupported(TemporalField) supported fields} will return 537 * appropriate range instances. 538 * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}. 539 * <p> 540 * If the field is not a {@code ChronoField}, then the result of this method 541 * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)} 542 * passing {@code this} as the argument. 543 * Whether the range can be obtained is determined by the field. 544 * 545 * @param field the field to query the range for, not null 546 * @return the range of valid values for the field, not null 547 * @throws DateTimeException if the range for the field cannot be obtained 548 * @throws UnsupportedTemporalTypeException if the field is not supported 549 */ 550 @Override 551 public ValueRange range(TemporalField field) { 552 if (field instanceof ChronoField) { 553 if (field == INSTANT_SECONDS || field == OFFSET_SECONDS) { 554 return field.range(); 555 } 556 return dateTime.range(field); 557 } 558 return field.rangeRefinedBy(this); 559 } 560 561 /** 562 * Gets the value of the specified field from this date-time as an {@code int}. 563 * <p> 564 * This queries this date-time for the value of the specified field. 565 * The returned value will always be within the valid range of values for the field. 566 * If it is not possible to return the value, because the field is not supported 567 * or for some other reason, an exception is thrown. 568 * <p> 569 * If the field is a {@link ChronoField} then the query is implemented here. 570 * The {@link #isSupported(TemporalField) supported fields} will return valid 571 * values based on this date-time, except {@code NANO_OF_DAY}, {@code MICRO_OF_DAY}, 572 * {@code EPOCH_DAY}, {@code PROLEPTIC_MONTH} and {@code INSTANT_SECONDS} which are too 573 * large to fit in an {@code int} and throw a {@code DateTimeException}. 574 * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}. 575 * <p> 576 * If the field is not a {@code ChronoField}, then the result of this method 577 * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)} 578 * passing {@code this} as the argument. Whether the value can be obtained, 579 * and what the value represents, is determined by the field. 580 * 581 * @param field the field to get, not null 582 * @return the value for the field 583 * @throws DateTimeException if a value for the field cannot be obtained or 584 * the value is outside the range of valid values for the field 585 * @throws UnsupportedTemporalTypeException if the field is not supported or 586 * the range of values exceeds an {@code int} 587 * @throws ArithmeticException if numeric overflow occurs 588 */ 589 @Override 590 public int get(TemporalField field) { 591 if (field instanceof ChronoField) { 592 switch ((ChronoField) field) { 593 case INSTANT_SECONDS: 594 throw new UnsupportedTemporalTypeException("Invalid field 'InstantSeconds' for get() method, use getLong() instead"); 595 case OFFSET_SECONDS: 596 return getOffset().getTotalSeconds(); 597 } 598 return dateTime.get(field); 599 } 600 return Temporal.super.get(field); 601 } 602 603 /** 604 * Gets the value of the specified field from this date-time as a {@code long}. 605 * <p> 606 * This queries this date-time for the value of the specified field. 607 * If it is not possible to return the value, because the field is not supported 608 * or for some other reason, an exception is thrown. 609 * <p> 610 * If the field is a {@link ChronoField} then the query is implemented here. 611 * The {@link #isSupported(TemporalField) supported fields} will return valid 612 * values based on this date-time. 613 * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}. 614 * <p> 615 * If the field is not a {@code ChronoField}, then the result of this method 616 * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)} 617 * passing {@code this} as the argument. Whether the value can be obtained, 618 * and what the value represents, is determined by the field. 619 * 620 * @param field the field to get, not null 621 * @return the value for the field 622 * @throws DateTimeException if a value for the field cannot be obtained 623 * @throws UnsupportedTemporalTypeException if the field is not supported 624 * @throws ArithmeticException if numeric overflow occurs 625 */ 626 @Override 627 public long getLong(TemporalField field) { 628 if (field instanceof ChronoField) { 629 switch ((ChronoField) field) { 630 case INSTANT_SECONDS: return toEpochSecond(); 631 case OFFSET_SECONDS: return getOffset().getTotalSeconds(); 632 } 633 return dateTime.getLong(field); 634 } 635 return field.getFrom(this); 636 } 637 638 //----------------------------------------------------------------------- 639 /** 640 * Gets the zone offset, such as '+01:00'. 641 * <p> 642 * This is the offset of the local date-time from UTC/Greenwich. 643 * 644 * @return the zone offset, not null 645 */ 646 public ZoneOffset getOffset() { 647 return offset; 648 } 649 650 /** 651 * Returns a copy of this {@code OffsetDateTime} with the specified offset ensuring 652 * that the result has the same local date-time. 653 * <p> 654 * This method returns an object with the same {@code LocalDateTime} and the specified {@code ZoneOffset}. 655 * No calculation is needed or performed. 656 * For example, if this time represents {@code 2007-12-03T10:30+02:00} and the offset specified is 657 * {@code +03:00}, then this method will return {@code 2007-12-03T10:30+03:00}. 658 * <p> 659 * To take into account the difference between the offsets, and adjust the time fields, 660 * use {@link #withOffsetSameInstant}. 661 * <p> 662 * This instance is immutable and unaffected by this method call. 663 * 664 * @param offset the zone offset to change to, not null 665 * @return an {@code OffsetDateTime} based on this date-time with the requested offset, not null 666 */ 667 public OffsetDateTime withOffsetSameLocal(ZoneOffset offset) { 668 return with(dateTime, offset); 669 } 670 671 /** 672 * Returns a copy of this {@code OffsetDateTime} with the specified offset ensuring 673 * that the result is at the same instant. 674 * <p> 675 * This method returns an object with the specified {@code ZoneOffset} and a {@code LocalDateTime} 676 * adjusted by the difference between the two offsets. 677 * This will result in the old and new objects representing the same instant. 678 * This is useful for finding the local time in a different offset. 679 * For example, if this time represents {@code 2007-12-03T10:30+02:00} and the offset specified is 680 * {@code +03:00}, then this method will return {@code 2007-12-03T11:30+03:00}. 681 * <p> 682 * To change the offset without adjusting the local time use {@link #withOffsetSameLocal}. 683 * <p> 684 * This instance is immutable and unaffected by this method call. 685 * 686 * @param offset the zone offset to change to, not null 687 * @return an {@code OffsetDateTime} based on this date-time with the requested offset, not null 688 * @throws DateTimeException if the result exceeds the supported date range 689 */ 690 public OffsetDateTime withOffsetSameInstant(ZoneOffset offset) { 691 if (offset.equals(this.offset)) { 692 return this; 693 } 694 int difference = offset.getTotalSeconds() - this.offset.getTotalSeconds(); 695 LocalDateTime adjusted = dateTime.plusSeconds(difference); 696 return new OffsetDateTime(adjusted, offset); 697 } 698 699 //----------------------------------------------------------------------- 700 /** 701 * Gets the {@code LocalDateTime} part of this date-time. 702 * <p> 703 * This returns a {@code LocalDateTime} with the same year, month, day and time 704 * as this date-time. 705 * 706 * @return the local date-time part of this date-time, not null 707 */ 708 public LocalDateTime toLocalDateTime() { 709 return dateTime; 710 } 711 712 //----------------------------------------------------------------------- 713 /** 714 * Gets the {@code LocalDate} part of this date-time. 715 * <p> 716 * This returns a {@code LocalDate} with the same year, month and day 717 * as this date-time. 718 * 719 * @return the date part of this date-time, not null 720 */ 721 public LocalDate toLocalDate() { 722 return dateTime.toLocalDate(); 723 } 724 725 /** 726 * Gets the year field. 727 * <p> 728 * This method returns the primitive {@code int} value for the year. 729 * <p> 730 * The year returned by this method is proleptic as per {@code get(YEAR)}. 731 * To obtain the year-of-era, use {@code get(YEAR_OF_ERA)}. 732 * 733 * @return the year, from MIN_YEAR to MAX_YEAR 734 */ 735 public int getYear() { 736 return dateTime.getYear(); 737 } 738 739 /** 740 * Gets the month-of-year field from 1 to 12. 741 * <p> 742 * This method returns the month as an {@code int} from 1 to 12. 743 * Application code is frequently clearer if the enum {@link Month} 744 * is used by calling {@link #getMonth()}. 745 * 746 * @return the month-of-year, from 1 to 12 747 * @see #getMonth() 748 */ 749 public int getMonthValue() { 750 return dateTime.getMonthValue(); 751 } 752 753 /** 754 * Gets the month-of-year field using the {@code Month} enum. 755 * <p> 756 * This method returns the enum {@link Month} for the month. 757 * This avoids confusion as to what {@code int} values mean. 758 * If you need access to the primitive {@code int} value then the enum 759 * provides the {@link Month#getValue() int value}. 760 * 761 * @return the month-of-year, not null 762 * @see #getMonthValue() 763 */ 764 public Month getMonth() { 765 return dateTime.getMonth(); 766 } 767 768 /** 769 * Gets the day-of-month field. 770 * <p> 771 * This method returns the primitive {@code int} value for the day-of-month. 772 * 773 * @return the day-of-month, from 1 to 31 774 */ 775 public int getDayOfMonth() { 776 return dateTime.getDayOfMonth(); 777 } 778 779 /** 780 * Gets the day-of-year field. 781 * <p> 782 * This method returns the primitive {@code int} value for the day-of-year. 783 * 784 * @return the day-of-year, from 1 to 365, or 366 in a leap year 785 */ 786 public int getDayOfYear() { 787 return dateTime.getDayOfYear(); 788 } 789 790 /** 791 * Gets the day-of-week field, which is an enum {@code DayOfWeek}. 792 * <p> 793 * This method returns the enum {@link DayOfWeek} for the day-of-week. 794 * This avoids confusion as to what {@code int} values mean. 795 * If you need access to the primitive {@code int} value then the enum 796 * provides the {@link DayOfWeek#getValue() int value}. 797 * <p> 798 * Additional information can be obtained from the {@code DayOfWeek}. 799 * This includes textual names of the values. 800 * 801 * @return the day-of-week, not null 802 */ 803 public DayOfWeek getDayOfWeek() { 804 return dateTime.getDayOfWeek(); 805 } 806 807 //----------------------------------------------------------------------- 808 /** 809 * Gets the {@code LocalTime} part of this date-time. 810 * <p> 811 * This returns a {@code LocalTime} with the same hour, minute, second and 812 * nanosecond as this date-time. 813 * 814 * @return the time part of this date-time, not null 815 */ 816 public LocalTime toLocalTime() { 817 return dateTime.toLocalTime(); 818 } 819 820 /** 821 * Gets the hour-of-day field. 822 * 823 * @return the hour-of-day, from 0 to 23 824 */ 825 public int getHour() { 826 return dateTime.getHour(); 827 } 828 829 /** 830 * Gets the minute-of-hour field. 831 * 832 * @return the minute-of-hour, from 0 to 59 833 */ 834 public int getMinute() { 835 return dateTime.getMinute(); 836 } 837 838 /** 839 * Gets the second-of-minute field. 840 * 841 * @return the second-of-minute, from 0 to 59 842 */ 843 public int getSecond() { 844 return dateTime.getSecond(); 845 } 846 847 /** 848 * Gets the nano-of-second field. 849 * 850 * @return the nano-of-second, from 0 to 999,999,999 851 */ 852 public int getNano() { 853 return dateTime.getNano(); 854 } 855 856 //----------------------------------------------------------------------- 857 /** 858 * Returns an adjusted copy of this date-time. 859 * <p> 860 * This returns an {@code OffsetDateTime}, based on this one, with the date-time adjusted. 861 * The adjustment takes place using the specified adjuster strategy object. 862 * Read the documentation of the adjuster to understand what adjustment will be made. 863 * <p> 864 * A simple adjuster might simply set the one of the fields, such as the year field. 865 * A more complex adjuster might set the date to the last day of the month. 866 * A selection of common adjustments is provided in 867 * {@link java.time.temporal.TemporalAdjusters TemporalAdjusters}. 868 * These include finding the "last day of the month" and "next Wednesday". 869 * Key date-time classes also implement the {@code TemporalAdjuster} interface, 870 * such as {@link Month} and {@link java.time.MonthDay MonthDay}. 871 * The adjuster is responsible for handling special cases, such as the varying 872 * lengths of month and leap years. 873 * <p> 874 * For example this code returns a date on the last day of July: 875 * <pre> 876 * import static java.time.Month.*; 877 * import static java.time.temporal.TemporalAdjusters.*; 878 * 879 * result = offsetDateTime.with(JULY).with(lastDayOfMonth()); 880 * </pre> 881 * <p> 882 * The classes {@link LocalDate}, {@link LocalTime} and {@link ZoneOffset} implement 883 * {@code TemporalAdjuster}, thus this method can be used to change the date, time or offset: 884 * <pre> 885 * result = offsetDateTime.with(date); 886 * result = offsetDateTime.with(time); 887 * result = offsetDateTime.with(offset); 888 * </pre> 889 * <p> 890 * The result of this method is obtained by invoking the 891 * {@link TemporalAdjuster#adjustInto(Temporal)} method on the 892 * specified adjuster passing {@code this} as the argument. 893 * <p> 894 * This instance is immutable and unaffected by this method call. 895 * 896 * @param adjuster the adjuster to use, not null 897 * @return an {@code OffsetDateTime} based on {@code this} with the adjustment made, not null 898 * @throws DateTimeException if the adjustment cannot be made 899 * @throws ArithmeticException if numeric overflow occurs 900 */ 901 @Override 902 public OffsetDateTime with(TemporalAdjuster adjuster) { 903 // optimizations 904 if (adjuster instanceof LocalDate || adjuster instanceof LocalTime || adjuster instanceof LocalDateTime) { 905 return with(dateTime.with(adjuster), offset); 906 } else if (adjuster instanceof Instant) { 907 return ofInstant((Instant) adjuster, offset); 908 } else if (adjuster instanceof ZoneOffset) { 909 return with(dateTime, (ZoneOffset) adjuster); 910 } else if (adjuster instanceof OffsetDateTime) { 911 return (OffsetDateTime) adjuster; 912 } 913 return (OffsetDateTime) adjuster.adjustInto(this); 914 } 915 916 /** 917 * Returns a copy of this date-time with the specified field set to a new value. 918 * <p> 919 * This returns an {@code OffsetDateTime}, based on this one, with the value 920 * for the specified field changed. 921 * This can be used to change any supported field, such as the year, month or day-of-month. 922 * If it is not possible to set the value, because the field is not supported or for 923 * some other reason, an exception is thrown. 924 * <p> 925 * In some cases, changing the specified field can cause the resulting date-time to become invalid, 926 * such as changing the month from 31st January to February would make the day-of-month invalid. 927 * In cases like this, the field is responsible for resolving the date. Typically it will choose 928 * the previous valid date, which would be the last valid day of February in this example. 929 * <p> 930 * If the field is a {@link ChronoField} then the adjustment is implemented here. 931 * <p> 932 * The {@code INSTANT_SECONDS} field will return a date-time with the specified instant. 933 * The offset and nano-of-second are unchanged. 934 * If the new instant value is outside the valid range then a {@code DateTimeException} will be thrown. 935 * <p> 936 * The {@code OFFSET_SECONDS} field will return a date-time with the specified offset. 937 * The local date-time is unaltered. If the new offset value is outside the valid range 938 * then a {@code DateTimeException} will be thrown. 939 * <p> 940 * The other {@link #isSupported(TemporalField) supported fields} will behave as per 941 * the matching method on {@link LocalDateTime#with(TemporalField, long) LocalDateTime}. 942 * In this case, the offset is not part of the calculation and will be unchanged. 943 * <p> 944 * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}. 945 * <p> 946 * If the field is not a {@code ChronoField}, then the result of this method 947 * is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)} 948 * passing {@code this} as the argument. In this case, the field determines 949 * whether and how to adjust the instant. 950 * <p> 951 * This instance is immutable and unaffected by this method call. 952 * 953 * @param field the field to set in the result, not null 954 * @param newValue the new value of the field in the result 955 * @return an {@code OffsetDateTime} based on {@code this} with the specified field set, not null 956 * @throws DateTimeException if the field cannot be set 957 * @throws UnsupportedTemporalTypeException if the field is not supported 958 * @throws ArithmeticException if numeric overflow occurs 959 */ 960 @Override 961 public OffsetDateTime with(TemporalField field, long newValue) { 962 if (field instanceof ChronoField) { 963 ChronoField f = (ChronoField) field; 964 switch (f) { 965 case INSTANT_SECONDS: return ofInstant(Instant.ofEpochSecond(newValue, getNano()), offset); 966 case OFFSET_SECONDS: { 967 return with(dateTime, ZoneOffset.ofTotalSeconds(f.checkValidIntValue(newValue))); 968 } 969 } 970 return with(dateTime.with(field, newValue), offset); 971 } 972 return field.adjustInto(this, newValue); 973 } 974 975 //----------------------------------------------------------------------- 976 /** 977 * Returns a copy of this {@code OffsetDateTime} with the year altered. 978 * <p> 979 * The time and offset do not affect the calculation and will be the same in the result. 980 * If the day-of-month is invalid for the year, it will be changed to the last valid day of the month. 981 * <p> 982 * This instance is immutable and unaffected by this method call. 983 * 984 * @param year the year to set in the result, from MIN_YEAR to MAX_YEAR 985 * @return an {@code OffsetDateTime} based on this date-time with the requested year, not null 986 * @throws DateTimeException if the year value is invalid 987 */ 988 public OffsetDateTime withYear(int year) { 989 return with(dateTime.withYear(year), offset); 990 } 991 992 /** 993 * Returns a copy of this {@code OffsetDateTime} with the month-of-year altered. 994 * <p> 995 * The time and offset do not affect the calculation and will be the same in the result. 996 * If the day-of-month is invalid for the year, it will be changed to the last valid day of the month. 997 * <p> 998 * This instance is immutable and unaffected by this method call. 999 * 1000 * @param month the month-of-year to set in the result, from 1 (January) to 12 (December) 1001 * @return an {@code OffsetDateTime} based on this date-time with the requested month, not null 1002 * @throws DateTimeException if the month-of-year value is invalid 1003 */ 1004 public OffsetDateTime withMonth(int month) { 1005 return with(dateTime.withMonth(month), offset); 1006 } 1007 1008 /** 1009 * Returns a copy of this {@code OffsetDateTime} with the day-of-month altered. 1010 * <p> 1011 * If the resulting {@code OffsetDateTime} is invalid, an exception is thrown. 1012 * The time and offset do not affect the calculation and will be the same in the result. 1013 * <p> 1014 * This instance is immutable and unaffected by this method call. 1015 * 1016 * @param dayOfMonth the day-of-month to set in the result, from 1 to 28-31 1017 * @return an {@code OffsetDateTime} based on this date-time with the requested day, not null 1018 * @throws DateTimeException if the day-of-month value is invalid, 1019 * or if the day-of-month is invalid for the month-year 1020 */ 1021 public OffsetDateTime withDayOfMonth(int dayOfMonth) { 1022 return with(dateTime.withDayOfMonth(dayOfMonth), offset); 1023 } 1024 1025 /** 1026 * Returns a copy of this {@code OffsetDateTime} with the day-of-year altered. 1027 * <p> 1028 * The time and offset do not affect the calculation and will be the same in the result. 1029 * If the resulting {@code OffsetDateTime} is invalid, an exception is thrown. 1030 * <p> 1031 * This instance is immutable and unaffected by this method call. 1032 * 1033 * @param dayOfYear the day-of-year to set in the result, from 1 to 365-366 1034 * @return an {@code OffsetDateTime} based on this date with the requested day, not null 1035 * @throws DateTimeException if the day-of-year value is invalid, 1036 * or if the day-of-year is invalid for the year 1037 */ 1038 public OffsetDateTime withDayOfYear(int dayOfYear) { 1039 return with(dateTime.withDayOfYear(dayOfYear), offset); 1040 } 1041 1042 //----------------------------------------------------------------------- 1043 /** 1044 * Returns a copy of this {@code OffsetDateTime} with the hour-of-day altered. 1045 * <p> 1046 * The date and offset do not affect the calculation and will be the same in the result. 1047 * <p> 1048 * This instance is immutable and unaffected by this method call. 1049 * 1050 * @param hour the hour-of-day to set in the result, from 0 to 23 1051 * @return an {@code OffsetDateTime} based on this date-time with the requested hour, not null 1052 * @throws DateTimeException if the hour value is invalid 1053 */ 1054 public OffsetDateTime withHour(int hour) { 1055 return with(dateTime.withHour(hour), offset); 1056 } 1057 1058 /** 1059 * Returns a copy of this {@code OffsetDateTime} with the minute-of-hour altered. 1060 * <p> 1061 * The date and offset do not affect the calculation and will be the same in the result. 1062 * <p> 1063 * This instance is immutable and unaffected by this method call. 1064 * 1065 * @param minute the minute-of-hour to set in the result, from 0 to 59 1066 * @return an {@code OffsetDateTime} based on this date-time with the requested minute, not null 1067 * @throws DateTimeException if the minute value is invalid 1068 */ 1069 public OffsetDateTime withMinute(int minute) { 1070 return with(dateTime.withMinute(minute), offset); 1071 } 1072 1073 /** 1074 * Returns a copy of this {@code OffsetDateTime} with the second-of-minute altered. 1075 * <p> 1076 * The date and offset do not affect the calculation and will be the same in the result. 1077 * <p> 1078 * This instance is immutable and unaffected by this method call. 1079 * 1080 * @param second the second-of-minute to set in the result, from 0 to 59 1081 * @return an {@code OffsetDateTime} based on this date-time with the requested second, not null 1082 * @throws DateTimeException if the second value is invalid 1083 */ 1084 public OffsetDateTime withSecond(int second) { 1085 return with(dateTime.withSecond(second), offset); 1086 } 1087 1088 /** 1089 * Returns a copy of this {@code OffsetDateTime} with the nano-of-second altered. 1090 * <p> 1091 * The date and offset do not affect the calculation and will be the same in the result. 1092 * <p> 1093 * This instance is immutable and unaffected by this method call. 1094 * 1095 * @param nanoOfSecond the nano-of-second to set in the result, from 0 to 999,999,999 1096 * @return an {@code OffsetDateTime} based on this date-time with the requested nanosecond, not null 1097 * @throws DateTimeException if the nano value is invalid 1098 */ 1099 public OffsetDateTime withNano(int nanoOfSecond) { 1100 return with(dateTime.withNano(nanoOfSecond), offset); 1101 } 1102 1103 //----------------------------------------------------------------------- 1104 /** 1105 * Returns a copy of this {@code OffsetDateTime} with the time truncated. 1106 * <p> 1107 * Truncation returns a copy of the original date-time with fields 1108 * smaller than the specified unit set to zero. 1109 * For example, truncating with the {@link ChronoUnit#MINUTES minutes} unit 1110 * will set the second-of-minute and nano-of-second field to zero. 1111 * <p> 1112 * The unit must have a {@linkplain TemporalUnit#getDuration() duration} 1113 * that divides into the length of a standard day without remainder. 1114 * This includes all supplied time units on {@link ChronoUnit} and 1115 * {@link ChronoUnit#DAYS DAYS}. Other units throw an exception. 1116 * <p> 1117 * The offset does not affect the calculation and will be the same in the result. 1118 * <p> 1119 * This instance is immutable and unaffected by this method call. 1120 * 1121 * @param unit the unit to truncate to, not null 1122 * @return an {@code OffsetDateTime} based on this date-time with the time truncated, not null 1123 * @throws DateTimeException if unable to truncate 1124 * @throws UnsupportedTemporalTypeException if the unit is not supported 1125 */ 1126 public OffsetDateTime truncatedTo(TemporalUnit unit) { 1127 return with(dateTime.truncatedTo(unit), offset); 1128 } 1129 1130 //----------------------------------------------------------------------- 1131 /** 1132 * Returns a copy of this date-time with the specified amount added. 1133 * <p> 1134 * This returns an {@code OffsetDateTime}, based on this one, with the specified amount added. 1135 * The amount is typically {@link Period} or {@link Duration} but may be 1136 * any other type implementing the {@link TemporalAmount} interface. 1137 * <p> 1138 * The calculation is delegated to the amount object by calling 1139 * {@link TemporalAmount#addTo(Temporal)}. The amount implementation is free 1140 * to implement the addition in any way it wishes, however it typically 1141 * calls back to {@link #plus(long, TemporalUnit)}. Consult the documentation 1142 * of the amount implementation to determine if it can be successfully added. 1143 * <p> 1144 * This instance is immutable and unaffected by this method call. 1145 * 1146 * @param amountToAdd the amount to add, not null 1147 * @return an {@code OffsetDateTime} based on this date-time with the addition made, not null 1148 * @throws DateTimeException if the addition cannot be made 1149 * @throws ArithmeticException if numeric overflow occurs 1150 */ 1151 @Override 1152 public OffsetDateTime plus(TemporalAmount amountToAdd) { 1153 return (OffsetDateTime) amountToAdd.addTo(this); 1154 } 1155 1156 /** 1157 * Returns a copy of this date-time with the specified amount added. 1158 * <p> 1159 * This returns an {@code OffsetDateTime}, based on this one, with the amount 1160 * in terms of the unit added. If it is not possible to add the amount, because the 1161 * unit is not supported or for some other reason, an exception is thrown. 1162 * <p> 1163 * If the field is a {@link ChronoUnit} then the addition is implemented by 1164 * {@link LocalDateTime#plus(long, TemporalUnit)}. 1165 * The offset is not part of the calculation and will be unchanged in the result. 1166 * <p> 1167 * If the field is not a {@code ChronoUnit}, then the result of this method 1168 * is obtained by invoking {@code TemporalUnit.addTo(Temporal, long)} 1169 * passing {@code this} as the argument. In this case, the unit determines 1170 * whether and how to perform the addition. 1171 * <p> 1172 * This instance is immutable and unaffected by this method call. 1173 * 1174 * @param amountToAdd the amount of the unit to add to the result, may be negative 1175 * @param unit the unit of the amount to add, not null 1176 * @return an {@code OffsetDateTime} based on this date-time with the specified amount added, not null 1177 * @throws DateTimeException if the addition cannot be made 1178 * @throws UnsupportedTemporalTypeException if the unit is not supported 1179 * @throws ArithmeticException if numeric overflow occurs 1180 */ 1181 @Override 1182 public OffsetDateTime plus(long amountToAdd, TemporalUnit unit) { 1183 if (unit instanceof ChronoUnit) { 1184 return with(dateTime.plus(amountToAdd, unit), offset); 1185 } 1186 return unit.addTo(this, amountToAdd); 1187 } 1188 1189 //----------------------------------------------------------------------- 1190 /** 1191 * Returns a copy of this {@code OffsetDateTime} with the specified number of years added. 1192 * <p> 1193 * This method adds the specified amount to the years field in three steps: 1194 * <ol> 1195 * <li>Add the input years to the year field</li> 1196 * <li>Check if the resulting date would be invalid</li> 1197 * <li>Adjust the day-of-month to the last valid day if necessary</li> 1198 * </ol> 1199 * <p> 1200 * For example, 2008-02-29 (leap year) plus one year would result in the 1201 * invalid date 2009-02-29 (standard year). Instead of returning an invalid 1202 * result, the last valid day of the month, 2009-02-28, is selected instead. 1203 * <p> 1204 * This instance is immutable and unaffected by this method call. 1205 * 1206 * @param years the years to add, may be negative 1207 * @return an {@code OffsetDateTime} based on this date-time with the years added, not null 1208 * @throws DateTimeException if the result exceeds the supported date range 1209 */ 1210 public OffsetDateTime plusYears(long years) { 1211 return with(dateTime.plusYears(years), offset); 1212 } 1213 1214 /** 1215 * Returns a copy of this {@code OffsetDateTime} with the specified number of months added. 1216 * <p> 1217 * This method adds the specified amount to the months field in three steps: 1218 * <ol> 1219 * <li>Add the input months to the month-of-year field</li> 1220 * <li>Check if the resulting date would be invalid</li> 1221 * <li>Adjust the day-of-month to the last valid day if necessary</li> 1222 * </ol> 1223 * <p> 1224 * For example, 2007-03-31 plus one month would result in the invalid date 1225 * 2007-04-31. Instead of returning an invalid result, the last valid day 1226 * of the month, 2007-04-30, is selected instead. 1227 * <p> 1228 * This instance is immutable and unaffected by this method call. 1229 * 1230 * @param months the months to add, may be negative 1231 * @return an {@code OffsetDateTime} based on this date-time with the months added, not null 1232 * @throws DateTimeException if the result exceeds the supported date range 1233 */ 1234 public OffsetDateTime plusMonths(long months) { 1235 return with(dateTime.plusMonths(months), offset); 1236 } 1237 1238 /** 1239 * Returns a copy of this OffsetDateTime with the specified number of weeks added. 1240 * <p> 1241 * This method adds the specified amount in weeks to the days field incrementing 1242 * the month and year fields as necessary to ensure the result remains valid. 1243 * The result is only invalid if the maximum/minimum year is exceeded. 1244 * <p> 1245 * For example, 2008-12-31 plus one week would result in 2009-01-07. 1246 * <p> 1247 * This instance is immutable and unaffected by this method call. 1248 * 1249 * @param weeks the weeks to add, may be negative 1250 * @return an {@code OffsetDateTime} based on this date-time with the weeks added, not null 1251 * @throws DateTimeException if the result exceeds the supported date range 1252 */ 1253 public OffsetDateTime plusWeeks(long weeks) { 1254 return with(dateTime.plusWeeks(weeks), offset); 1255 } 1256 1257 /** 1258 * Returns a copy of this OffsetDateTime with the specified number of days added. 1259 * <p> 1260 * This method adds the specified amount to the days field incrementing the 1261 * month and year fields as necessary to ensure the result remains valid. 1262 * The result is only invalid if the maximum/minimum year is exceeded. 1263 * <p> 1264 * For example, 2008-12-31 plus one day would result in 2009-01-01. 1265 * <p> 1266 * This instance is immutable and unaffected by this method call. 1267 * 1268 * @param days the days to add, may be negative 1269 * @return an {@code OffsetDateTime} based on this date-time with the days added, not null 1270 * @throws DateTimeException if the result exceeds the supported date range 1271 */ 1272 public OffsetDateTime plusDays(long days) { 1273 return with(dateTime.plusDays(days), offset); 1274 } 1275 1276 /** 1277 * Returns a copy of this {@code OffsetDateTime} with the specified number of hours added. 1278 * <p> 1279 * This instance is immutable and unaffected by this method call. 1280 * 1281 * @param hours the hours to add, may be negative 1282 * @return an {@code OffsetDateTime} based on this date-time with the hours added, not null 1283 * @throws DateTimeException if the result exceeds the supported date range 1284 */ 1285 public OffsetDateTime plusHours(long hours) { 1286 return with(dateTime.plusHours(hours), offset); 1287 } 1288 1289 /** 1290 * Returns a copy of this {@code OffsetDateTime} with the specified number of minutes added. 1291 * <p> 1292 * This instance is immutable and unaffected by this method call. 1293 * 1294 * @param minutes the minutes to add, may be negative 1295 * @return an {@code OffsetDateTime} based on this date-time with the minutes added, not null 1296 * @throws DateTimeException if the result exceeds the supported date range 1297 */ 1298 public OffsetDateTime plusMinutes(long minutes) { 1299 return with(dateTime.plusMinutes(minutes), offset); 1300 } 1301 1302 /** 1303 * Returns a copy of this {@code OffsetDateTime} with the specified number of seconds added. 1304 * <p> 1305 * This instance is immutable and unaffected by this method call. 1306 * 1307 * @param seconds the seconds to add, may be negative 1308 * @return an {@code OffsetDateTime} based on this date-time with the seconds added, not null 1309 * @throws DateTimeException if the result exceeds the supported date range 1310 */ 1311 public OffsetDateTime plusSeconds(long seconds) { 1312 return with(dateTime.plusSeconds(seconds), offset); 1313 } 1314 1315 /** 1316 * Returns a copy of this {@code OffsetDateTime} with the specified number of nanoseconds added. 1317 * <p> 1318 * This instance is immutable and unaffected by this method call. 1319 * 1320 * @param nanos the nanos to add, may be negative 1321 * @return an {@code OffsetDateTime} based on this date-time with the nanoseconds added, not null 1322 * @throws DateTimeException if the unit cannot be added to this type 1323 */ 1324 public OffsetDateTime plusNanos(long nanos) { 1325 return with(dateTime.plusNanos(nanos), offset); 1326 } 1327 1328 //----------------------------------------------------------------------- 1329 /** 1330 * Returns a copy of this date-time with the specified amount subtracted. 1331 * <p> 1332 * This returns an {@code OffsetDateTime}, based on this one, with the specified amount subtracted. 1333 * The amount is typically {@link Period} or {@link Duration} but may be 1334 * any other type implementing the {@link TemporalAmount} interface. 1335 * <p> 1336 * The calculation is delegated to the amount object by calling 1337 * {@link TemporalAmount#subtractFrom(Temporal)}. The amount implementation is free 1338 * to implement the subtraction in any way it wishes, however it typically 1339 * calls back to {@link #minus(long, TemporalUnit)}. Consult the documentation 1340 * of the amount implementation to determine if it can be successfully subtracted. 1341 * <p> 1342 * This instance is immutable and unaffected by this method call. 1343 * 1344 * @param amountToSubtract the amount to subtract, not null 1345 * @return an {@code OffsetDateTime} based on this date-time with the subtraction made, not null 1346 * @throws DateTimeException if the subtraction cannot be made 1347 * @throws ArithmeticException if numeric overflow occurs 1348 */ 1349 @Override 1350 public OffsetDateTime minus(TemporalAmount amountToSubtract) { 1351 return (OffsetDateTime) amountToSubtract.subtractFrom(this); 1352 } 1353 1354 /** 1355 * Returns a copy of this date-time with the specified amount subtracted. 1356 * <p> 1357 * This returns an {@code OffsetDateTime}, based on this one, with the amount 1358 * in terms of the unit subtracted. If it is not possible to subtract the amount, 1359 * because the unit is not supported or for some other reason, an exception is thrown. 1360 * <p> 1361 * This method is equivalent to {@link #plus(long, TemporalUnit)} with the amount negated. 1362 * See that method for a full description of how addition, and thus subtraction, works. 1363 * <p> 1364 * This instance is immutable and unaffected by this method call. 1365 * 1366 * @param amountToSubtract the amount of the unit to subtract from the result, may be negative 1367 * @param unit the unit of the amount to subtract, not null 1368 * @return an {@code OffsetDateTime} based on this date-time with the specified amount subtracted, not null 1369 * @throws DateTimeException if the subtraction cannot be made 1370 * @throws UnsupportedTemporalTypeException if the unit is not supported 1371 * @throws ArithmeticException if numeric overflow occurs 1372 */ 1373 @Override 1374 public OffsetDateTime minus(long amountToSubtract, TemporalUnit unit) { 1375 return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit)); 1376 } 1377 1378 //----------------------------------------------------------------------- 1379 /** 1380 * Returns a copy of this {@code OffsetDateTime} with the specified number of years subtracted. 1381 * <p> 1382 * This method subtracts the specified amount from the years field in three steps: 1383 * <ol> 1384 * <li>Subtract the input years from the year field</li> 1385 * <li>Check if the resulting date would be invalid</li> 1386 * <li>Adjust the day-of-month to the last valid day if necessary</li> 1387 * </ol> 1388 * <p> 1389 * For example, 2008-02-29 (leap year) minus one year would result in the 1390 * invalid date 2009-02-29 (standard year). Instead of returning an invalid 1391 * result, the last valid day of the month, 2009-02-28, is selected instead. 1392 * <p> 1393 * This instance is immutable and unaffected by this method call. 1394 * 1395 * @param years the years to subtract, may be negative 1396 * @return an {@code OffsetDateTime} based on this date-time with the years subtracted, not null 1397 * @throws DateTimeException if the result exceeds the supported date range 1398 */ 1399 public OffsetDateTime minusYears(long years) { 1400 return (years == Long.MIN_VALUE ? plusYears(Long.MAX_VALUE).plusYears(1) : plusYears(-years)); 1401 } 1402 1403 /** 1404 * Returns a copy of this {@code OffsetDateTime} with the specified number of months subtracted. 1405 * <p> 1406 * This method subtracts the specified amount from the months field in three steps: 1407 * <ol> 1408 * <li>Subtract the input months from the month-of-year field</li> 1409 * <li>Check if the resulting date would be invalid</li> 1410 * <li>Adjust the day-of-month to the last valid day if necessary</li> 1411 * </ol> 1412 * <p> 1413 * For example, 2007-03-31 minus one month would result in the invalid date 1414 * 2007-04-31. Instead of returning an invalid result, the last valid day 1415 * of the month, 2007-04-30, is selected instead. 1416 * <p> 1417 * This instance is immutable and unaffected by this method call. 1418 * 1419 * @param months the months to subtract, may be negative 1420 * @return an {@code OffsetDateTime} based on this date-time with the months subtracted, not null 1421 * @throws DateTimeException if the result exceeds the supported date range 1422 */ 1423 public OffsetDateTime minusMonths(long months) { 1424 return (months == Long.MIN_VALUE ? plusMonths(Long.MAX_VALUE).plusMonths(1) : plusMonths(-months)); 1425 } 1426 1427 /** 1428 * Returns a copy of this {@code OffsetDateTime} with the specified number of weeks subtracted. 1429 * <p> 1430 * This method subtracts the specified amount in weeks from the days field decrementing 1431 * the month and year fields as necessary to ensure the result remains valid. 1432 * The result is only invalid if the maximum/minimum year is exceeded. 1433 * <p> 1434 * For example, 2008-12-31 minus one week would result in 2009-01-07. 1435 * <p> 1436 * This instance is immutable and unaffected by this method call. 1437 * 1438 * @param weeks the weeks to subtract, may be negative 1439 * @return an {@code OffsetDateTime} based on this date-time with the weeks subtracted, not null 1440 * @throws DateTimeException if the result exceeds the supported date range 1441 */ 1442 public OffsetDateTime minusWeeks(long weeks) { 1443 return (weeks == Long.MIN_VALUE ? plusWeeks(Long.MAX_VALUE).plusWeeks(1) : plusWeeks(-weeks)); 1444 } 1445 1446 /** 1447 * Returns a copy of this {@code OffsetDateTime} with the specified number of days subtracted. 1448 * <p> 1449 * This method subtracts the specified amount from the days field decrementing the 1450 * month and year fields as necessary to ensure the result remains valid. 1451 * The result is only invalid if the maximum/minimum year is exceeded. 1452 * <p> 1453 * For example, 2008-12-31 minus one day would result in 2009-01-01. 1454 * <p> 1455 * This instance is immutable and unaffected by this method call. 1456 * 1457 * @param days the days to subtract, may be negative 1458 * @return an {@code OffsetDateTime} based on this date-time with the days subtracted, not null 1459 * @throws DateTimeException if the result exceeds the supported date range 1460 */ 1461 public OffsetDateTime minusDays(long days) { 1462 return (days == Long.MIN_VALUE ? plusDays(Long.MAX_VALUE).plusDays(1) : plusDays(-days)); 1463 } 1464 1465 /** 1466 * Returns a copy of this {@code OffsetDateTime} with the specified number of hours subtracted. 1467 * <p> 1468 * This instance is immutable and unaffected by this method call. 1469 * 1470 * @param hours the hours to subtract, may be negative 1471 * @return an {@code OffsetDateTime} based on this date-time with the hours subtracted, not null 1472 * @throws DateTimeException if the result exceeds the supported date range 1473 */ 1474 public OffsetDateTime minusHours(long hours) { 1475 return (hours == Long.MIN_VALUE ? plusHours(Long.MAX_VALUE).plusHours(1) : plusHours(-hours)); 1476 } 1477 1478 /** 1479 * Returns a copy of this {@code OffsetDateTime} with the specified number of minutes subtracted. 1480 * <p> 1481 * This instance is immutable and unaffected by this method call. 1482 * 1483 * @param minutes the minutes to subtract, may be negative 1484 * @return an {@code OffsetDateTime} based on this date-time with the minutes subtracted, not null 1485 * @throws DateTimeException if the result exceeds the supported date range 1486 */ 1487 public OffsetDateTime minusMinutes(long minutes) { 1488 return (minutes == Long.MIN_VALUE ? plusMinutes(Long.MAX_VALUE).plusMinutes(1) : plusMinutes(-minutes)); 1489 } 1490 1491 /** 1492 * Returns a copy of this {@code OffsetDateTime} with the specified number of seconds subtracted. 1493 * <p> 1494 * This instance is immutable and unaffected by this method call. 1495 * 1496 * @param seconds the seconds to subtract, may be negative 1497 * @return an {@code OffsetDateTime} based on this date-time with the seconds subtracted, not null 1498 * @throws DateTimeException if the result exceeds the supported date range 1499 */ 1500 public OffsetDateTime minusSeconds(long seconds) { 1501 return (seconds == Long.MIN_VALUE ? plusSeconds(Long.MAX_VALUE).plusSeconds(1) : plusSeconds(-seconds)); 1502 } 1503 1504 /** 1505 * Returns a copy of this {@code OffsetDateTime} with the specified number of nanoseconds subtracted. 1506 * <p> 1507 * This instance is immutable and unaffected by this method call. 1508 * 1509 * @param nanos the nanos to subtract, may be negative 1510 * @return an {@code OffsetDateTime} based on this date-time with the nanoseconds subtracted, not null 1511 * @throws DateTimeException if the result exceeds the supported date range 1512 */ 1513 public OffsetDateTime minusNanos(long nanos) { 1514 return (nanos == Long.MIN_VALUE ? plusNanos(Long.MAX_VALUE).plusNanos(1) : plusNanos(-nanos)); 1515 } 1516 1517 //----------------------------------------------------------------------- 1518 /** 1519 * Queries this date-time using the specified query. 1520 * <p> 1521 * This queries this date-time using the specified query strategy object. 1522 * The {@code TemporalQuery} object defines the logic to be used to 1523 * obtain the result. Read the documentation of the query to understand 1524 * what the result of this method will be. 1525 * <p> 1526 * The result of this method is obtained by invoking the 1527 * {@link TemporalQuery#queryFrom(TemporalAccessor)} method on the 1528 * specified query passing {@code this} as the argument. 1529 * 1530 * @param <R> the type of the result 1531 * @param query the query to invoke, not null 1532 * @return the query result, null may be returned (defined by the query) 1533 * @throws DateTimeException if unable to query (defined by the query) 1534 * @throws ArithmeticException if numeric overflow occurs (defined by the query) 1535 */ 1536 @SuppressWarnings("unchecked") 1537 @Override 1538 public <R> R query(TemporalQuery<R> query) { 1539 if (query == TemporalQueries.offset() || query == TemporalQueries.zone()) { 1540 return (R) getOffset(); 1541 } else if (query == TemporalQueries.zoneId()) { 1542 return null; 1543 } else if (query == TemporalQueries.localDate()) { 1544 return (R) toLocalDate(); 1545 } else if (query == TemporalQueries.localTime()) { 1546 return (R) toLocalTime(); 1547 } else if (query == TemporalQueries.chronology()) { 1548 return (R) IsoChronology.INSTANCE; 1549 } else if (query == TemporalQueries.precision()) { 1550 return (R) NANOS; 1551 } 1552 // inline TemporalAccessor.super.query(query) as an optimization 1553 // non-JDK classes are not permitted to make this optimization 1554 return query.queryFrom(this); 1555 } 1556 1557 /** 1558 * Adjusts the specified temporal object to have the same offset, date 1559 * and time as this object. 1560 * <p> 1561 * This returns a temporal object of the same observable type as the input 1562 * with the offset, date and time changed to be the same as this. 1563 * <p> 1564 * The adjustment is equivalent to using {@link Temporal#with(TemporalField, long)} 1565 * three times, passing {@link ChronoField#EPOCH_DAY}, 1566 * {@link ChronoField#NANO_OF_DAY} and {@link ChronoField#OFFSET_SECONDS} as the fields. 1567 * <p> 1568 * In most cases, it is clearer to reverse the calling pattern by using 1569 * {@link Temporal#with(TemporalAdjuster)}: 1570 * <pre> 1571 * // these two lines are equivalent, but the second approach is recommended 1572 * temporal = thisOffsetDateTime.adjustInto(temporal); 1573 * temporal = temporal.with(thisOffsetDateTime); 1574 * </pre> 1575 * <p> 1576 * This instance is immutable and unaffected by this method call. 1577 * 1578 * @param temporal the target object to be adjusted, not null 1579 * @return the adjusted object, not null 1580 * @throws DateTimeException if unable to make the adjustment 1581 * @throws ArithmeticException if numeric overflow occurs 1582 */ 1583 @Override 1584 public Temporal adjustInto(Temporal temporal) { 1585 // OffsetDateTime is treated as three separate fields, not an instant 1586 // this produces the most consistent set of results overall 1587 // the offset is set after the date and time, as it is typically a small 1588 // tweak to the result, with ZonedDateTime frequently ignoring the offset 1589 return temporal 1590 .with(EPOCH_DAY, toLocalDate().toEpochDay()) 1591 .with(NANO_OF_DAY, toLocalTime().toNanoOfDay()) 1592 .with(OFFSET_SECONDS, getOffset().getTotalSeconds()); 1593 } 1594 1595 /** 1596 * Calculates the amount of time until another date-time in terms of the specified unit. 1597 * <p> 1598 * This calculates the amount of time between two {@code OffsetDateTime} 1599 * objects in terms of a single {@code TemporalUnit}. 1600 * The start and end points are {@code this} and the specified date-time. 1601 * The result will be negative if the end is before the start. 1602 * For example, the amount in days between two date-times can be calculated 1603 * using {@code startDateTime.until(endDateTime, DAYS)}. 1604 * <p> 1605 * The {@code Temporal} passed to this method is converted to a 1606 * {@code OffsetDateTime} using {@link #from(TemporalAccessor)}. 1607 * If the offset differs between the two date-times, the specified 1608 * end date-time is normalized to have the same offset as this date-time. 1609 * <p> 1610 * The calculation returns a whole number, representing the number of 1611 * complete units between the two date-times. 1612 * For example, the amount in months between 2012-06-15T00:00Z and 2012-08-14T23:59Z 1613 * will only be one month as it is one minute short of two months. 1614 * <p> 1615 * There are two equivalent ways of using this method. 1616 * The first is to invoke this method. 1617 * The second is to use {@link TemporalUnit#between(Temporal, Temporal)}: 1618 * <pre> 1619 * // these two lines are equivalent 1620 * amount = start.until(end, MONTHS); 1621 * amount = MONTHS.between(start, end); 1622 * </pre> 1623 * The choice should be made based on which makes the code more readable. 1624 * <p> 1625 * The calculation is implemented in this method for {@link ChronoUnit}. 1626 * The units {@code NANOS}, {@code MICROS}, {@code MILLIS}, {@code SECONDS}, 1627 * {@code MINUTES}, {@code HOURS} and {@code HALF_DAYS}, {@code DAYS}, 1628 * {@code WEEKS}, {@code MONTHS}, {@code YEARS}, {@code DECADES}, 1629 * {@code CENTURIES}, {@code MILLENNIA} and {@code ERAS} are supported. 1630 * Other {@code ChronoUnit} values will throw an exception. 1631 * <p> 1632 * If the unit is not a {@code ChronoUnit}, then the result of this method 1633 * is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)} 1634 * passing {@code this} as the first argument and the converted input temporal 1635 * as the second argument. 1636 * <p> 1637 * This instance is immutable and unaffected by this method call. 1638 * 1639 * @param endExclusive the end date, exclusive, which is converted to an {@code OffsetDateTime}, not null 1640 * @param unit the unit to measure the amount in, not null 1641 * @return the amount of time between this date-time and the end date-time 1642 * @throws DateTimeException if the amount cannot be calculated, or the end 1643 * temporal cannot be converted to an {@code OffsetDateTime} 1644 * @throws UnsupportedTemporalTypeException if the unit is not supported 1645 * @throws ArithmeticException if numeric overflow occurs 1646 */ 1647 @Override 1648 public long until(Temporal endExclusive, TemporalUnit unit) { 1649 OffsetDateTime end = OffsetDateTime.from(endExclusive); 1650 if (unit instanceof ChronoUnit) { 1651 end = end.withOffsetSameInstant(offset); 1652 return dateTime.until(end.dateTime, unit); 1653 } 1654 return unit.between(this, end); 1655 } 1656 1657 /** 1658 * Formats this date-time using the specified formatter. 1659 * <p> 1660 * This date-time will be passed to the formatter to produce a string. 1661 * 1662 * @param formatter the formatter to use, not null 1663 * @return the formatted date-time string, not null 1664 * @throws DateTimeException if an error occurs during printing 1665 */ 1666 public String format(DateTimeFormatter formatter) { 1667 Objects.requireNonNull(formatter, "formatter"); 1668 return formatter.format(this); 1669 } 1670 1671 //----------------------------------------------------------------------- 1672 /** 1673 * Combines this date-time with a time-zone to create a {@code ZonedDateTime} 1674 * ensuring that the result has the same instant. 1675 * <p> 1676 * This returns a {@code ZonedDateTime} formed from this date-time and the specified time-zone. 1677 * This conversion will ignore the visible local date-time and use the underlying instant instead. 1678 * This avoids any problems with local time-line gaps or overlaps. 1679 * The result might have different values for fields such as hour, minute an even day. 1680 * <p> 1681 * To attempt to retain the values of the fields, use {@link #atZoneSimilarLocal(ZoneId)}. 1682 * To use the offset as the zone ID, use {@link #toZonedDateTime()}. 1683 * 1684 * @param zone the time-zone to use, not null 1685 * @return the zoned date-time formed from this date-time, not null 1686 */ 1687 public ZonedDateTime atZoneSameInstant(ZoneId zone) { 1688 return ZonedDateTime.ofInstant(dateTime, offset, zone); 1689 } 1690 1691 /** 1692 * Combines this date-time with a time-zone to create a {@code ZonedDateTime} 1693 * trying to keep the same local date and time. 1694 * <p> 1695 * This returns a {@code ZonedDateTime} formed from this date-time and the specified time-zone. 1696 * Where possible, the result will have the same local date-time as this object. 1697 * <p> 1698 * Time-zone rules, such as daylight savings, mean that not every time on the 1699 * local time-line exists. If the local date-time is in a gap or overlap according to 1700 * the rules then a resolver is used to determine the resultant local time and offset. 1701 * This method uses {@link ZonedDateTime#ofLocal(LocalDateTime, ZoneId, ZoneOffset)} 1702 * to retain the offset from this instance if possible. 1703 * <p> 1704 * Finer control over gaps and overlaps is available in two ways. 1705 * If you simply want to use the later offset at overlaps then call 1706 * {@link ZonedDateTime#withLaterOffsetAtOverlap()} immediately after this method. 1707 * <p> 1708 * To create a zoned date-time at the same instant irrespective of the local time-line, 1709 * use {@link #atZoneSameInstant(ZoneId)}. 1710 * To use the offset as the zone ID, use {@link #toZonedDateTime()}. 1711 * 1712 * @param zone the time-zone to use, not null 1713 * @return the zoned date-time formed from this date and the earliest valid time for the zone, not null 1714 */ 1715 public ZonedDateTime atZoneSimilarLocal(ZoneId zone) { 1716 return ZonedDateTime.ofLocal(dateTime, zone, offset); 1717 } 1718 1719 //----------------------------------------------------------------------- 1720 /** 1721 * Converts this date-time to an {@code OffsetTime}. 1722 * <p> 1723 * This returns an offset time with the same local time and offset. 1724 * 1725 * @return an OffsetTime representing the time and offset, not null 1726 */ 1727 public OffsetTime toOffsetTime() { 1728 return OffsetTime.of(dateTime.toLocalTime(), offset); 1729 } 1730 1731 /** 1732 * Converts this date-time to a {@code ZonedDateTime} using the offset as the zone ID. 1733 * <p> 1734 * This creates the simplest possible {@code ZonedDateTime} using the offset 1735 * as the zone ID. 1736 * <p> 1737 * To control the time-zone used, see {@link #atZoneSameInstant(ZoneId)} and 1738 * {@link #atZoneSimilarLocal(ZoneId)}. 1739 * 1740 * @return a zoned date-time representing the same local date-time and offset, not null 1741 */ 1742 public ZonedDateTime toZonedDateTime() { 1743 return ZonedDateTime.of(dateTime, offset); 1744 } 1745 1746 /** 1747 * Converts this date-time to an {@code Instant}. 1748 * <p> 1749 * This returns an {@code Instant} representing the same point on the 1750 * time-line as this date-time. 1751 * 1752 * @return an {@code Instant} representing the same instant, not null 1753 */ 1754 public Instant toInstant() { 1755 return dateTime.toInstant(offset); 1756 } 1757 1758 /** 1759 * Converts this date-time to the number of seconds from the epoch of 1970-01-01T00:00:00Z. 1760 * <p> 1761 * This allows this date-time to be converted to a value of the 1762 * {@link ChronoField#INSTANT_SECONDS epoch-seconds} field. This is primarily 1763 * intended for low-level conversions rather than general application usage. 1764 * 1765 * @return the number of seconds from the epoch of 1970-01-01T00:00:00Z 1766 */ 1767 public long toEpochSecond() { 1768 return dateTime.toEpochSecond(offset); 1769 } 1770 1771 //----------------------------------------------------------------------- 1772 /** 1773 * Compares this date-time to another date-time. 1774 * <p> 1775 * The comparison is based on the instant then on the local date-time. 1776 * It is "consistent with equals", as defined by {@link Comparable}. 1777 * <p> 1778 * For example, the following is the comparator order: 1779 * <ol> 1780 * <li>{@code 2008-12-03T10:30+01:00}</li> 1781 * <li>{@code 2008-12-03T11:00+01:00}</li> 1782 * <li>{@code 2008-12-03T12:00+02:00}</li> 1783 * <li>{@code 2008-12-03T11:30+01:00}</li> 1784 * <li>{@code 2008-12-03T12:00+01:00}</li> 1785 * <li>{@code 2008-12-03T12:30+01:00}</li> 1786 * </ol> 1787 * Values #2 and #3 represent the same instant on the time-line. 1788 * When two values represent the same instant, the local date-time is compared 1789 * to distinguish them. This step is needed to make the ordering 1790 * consistent with {@code equals()}. 1791 * 1792 * @param other the other date-time to compare to, not null 1793 * @return the comparator value, negative if less, positive if greater 1794 */ 1795 @Override 1796 public int compareTo(OffsetDateTime other) { 1797 int cmp = compareInstant(this, other); 1798 if (cmp == 0) { 1799 cmp = toLocalDateTime().compareTo(other.toLocalDateTime()); 1800 } 1801 return cmp; 1802 } 1803 1804 //----------------------------------------------------------------------- 1805 /** 1806 * Checks if the instant of this date-time is after that of the specified date-time. 1807 * <p> 1808 * This method differs from the comparison in {@link #compareTo} and {@link #equals} in that it 1809 * only compares the instant of the date-time. This is equivalent to using 1810 * {@code dateTime1.toInstant().isAfter(dateTime2.toInstant());}. 1811 * 1812 * @param other the other date-time to compare to, not null 1813 * @return true if this is after the instant of the specified date-time 1814 */ 1815 public boolean isAfter(OffsetDateTime other) { 1816 long thisEpochSec = toEpochSecond(); 1817 long otherEpochSec = other.toEpochSecond(); 1818 return thisEpochSec > otherEpochSec || 1819 (thisEpochSec == otherEpochSec && toLocalTime().getNano() > other.toLocalTime().getNano()); 1820 } 1821 1822 /** 1823 * Checks if the instant of this date-time is before that of the specified date-time. 1824 * <p> 1825 * This method differs from the comparison in {@link #compareTo} in that it 1826 * only compares the instant of the date-time. This is equivalent to using 1827 * {@code dateTime1.toInstant().isBefore(dateTime2.toInstant());}. 1828 * 1829 * @param other the other date-time to compare to, not null 1830 * @return true if this is before the instant of the specified date-time 1831 */ 1832 public boolean isBefore(OffsetDateTime other) { 1833 long thisEpochSec = toEpochSecond(); 1834 long otherEpochSec = other.toEpochSecond(); 1835 return thisEpochSec < otherEpochSec || 1836 (thisEpochSec == otherEpochSec && toLocalTime().getNano() < other.toLocalTime().getNano()); 1837 } 1838 1839 /** 1840 * Checks if the instant of this date-time is equal to that of the specified date-time. 1841 * <p> 1842 * This method differs from the comparison in {@link #compareTo} and {@link #equals} 1843 * in that it only compares the instant of the date-time. This is equivalent to using 1844 * {@code dateTime1.toInstant().equals(dateTime2.toInstant());}. 1845 * 1846 * @param other the other date-time to compare to, not null 1847 * @return true if the instant equals the instant of the specified date-time 1848 */ 1849 public boolean isEqual(OffsetDateTime other) { 1850 return toEpochSecond() == other.toEpochSecond() && 1851 toLocalTime().getNano() == other.toLocalTime().getNano(); 1852 } 1853 1854 //----------------------------------------------------------------------- 1855 /** 1856 * Checks if this date-time is equal to another date-time. 1857 * <p> 1858 * The comparison is based on the local date-time and the offset. 1859 * To compare for the same instant on the time-line, use {@link #isEqual}. 1860 * Only objects of type {@code OffsetDateTime} are compared, other types return false. 1861 * 1862 * @param obj the object to check, null returns false 1863 * @return true if this is equal to the other date-time 1864 */ 1865 @Override 1866 public boolean equals(Object obj) { 1867 if (this == obj) { 1868 return true; 1869 } 1870 if (obj instanceof OffsetDateTime) { 1871 OffsetDateTime other = (OffsetDateTime) obj; 1872 return dateTime.equals(other.dateTime) && offset.equals(other.offset); 1873 } 1874 return false; 1875 } 1876 1877 /** 1878 * A hash code for this date-time. 1879 * 1880 * @return a suitable hash code 1881 */ 1882 @Override 1883 public int hashCode() { 1884 return dateTime.hashCode() ^ offset.hashCode(); 1885 } 1886 1887 //----------------------------------------------------------------------- 1888 /** 1889 * Outputs this date-time as a {@code String}, such as {@code 2007-12-03T10:15:30+01:00}. 1890 * <p> 1891 * The output will be one of the following ISO-8601 formats: 1892 * <ul> 1893 * <li>{@code uuuu-MM-dd'T'HH:mmXXXXX}</li> 1894 * <li>{@code uuuu-MM-dd'T'HH:mm:ssXXXXX}</li> 1895 * <li>{@code uuuu-MM-dd'T'HH:mm:ss.SSSXXXXX}</li> 1896 * <li>{@code uuuu-MM-dd'T'HH:mm:ss.SSSSSSXXXXX}</li> 1897 * <li>{@code uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSXXXXX}</li> 1898 * </ul> 1899 * The format used will be the shortest that outputs the full value of 1900 * the time where the omitted parts are implied to be zero. 1901 * 1902 * @return a string representation of this date-time, not null 1903 */ 1904 @Override 1905 public String toString() { 1906 return dateTime.toString() + offset.toString(); 1907 } 1908 1909 //----------------------------------------------------------------------- 1910 /** 1911 * Writes the object using a 1912 * <a href="../../serialized-form.html#java.time.Ser">dedicated serialized form</a>. 1913 * @serialData 1914 * <pre> 1915 * out.writeByte(10); // identifies an OffsetDateTime 1916 * // the <a href="../../serialized-form.html#java.time.LocalDateTime">datetime</a> excluding the one byte header 1917 * // the <a href="../../serialized-form.html#java.time.ZoneOffset">offset</a> excluding the one byte header 1918 * </pre> 1919 * 1920 * @return the instance of {@code Ser}, not null 1921 */ 1922 private Object writeReplace() { 1923 return new Ser(Ser.OFFSET_DATE_TIME_TYPE, this); 1924 } 1925 1926 /** 1927 * Defend against malicious streams. 1928 * 1929 * @param s the stream to read 1930 * @throws InvalidObjectException always 1931 */ 1932 private void readObject(ObjectInputStream s) throws InvalidObjectException { 1933 throw new InvalidObjectException("Deserialization via serialization delegate"); 1934 } 1935 1936 void writeExternal(ObjectOutput out) throws IOException { 1937 dateTime.writeExternal(out); 1938 offset.writeExternal(out); 1939 } 1940 1941 static OffsetDateTime readExternal(ObjectInput in) throws IOException, ClassNotFoundException { 1942 LocalDateTime dateTime = LocalDateTime.readExternal(in); 1943 ZoneOffset offset = ZoneOffset.readExternal(in); 1944 return OffsetDateTime.of(dateTime, offset); 1945 } 1946 1947} 1948