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