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