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