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