jdk/src/share/classes/java/time/temporal/OffsetTime.java
changeset 15658 55b829ca2334
parent 15657 c588664d547e
child 15659 e575dab44ff5
equal deleted inserted replaced
15657:c588664d547e 15658:55b829ca2334
     1 /*
       
     2  * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 /*
       
    27  * This file is available under and governed by the GNU General Public
       
    28  * License version 2 only, as published by the Free Software Foundation.
       
    29  * However, the following notice accompanied the original version of this
       
    30  * file:
       
    31  *
       
    32  * Copyright (c) 2007-2012, Stephen Colebourne & Michael Nascimento Santos
       
    33  *
       
    34  * All rights reserved.
       
    35  *
       
    36  * Redistribution and use in source and binary forms, with or without
       
    37  * modification, are permitted provided that the following conditions are met:
       
    38  *
       
    39  *  * Redistributions of source code must retain the above copyright notice,
       
    40  *    this list of conditions and the following disclaimer.
       
    41  *
       
    42  *  * Redistributions in binary form must reproduce the above copyright notice,
       
    43  *    this list of conditions and the following disclaimer in the documentation
       
    44  *    and/or other materials provided with the distribution.
       
    45  *
       
    46  *  * Neither the name of JSR-310 nor the names of its contributors
       
    47  *    may be used to endorse or promote products derived from this software
       
    48  *    without specific prior written permission.
       
    49  *
       
    50  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
       
    51  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
       
    52  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
       
    53  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
       
    54  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
       
    55  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
       
    56  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
       
    57  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
       
    58  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
       
    59  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
       
    60  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    61  */
       
    62 package java.time.temporal;
       
    63 
       
    64 import static java.time.temporal.ChronoField.NANO_OF_DAY;
       
    65 import static java.time.temporal.ChronoField.OFFSET_SECONDS;
       
    66 import static java.time.temporal.ChronoLocalDateTimeImpl.NANOS_PER_HOUR;
       
    67 import static java.time.temporal.ChronoLocalDateTimeImpl.NANOS_PER_MINUTE;
       
    68 import static java.time.temporal.ChronoLocalDateTimeImpl.NANOS_PER_SECOND;
       
    69 import static java.time.temporal.ChronoLocalDateTimeImpl.SECONDS_PER_DAY;
       
    70 import static java.time.temporal.ChronoUnit.NANOS;
       
    71 
       
    72 import java.io.IOException;
       
    73 import java.io.InvalidObjectException;
       
    74 import java.io.ObjectInput;
       
    75 import java.io.ObjectOutput;
       
    76 import java.io.ObjectStreamException;
       
    77 import java.io.Serializable;
       
    78 import java.time.Clock;
       
    79 import java.time.DateTimeException;
       
    80 import java.time.Instant;
       
    81 import java.time.LocalDate;
       
    82 import java.time.LocalTime;
       
    83 import java.time.ZoneId;
       
    84 import java.time.ZoneOffset;
       
    85 import java.time.format.DateTimeFormatter;
       
    86 import java.time.format.DateTimeFormatters;
       
    87 import java.time.format.DateTimeParseException;
       
    88 import java.time.zone.ZoneRules;
       
    89 import java.util.Objects;
       
    90 
       
    91 /**
       
    92  * A time with an offset from UTC/Greenwich in the ISO-8601 calendar system,
       
    93  * such as {@code 10:15:30+01:00}.
       
    94  * <p>
       
    95  * {@code OffsetTime} is an immutable date-time object that represents a time, often
       
    96  * viewed as hour-minute-second-offset.
       
    97  * This class stores all time fields, to a precision of nanoseconds,
       
    98  * as well as a zone offset.
       
    99  * For example, the value "13:45.30.123456789+02:00" can be stored
       
   100  * in an {@code OffsetTime}.
       
   101  *
       
   102  * <h3>Specification for implementors</h3>
       
   103  * This class is immutable and thread-safe.
       
   104  *
       
   105  * @since 1.8
       
   106  */
       
   107 public final class OffsetTime
       
   108         implements Temporal, TemporalAdjuster, Comparable<OffsetTime>, Serializable {
       
   109 
       
   110     /**
       
   111      * The minimum supported {@code OffsetTime}, '00:00:00+18:00'.
       
   112      * This is the time of midnight at the start of the day in the maximum offset
       
   113      * (larger offsets are earlier on the time-line).
       
   114      * This combines {@link LocalTime#MIN} and {@link ZoneOffset#MAX}.
       
   115      * This could be used by an application as a "far past" date.
       
   116      */
       
   117     public static final OffsetTime MIN = LocalTime.MIN.atOffset(ZoneOffset.MAX);
       
   118     /**
       
   119      * The maximum supported {@code OffsetTime}, '23:59:59.999999999-18:00'.
       
   120      * This is the time just before midnight at the end of the day in the minimum offset
       
   121      * (larger negative offsets are later on the time-line).
       
   122      * This combines {@link LocalTime#MAX} and {@link ZoneOffset#MIN}.
       
   123      * This could be used by an application as a "far future" date.
       
   124      */
       
   125     public static final OffsetTime MAX = LocalTime.MAX.atOffset(ZoneOffset.MIN);
       
   126 
       
   127     /**
       
   128      * Serialization version.
       
   129      */
       
   130     private static final long serialVersionUID = 7264499704384272492L;
       
   131 
       
   132     /**
       
   133      * The local date-time.
       
   134      */
       
   135     private final LocalTime time;
       
   136     /**
       
   137      * The offset from UTC/Greenwich.
       
   138      */
       
   139     private final ZoneOffset offset;
       
   140 
       
   141     //-----------------------------------------------------------------------
       
   142     /**
       
   143      * Obtains the current time from the system clock in the default time-zone.
       
   144      * <p>
       
   145      * This will query the {@link java.time.Clock#systemDefaultZone() system clock} in the default
       
   146      * time-zone to obtain the current time.
       
   147      * The offset will be calculated from the time-zone in the clock.
       
   148      * <p>
       
   149      * Using this method will prevent the ability to use an alternate clock for testing
       
   150      * because the clock is hard-coded.
       
   151      *
       
   152      * @return the current time using the system clock, not null
       
   153      */
       
   154     public static OffsetTime now() {
       
   155         return now(Clock.systemDefaultZone());
       
   156     }
       
   157 
       
   158     /**
       
   159      * Obtains the current time from the system clock in the specified time-zone.
       
   160      * <p>
       
   161      * This will query the {@link Clock#system(java.time.ZoneId) system clock} to obtain the current time.
       
   162      * Specifying the time-zone avoids dependence on the default time-zone.
       
   163      * The offset will be calculated from the specified time-zone.
       
   164      * <p>
       
   165      * Using this method will prevent the ability to use an alternate clock for testing
       
   166      * because the clock is hard-coded.
       
   167      *
       
   168      * @param zone  the zone ID to use, not null
       
   169      * @return the current time using the system clock, not null
       
   170      */
       
   171     public static OffsetTime now(ZoneId zone) {
       
   172         return now(Clock.system(zone));
       
   173     }
       
   174 
       
   175     /**
       
   176      * Obtains the current time from the specified clock.
       
   177      * <p>
       
   178      * This will query the specified clock to obtain the current time.
       
   179      * The offset will be calculated from the time-zone in the clock.
       
   180      * <p>
       
   181      * Using this method allows the use of an alternate clock for testing.
       
   182      * The alternate clock may be introduced using {@link Clock dependency injection}.
       
   183      *
       
   184      * @param clock  the clock to use, not null
       
   185      * @return the current time, not null
       
   186      */
       
   187     public static OffsetTime now(Clock clock) {
       
   188         Objects.requireNonNull(clock, "clock");
       
   189         final Instant now = clock.instant();  // called once
       
   190         return ofInstant(now, clock.getZone().getRules().getOffset(now));
       
   191     }
       
   192 
       
   193     //-----------------------------------------------------------------------
       
   194     /**
       
   195      * Obtains an instance of {@code OffsetTime} from a local time and an offset.
       
   196      *
       
   197      * @param time  the local time, not null
       
   198      * @param offset  the zone offset, not null
       
   199      * @return the offset time, not null
       
   200      */
       
   201     public static OffsetTime of(LocalTime time, ZoneOffset offset) {
       
   202         return new OffsetTime(time, offset);
       
   203     }
       
   204 
       
   205     //-----------------------------------------------------------------------
       
   206     /**
       
   207      * Obtains an instance of {@code OffsetTime} from an {@code Instant} and zone ID.
       
   208      * <p>
       
   209      * This creates an offset time with the same instant as that specified.
       
   210      * Finding the offset from UTC/Greenwich is simple as there is only one valid
       
   211      * offset for each instant.
       
   212      * <p>
       
   213      * The date component of the instant is dropped during the conversion.
       
   214      * This means that the conversion can never fail due to the instant being
       
   215      * out of the valid range of dates.
       
   216      *
       
   217      * @param instant  the instant to create the time from, not null
       
   218      * @param zone  the time-zone, which may be an offset, not null
       
   219      * @return the offset time, not null
       
   220      */
       
   221     public static OffsetTime ofInstant(Instant instant, ZoneId zone) {
       
   222         Objects.requireNonNull(instant, "instant");
       
   223         Objects.requireNonNull(zone, "zone");
       
   224         ZoneRules rules = zone.getRules();
       
   225         ZoneOffset offset = rules.getOffset(instant);
       
   226         long secsOfDay = instant.getEpochSecond() % SECONDS_PER_DAY;
       
   227         secsOfDay = (secsOfDay + offset.getTotalSeconds()) % SECONDS_PER_DAY;
       
   228         if (secsOfDay < 0) {
       
   229             secsOfDay += SECONDS_PER_DAY;
       
   230         }
       
   231         LocalTime time = LocalTime.ofSecondOfDay(secsOfDay, instant.getNano());
       
   232         return new OffsetTime(time, offset);
       
   233     }
       
   234 
       
   235     //-----------------------------------------------------------------------
       
   236     /**
       
   237      * Obtains an instance of {@code OffsetTime} from a temporal object.
       
   238      * <p>
       
   239      * A {@code TemporalAccessor} represents some form of date and time information.
       
   240      * This factory converts the arbitrary temporal object to an instance of {@code OffsetTime}.
       
   241      * <p>
       
   242      * The conversion extracts and combines {@code LocalTime} and {@code ZoneOffset}.
       
   243      * <p>
       
   244      * This method matches the signature of the functional interface {@link TemporalQuery}
       
   245      * allowing it to be used in queries via method reference, {@code OffsetTime::from}.
       
   246      *
       
   247      * @param temporal  the temporal object to convert, not null
       
   248      * @return the offset time, not null
       
   249      * @throws DateTimeException if unable to convert to an {@code OffsetTime}
       
   250      */
       
   251     public static OffsetTime from(TemporalAccessor temporal) {
       
   252         if (temporal instanceof OffsetTime) {
       
   253             return (OffsetTime) temporal;
       
   254         }
       
   255         try {
       
   256             LocalTime time = LocalTime.from(temporal);
       
   257             ZoneOffset offset = ZoneOffset.from(temporal);
       
   258             return new OffsetTime(time, offset);
       
   259         } catch (DateTimeException ex) {
       
   260             throw new DateTimeException("Unable to obtain OffsetTime from TemporalAccessor: " + temporal.getClass(), ex);
       
   261         }
       
   262     }
       
   263 
       
   264     //-----------------------------------------------------------------------
       
   265     /**
       
   266      * Obtains an instance of {@code OffsetTime} from a text string such as {@code 10:15:30+01:00}.
       
   267      * <p>
       
   268      * The string must represent a valid time and is parsed using
       
   269      * {@link java.time.format.DateTimeFormatters#isoOffsetTime()}.
       
   270      *
       
   271      * @param text  the text to parse such as "10:15:30+01:00", not null
       
   272      * @return the parsed local time, not null
       
   273      * @throws DateTimeParseException if the text cannot be parsed
       
   274      */
       
   275     public static OffsetTime parse(CharSequence text) {
       
   276         return parse(text, DateTimeFormatters.isoOffsetTime());
       
   277     }
       
   278 
       
   279     /**
       
   280      * Obtains an instance of {@code OffsetTime} from a text string using a specific formatter.
       
   281      * <p>
       
   282      * The text is parsed using the formatter, returning a time.
       
   283      *
       
   284      * @param text  the text to parse, not null
       
   285      * @param formatter  the formatter to use, not null
       
   286      * @return the parsed offset time, not null
       
   287      * @throws DateTimeParseException if the text cannot be parsed
       
   288      */
       
   289     public static OffsetTime parse(CharSequence text, DateTimeFormatter formatter) {
       
   290         Objects.requireNonNull(formatter, "formatter");
       
   291         return formatter.parse(text, OffsetTime::from);
       
   292     }
       
   293 
       
   294     //-----------------------------------------------------------------------
       
   295     /**
       
   296      * Constructor.
       
   297      *
       
   298      * @param time  the local time, not null
       
   299      * @param offset  the zone offset, not null
       
   300      */
       
   301     private OffsetTime(LocalTime time, ZoneOffset offset) {
       
   302         this.time = Objects.requireNonNull(time, "time");
       
   303         this.offset = Objects.requireNonNull(offset, "offset");
       
   304     }
       
   305 
       
   306     /**
       
   307      * Returns a new time based on this one, returning {@code this} where possible.
       
   308      *
       
   309      * @param time  the time to create with, not null
       
   310      * @param offset  the zone offset to create with, not null
       
   311      */
       
   312     private OffsetTime with(LocalTime time, ZoneOffset offset) {
       
   313         if (this.time == time && this.offset.equals(offset)) {
       
   314             return this;
       
   315         }
       
   316         return new OffsetTime(time, offset);
       
   317     }
       
   318 
       
   319     //-----------------------------------------------------------------------
       
   320     /**
       
   321      * Checks if the specified field is supported.
       
   322      * <p>
       
   323      * This checks if this time can be queried for the specified field.
       
   324      * If false, then calling the {@link #range(TemporalField) range} and
       
   325      * {@link #get(TemporalField) get} methods will throw an exception.
       
   326      * <p>
       
   327      * If the field is a {@link ChronoField} then the query is implemented here.
       
   328      * The supported fields are:
       
   329      * <ul>
       
   330      * <li>{@code NANO_OF_SECOND}
       
   331      * <li>{@code NANO_OF_DAY}
       
   332      * <li>{@code MICRO_OF_SECOND}
       
   333      * <li>{@code MICRO_OF_DAY}
       
   334      * <li>{@code MILLI_OF_SECOND}
       
   335      * <li>{@code MILLI_OF_DAY}
       
   336      * <li>{@code SECOND_OF_MINUTE}
       
   337      * <li>{@code SECOND_OF_DAY}
       
   338      * <li>{@code MINUTE_OF_HOUR}
       
   339      * <li>{@code MINUTE_OF_DAY}
       
   340      * <li>{@code HOUR_OF_AMPM}
       
   341      * <li>{@code CLOCK_HOUR_OF_AMPM}
       
   342      * <li>{@code HOUR_OF_DAY}
       
   343      * <li>{@code CLOCK_HOUR_OF_DAY}
       
   344      * <li>{@code AMPM_OF_DAY}
       
   345      * <li>{@code OFFSET_SECONDS}
       
   346      * </ul>
       
   347      * All other {@code ChronoField} instances will return false.
       
   348      * <p>
       
   349      * If the field is not a {@code ChronoField}, then the result of this method
       
   350      * is obtained by invoking {@code TemporalField.doIsSupported(TemporalAccessor)}
       
   351      * passing {@code this} as the argument.
       
   352      * Whether the field is supported is determined by the field.
       
   353      *
       
   354      * @param field  the field to check, null returns false
       
   355      * @return true if the field is supported on this time, false if not
       
   356      */
       
   357     @Override
       
   358     public boolean isSupported(TemporalField field) {
       
   359         if (field instanceof ChronoField) {
       
   360             return ((ChronoField) field).isTimeField() || field == OFFSET_SECONDS;
       
   361         }
       
   362         return field != null && field.doIsSupported(this);
       
   363     }
       
   364 
       
   365     /**
       
   366      * Gets the range of valid values for the specified field.
       
   367      * <p>
       
   368      * The range object expresses the minimum and maximum valid values for a field.
       
   369      * This time is used to enhance the accuracy of the returned range.
       
   370      * If it is not possible to return the range, because the field is not supported
       
   371      * or for some other reason, an exception is thrown.
       
   372      * <p>
       
   373      * If the field is a {@link ChronoField} then the query is implemented here.
       
   374      * The {@link #isSupported(TemporalField) supported fields} will return
       
   375      * appropriate range instances.
       
   376      * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
       
   377      * <p>
       
   378      * If the field is not a {@code ChronoField}, then the result of this method
       
   379      * is obtained by invoking {@code TemporalField.doRange(TemporalAccessor)}
       
   380      * passing {@code this} as the argument.
       
   381      * Whether the range can be obtained is determined by the field.
       
   382      *
       
   383      * @param field  the field to query the range for, not null
       
   384      * @return the range of valid values for the field, not null
       
   385      * @throws DateTimeException if the range for the field cannot be obtained
       
   386      */
       
   387     @Override
       
   388     public ValueRange range(TemporalField field) {
       
   389         if (field instanceof ChronoField) {
       
   390             if (field == OFFSET_SECONDS) {
       
   391                 return field.range();
       
   392             }
       
   393             return time.range(field);
       
   394         }
       
   395         return field.doRange(this);
       
   396     }
       
   397 
       
   398     /**
       
   399      * Gets the value of the specified field from this time as an {@code int}.
       
   400      * <p>
       
   401      * This queries this time for the value for the specified field.
       
   402      * The returned value will always be within the valid range of values for the field.
       
   403      * If it is not possible to return the value, because the field is not supported
       
   404      * or for some other reason, an exception is thrown.
       
   405      * <p>
       
   406      * If the field is a {@link ChronoField} then the query is implemented here.
       
   407      * The {@link #isSupported(TemporalField) supported fields} will return valid
       
   408      * values based on this time, except {@code NANO_OF_DAY} and {@code MICRO_OF_DAY}
       
   409      * which are too large to fit in an {@code int} and throw a {@code DateTimeException}.
       
   410      * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
       
   411      * <p>
       
   412      * If the field is not a {@code ChronoField}, then the result of this method
       
   413      * is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
       
   414      * passing {@code this} as the argument. Whether the value can be obtained,
       
   415      * and what the value represents, is determined by the field.
       
   416      *
       
   417      * @param field  the field to get, not null
       
   418      * @return the value for the field
       
   419      * @throws DateTimeException if a value for the field cannot be obtained
       
   420      * @throws ArithmeticException if numeric overflow occurs
       
   421      */
       
   422     @Override  // override for Javadoc
       
   423     public int get(TemporalField field) {
       
   424         return Temporal.super.get(field);
       
   425     }
       
   426 
       
   427     /**
       
   428      * Gets the value of the specified field from this time as a {@code long}.
       
   429      * <p>
       
   430      * This queries this time for the value for the specified field.
       
   431      * If it is not possible to return the value, because the field is not supported
       
   432      * or for some other reason, an exception is thrown.
       
   433      * <p>
       
   434      * If the field is a {@link ChronoField} then the query is implemented here.
       
   435      * The {@link #isSupported(TemporalField) supported fields} will return valid
       
   436      * values based on this time.
       
   437      * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
       
   438      * <p>
       
   439      * If the field is not a {@code ChronoField}, then the result of this method
       
   440      * is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
       
   441      * passing {@code this} as the argument. Whether the value can be obtained,
       
   442      * and what the value represents, is determined by the field.
       
   443      *
       
   444      * @param field  the field to get, not null
       
   445      * @return the value for the field
       
   446      * @throws DateTimeException if a value for the field cannot be obtained
       
   447      * @throws ArithmeticException if numeric overflow occurs
       
   448      */
       
   449     @Override
       
   450     public long getLong(TemporalField field) {
       
   451         if (field instanceof ChronoField) {
       
   452             if (field == OFFSET_SECONDS) {
       
   453                 return getOffset().getTotalSeconds();
       
   454             }
       
   455             return time.getLong(field);
       
   456         }
       
   457         return field.doGet(this);
       
   458     }
       
   459 
       
   460     //-----------------------------------------------------------------------
       
   461     /**
       
   462      * Gets the zone offset, such as '+01:00'.
       
   463      * <p>
       
   464      * This is the offset of the local time from UTC/Greenwich.
       
   465      *
       
   466      * @return the zone offset, not null
       
   467      */
       
   468     public ZoneOffset getOffset() {
       
   469         return offset;
       
   470     }
       
   471 
       
   472     /**
       
   473      * Returns a copy of this {@code OffsetTime} with the specified offset ensuring
       
   474      * that the result has the same local time.
       
   475      * <p>
       
   476      * This method returns an object with the same {@code LocalTime} and the specified {@code ZoneOffset}.
       
   477      * No calculation is needed or performed.
       
   478      * For example, if this time represents {@code 10:30+02:00} and the offset specified is
       
   479      * {@code +03:00}, then this method will return {@code 10:30+03:00}.
       
   480      * <p>
       
   481      * To take into account the difference between the offsets, and adjust the time fields,
       
   482      * use {@link #withOffsetSameInstant}.
       
   483      * <p>
       
   484      * This instance is immutable and unaffected by this method call.
       
   485      *
       
   486      * @param offset  the zone offset to change to, not null
       
   487      * @return an {@code OffsetTime} based on this time with the requested offset, not null
       
   488      */
       
   489     public OffsetTime withOffsetSameLocal(ZoneOffset offset) {
       
   490         return offset != null && offset.equals(this.offset) ? this : new OffsetTime(time, offset);
       
   491     }
       
   492 
       
   493     /**
       
   494      * Returns a copy of this {@code OffsetTime} with the specified offset ensuring
       
   495      * that the result is at the same instant on an implied day.
       
   496      * <p>
       
   497      * This method returns an object with the specified {@code ZoneOffset} and a {@code LocalTime}
       
   498      * adjusted by the difference between the two offsets.
       
   499      * This will result in the old and new objects representing the same instant an an implied day.
       
   500      * This is useful for finding the local time in a different offset.
       
   501      * For example, if this time represents {@code 10:30+02:00} and the offset specified is
       
   502      * {@code +03:00}, then this method will return {@code 11:30+03:00}.
       
   503      * <p>
       
   504      * To change the offset without adjusting the local time use {@link #withOffsetSameLocal}.
       
   505      * <p>
       
   506      * This instance is immutable and unaffected by this method call.
       
   507      *
       
   508      * @param offset  the zone offset to change to, not null
       
   509      * @return an {@code OffsetTime} based on this time with the requested offset, not null
       
   510      */
       
   511     public OffsetTime withOffsetSameInstant(ZoneOffset offset) {
       
   512         if (offset.equals(this.offset)) {
       
   513             return this;
       
   514         }
       
   515         int difference = offset.getTotalSeconds() - this.offset.getTotalSeconds();
       
   516         LocalTime adjusted = time.plusSeconds(difference);
       
   517         return new OffsetTime(adjusted, offset);
       
   518     }
       
   519 
       
   520     //-----------------------------------------------------------------------
       
   521     /**
       
   522      * Gets the {@code LocalTime} part of this date-time.
       
   523      * <p>
       
   524      * This returns a {@code LocalTime} with the same hour, minute, second and
       
   525      * nanosecond as this date-time.
       
   526      *
       
   527      * @return the time part of this date-time, not null
       
   528      */
       
   529     public LocalTime getTime() {
       
   530         return time;
       
   531     }
       
   532 
       
   533     //-----------------------------------------------------------------------
       
   534     /**
       
   535      * Gets the hour-of-day field.
       
   536      *
       
   537      * @return the hour-of-day, from 0 to 23
       
   538      */
       
   539     public int getHour() {
       
   540         return time.getHour();
       
   541     }
       
   542 
       
   543     /**
       
   544      * Gets the minute-of-hour field.
       
   545      *
       
   546      * @return the minute-of-hour, from 0 to 59
       
   547      */
       
   548     public int getMinute() {
       
   549         return time.getMinute();
       
   550     }
       
   551 
       
   552     /**
       
   553      * Gets the second-of-minute field.
       
   554      *
       
   555      * @return the second-of-minute, from 0 to 59
       
   556      */
       
   557     public int getSecond() {
       
   558         return time.getSecond();
       
   559     }
       
   560 
       
   561     /**
       
   562      * Gets the nano-of-second field.
       
   563      *
       
   564      * @return the nano-of-second, from 0 to 999,999,999
       
   565      */
       
   566     public int getNano() {
       
   567         return time.getNano();
       
   568     }
       
   569 
       
   570     //-----------------------------------------------------------------------
       
   571     /**
       
   572      * Returns an adjusted copy of this time.
       
   573      * <p>
       
   574      * This returns a new {@code OffsetTime}, based on this one, with the time adjusted.
       
   575      * The adjustment takes place using the specified adjuster strategy object.
       
   576      * Read the documentation of the adjuster to understand what adjustment will be made.
       
   577      * <p>
       
   578      * A simple adjuster might simply set the one of the fields, such as the hour field.
       
   579      * A more complex adjuster might set the time to the last hour of the day.
       
   580      * <p>
       
   581      * The classes {@link LocalTime} and {@link ZoneOffset} implement {@code TemporalAdjuster},
       
   582      * thus this method can be used to change the time or offset:
       
   583      * <pre>
       
   584      *  result = offsetTime.with(time);
       
   585      *  result = offsetTime.with(offset);
       
   586      * </pre>
       
   587      * <p>
       
   588      * The result of this method is obtained by invoking the
       
   589      * {@link TemporalAdjuster#adjustInto(Temporal)} method on the
       
   590      * specified adjuster passing {@code this} as the argument.
       
   591      * <p>
       
   592      * This instance is immutable and unaffected by this method call.
       
   593      *
       
   594      * @param adjuster the adjuster to use, not null
       
   595      * @return an {@code OffsetTime} based on {@code this} with the adjustment made, not null
       
   596      * @throws DateTimeException if the adjustment cannot be made
       
   597      * @throws ArithmeticException if numeric overflow occurs
       
   598      */
       
   599     @Override
       
   600     public OffsetTime with(TemporalAdjuster adjuster) {
       
   601         // optimizations
       
   602         if (adjuster instanceof LocalTime) {
       
   603             return with((LocalTime) adjuster, offset);
       
   604         } else if (adjuster instanceof ZoneOffset) {
       
   605             return with(time, (ZoneOffset) adjuster);
       
   606         } else if (adjuster instanceof OffsetTime) {
       
   607             return (OffsetTime) adjuster;
       
   608         }
       
   609         return (OffsetTime) adjuster.adjustInto(this);
       
   610     }
       
   611 
       
   612     /**
       
   613      * Returns a copy of this time with the specified field set to a new value.
       
   614      * <p>
       
   615      * This returns a new {@code OffsetTime}, based on this one, with the value
       
   616      * for the specified field changed.
       
   617      * This can be used to change any supported field, such as the hour, minute or second.
       
   618      * If it is not possible to set the value, because the field is not supported or for
       
   619      * some other reason, an exception is thrown.
       
   620      * <p>
       
   621      * If the field is a {@link ChronoField} then the adjustment is implemented here.
       
   622      * <p>
       
   623      * The {@code OFFSET_SECONDS} field will return a time with the specified offset.
       
   624      * The local time is unaltered. If the new offset value is outside the valid range
       
   625      * then a {@code DateTimeException} will be thrown.
       
   626      * <p>
       
   627      * The other {@link #isSupported(TemporalField) supported fields} will behave as per
       
   628      * the matching method on {@link LocalTime#with(TemporalField, long)} LocalTime}.
       
   629      * In this case, the offset is not part of the calculation and will be unchanged.
       
   630      * <p>
       
   631      * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
       
   632      * <p>
       
   633      * If the field is not a {@code ChronoField}, then the result of this method
       
   634      * is obtained by invoking {@code TemporalField.doWith(Temporal, long)}
       
   635      * passing {@code this} as the argument. In this case, the field determines
       
   636      * whether and how to adjust the instant.
       
   637      * <p>
       
   638      * This instance is immutable and unaffected by this method call.
       
   639      *
       
   640      * @param field  the field to set in the result, not null
       
   641      * @param newValue  the new value of the field in the result
       
   642      * @return an {@code OffsetTime} based on {@code this} with the specified field set, not null
       
   643      * @throws DateTimeException if the field cannot be set
       
   644      * @throws ArithmeticException if numeric overflow occurs
       
   645      */
       
   646     @Override
       
   647     public OffsetTime with(TemporalField field, long newValue) {
       
   648         if (field instanceof ChronoField) {
       
   649             if (field == OFFSET_SECONDS) {
       
   650                 ChronoField f = (ChronoField) field;
       
   651                 return with(time, ZoneOffset.ofTotalSeconds(f.checkValidIntValue(newValue)));
       
   652             }
       
   653             return with(time.with(field, newValue), offset);
       
   654         }
       
   655         return field.doWith(this, newValue);
       
   656     }
       
   657 
       
   658     //-----------------------------------------------------------------------
       
   659     /**
       
   660      * Returns a copy of this {@code OffsetTime} with the hour-of-day value altered.
       
   661      * <p>
       
   662      * The offset does not affect the calculation and will be the same in the result.
       
   663      * <p>
       
   664      * This instance is immutable and unaffected by this method call.
       
   665      *
       
   666      * @param hour  the hour-of-day to set in the result, from 0 to 23
       
   667      * @return an {@code OffsetTime} based on this time with the requested hour, not null
       
   668      * @throws DateTimeException if the hour value is invalid
       
   669      */
       
   670     public OffsetTime withHour(int hour) {
       
   671         return with(time.withHour(hour), offset);
       
   672     }
       
   673 
       
   674     /**
       
   675      * Returns a copy of this {@code OffsetTime} with the minute-of-hour value altered.
       
   676      * <p>
       
   677      * The offset does not affect the calculation and will be the same in the result.
       
   678      * <p>
       
   679      * This instance is immutable and unaffected by this method call.
       
   680      *
       
   681      * @param minute  the minute-of-hour to set in the result, from 0 to 59
       
   682      * @return an {@code OffsetTime} based on this time with the requested minute, not null
       
   683      * @throws DateTimeException if the minute value is invalid
       
   684      */
       
   685     public OffsetTime withMinute(int minute) {
       
   686         return with(time.withMinute(minute), offset);
       
   687     }
       
   688 
       
   689     /**
       
   690      * Returns a copy of this {@code OffsetTime} with the second-of-minute value altered.
       
   691      * <p>
       
   692      * The offset does not affect the calculation and will be the same in the result.
       
   693      * <p>
       
   694      * This instance is immutable and unaffected by this method call.
       
   695      *
       
   696      * @param second  the second-of-minute to set in the result, from 0 to 59
       
   697      * @return an {@code OffsetTime} based on this time with the requested second, not null
       
   698      * @throws DateTimeException if the second value is invalid
       
   699      */
       
   700     public OffsetTime withSecond(int second) {
       
   701         return with(time.withSecond(second), offset);
       
   702     }
       
   703 
       
   704     /**
       
   705      * Returns a copy of this {@code OffsetTime} with the nano-of-second value altered.
       
   706      * <p>
       
   707      * The offset does not affect the calculation and will be the same in the result.
       
   708      * <p>
       
   709      * This instance is immutable and unaffected by this method call.
       
   710      *
       
   711      * @param nanoOfSecond  the nano-of-second to set in the result, from 0 to 999,999,999
       
   712      * @return an {@code OffsetTime} based on this time with the requested nanosecond, not null
       
   713      * @throws DateTimeException if the nanos value is invalid
       
   714      */
       
   715     public OffsetTime withNano(int nanoOfSecond) {
       
   716         return with(time.withNano(nanoOfSecond), offset);
       
   717     }
       
   718 
       
   719     //-----------------------------------------------------------------------
       
   720     /**
       
   721      * Returns a copy of this {@code OffsetTime} with the time truncated.
       
   722      * <p>
       
   723      * Truncation returns a copy of the original time with fields
       
   724      * smaller than the specified unit set to zero.
       
   725      * For example, truncating with the {@link ChronoUnit#MINUTES minutes} unit
       
   726      * will set the second-of-minute and nano-of-second field to zero.
       
   727      * <p>
       
   728      * Not all units are accepted. The {@link ChronoUnit#DAYS days} unit and time
       
   729      * units with an exact duration can be used, other units throw an exception.
       
   730      * <p>
       
   731      * The offset does not affect the calculation and will be the same in the result.
       
   732      * <p>
       
   733      * This instance is immutable and unaffected by this method call.
       
   734      *
       
   735      * @param unit  the unit to truncate to, not null
       
   736      * @return an {@code OffsetTime} based on this time with the time truncated, not null
       
   737      * @throws DateTimeException if unable to truncate
       
   738      */
       
   739     public OffsetTime truncatedTo(TemporalUnit unit) {
       
   740         return with(time.truncatedTo(unit), offset);
       
   741     }
       
   742 
       
   743     //-----------------------------------------------------------------------
       
   744     /**
       
   745      * Returns a copy of this date with the specified period added.
       
   746      * <p>
       
   747      * This method returns a new time based on this time with the specified period added.
       
   748      * The adder is typically {@link java.time.Period} but may be any other type implementing
       
   749      * the {@link TemporalAdder} interface.
       
   750      * The calculation is delegated to the specified adjuster, which typically calls
       
   751      * back to {@link #plus(long, TemporalUnit)}.
       
   752      * The offset is not part of the calculation and will be unchanged in the result.
       
   753      * <p>
       
   754      * This instance is immutable and unaffected by this method call.
       
   755      *
       
   756      * @param adder  the adder to use, not null
       
   757      * @return an {@code OffsetTime} based on this time with the addition made, not null
       
   758      * @throws DateTimeException if the addition cannot be made
       
   759      * @throws ArithmeticException if numeric overflow occurs
       
   760      */
       
   761     @Override
       
   762     public OffsetTime plus(TemporalAdder adder) {
       
   763         return (OffsetTime) adder.addTo(this);
       
   764     }
       
   765 
       
   766     /**
       
   767      * Returns a copy of this time with the specified period added.
       
   768      * <p>
       
   769      * This method returns a new time based on this time with the specified period added.
       
   770      * This can be used to add any period that is defined by a unit, for example to add hours, minutes or seconds.
       
   771      * The unit is responsible for the details of the calculation, including the resolution
       
   772      * of any edge cases in the calculation.
       
   773      * The offset is not part of the calculation and will be unchanged in the result.
       
   774      * <p>
       
   775      * This instance is immutable and unaffected by this method call.
       
   776      *
       
   777      * @param amountToAdd  the amount of the unit to add to the result, may be negative
       
   778      * @param unit  the unit of the period to add, not null
       
   779      * @return an {@code OffsetTime} based on this time with the specified period added, not null
       
   780      * @throws DateTimeException if the unit cannot be added to this type
       
   781      */
       
   782     @Override
       
   783     public OffsetTime plus(long amountToAdd, TemporalUnit unit) {
       
   784         if (unit instanceof ChronoUnit) {
       
   785             return with(time.plus(amountToAdd, unit), offset);
       
   786         }
       
   787         return unit.doPlus(this, amountToAdd);
       
   788     }
       
   789 
       
   790     //-----------------------------------------------------------------------
       
   791     /**
       
   792      * Returns a copy of this {@code OffsetTime} with the specified period in hours added.
       
   793      * <p>
       
   794      * This adds the specified number of hours to this time, returning a new time.
       
   795      * The calculation wraps around midnight.
       
   796      * <p>
       
   797      * This instance is immutable and unaffected by this method call.
       
   798      *
       
   799      * @param hours  the hours to add, may be negative
       
   800      * @return an {@code OffsetTime} based on this time with the hours added, not null
       
   801      */
       
   802     public OffsetTime plusHours(long hours) {
       
   803         return with(time.plusHours(hours), offset);
       
   804     }
       
   805 
       
   806     /**
       
   807      * Returns a copy of this {@code OffsetTime} with the specified period in minutes added.
       
   808      * <p>
       
   809      * This adds the specified number of minutes to this time, returning a new time.
       
   810      * The calculation wraps around midnight.
       
   811      * <p>
       
   812      * This instance is immutable and unaffected by this method call.
       
   813      *
       
   814      * @param minutes  the minutes to add, may be negative
       
   815      * @return an {@code OffsetTime} based on this time with the minutes added, not null
       
   816      */
       
   817     public OffsetTime plusMinutes(long minutes) {
       
   818         return with(time.plusMinutes(minutes), offset);
       
   819     }
       
   820 
       
   821     /**
       
   822      * Returns a copy of this {@code OffsetTime} with the specified period in seconds added.
       
   823      * <p>
       
   824      * This adds the specified number of seconds to this time, returning a new time.
       
   825      * The calculation wraps around midnight.
       
   826      * <p>
       
   827      * This instance is immutable and unaffected by this method call.
       
   828      *
       
   829      * @param seconds  the seconds to add, may be negative
       
   830      * @return an {@code OffsetTime} based on this time with the seconds added, not null
       
   831      */
       
   832     public OffsetTime plusSeconds(long seconds) {
       
   833         return with(time.plusSeconds(seconds), offset);
       
   834     }
       
   835 
       
   836     /**
       
   837      * Returns a copy of this {@code OffsetTime} with the specified period in nanoseconds added.
       
   838      * <p>
       
   839      * This adds the specified number of nanoseconds to this time, returning a new time.
       
   840      * The calculation wraps around midnight.
       
   841      * <p>
       
   842      * This instance is immutable and unaffected by this method call.
       
   843      *
       
   844      * @param nanos  the nanos to add, may be negative
       
   845      * @return an {@code OffsetTime} based on this time with the nanoseconds added, not null
       
   846      */
       
   847     public OffsetTime plusNanos(long nanos) {
       
   848         return with(time.plusNanos(nanos), offset);
       
   849     }
       
   850 
       
   851     //-----------------------------------------------------------------------
       
   852     /**
       
   853      * Returns a copy of this time with the specified period subtracted.
       
   854      * <p>
       
   855      * This method returns a new time based on this time with the specified period subtracted.
       
   856      * The subtractor is typically {@link java.time.Period} but may be any other type implementing
       
   857      * the {@link TemporalSubtractor} interface.
       
   858      * The calculation is delegated to the specified adjuster, which typically calls
       
   859      * back to {@link #minus(long, TemporalUnit)}.
       
   860      * The offset is not part of the calculation and will be unchanged in the result.
       
   861      * <p>
       
   862      * This instance is immutable and unaffected by this method call.
       
   863      *
       
   864      * @param subtractor  the subtractor to use, not null
       
   865      * @return an {@code OffsetTime} based on this time with the subtraction made, not null
       
   866      * @throws DateTimeException if the subtraction cannot be made
       
   867      * @throws ArithmeticException if numeric overflow occurs
       
   868      */
       
   869     @Override
       
   870     public OffsetTime minus(TemporalSubtractor subtractor) {
       
   871         return (OffsetTime) subtractor.subtractFrom(this);
       
   872     }
       
   873 
       
   874     /**
       
   875      * Returns a copy of this time with the specified period subtracted.
       
   876      * <p>
       
   877      * This method returns a new time based on this time with the specified period subtracted.
       
   878      * This can be used to subtract any period that is defined by a unit, for example to subtract hours, minutes or seconds.
       
   879      * The unit is responsible for the details of the calculation, including the resolution
       
   880      * of any edge cases in the calculation.
       
   881      * The offset is not part of the calculation and will be unchanged in the result.
       
   882      * <p>
       
   883      * This instance is immutable and unaffected by this method call.
       
   884      *
       
   885      * @param amountToSubtract  the amount of the unit to subtract from the result, may be negative
       
   886      * @param unit  the unit of the period to subtract, not null
       
   887      * @return an {@code OffsetTime} based on this time with the specified period subtracted, not null
       
   888      * @throws DateTimeException if the unit cannot be added to this type
       
   889      */
       
   890     @Override
       
   891     public OffsetTime minus(long amountToSubtract, TemporalUnit unit) {
       
   892         return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit));
       
   893     }
       
   894 
       
   895     //-----------------------------------------------------------------------
       
   896     /**
       
   897      * Returns a copy of this {@code OffsetTime} with the specified period in hours subtracted.
       
   898      * <p>
       
   899      * This subtracts the specified number of hours from this time, returning a new time.
       
   900      * The calculation wraps around midnight.
       
   901      * <p>
       
   902      * This instance is immutable and unaffected by this method call.
       
   903      *
       
   904      * @param hours  the hours to subtract, may be negative
       
   905      * @return an {@code OffsetTime} based on this time with the hours subtracted, not null
       
   906      */
       
   907     public OffsetTime minusHours(long hours) {
       
   908         return with(time.minusHours(hours), offset);
       
   909     }
       
   910 
       
   911     /**
       
   912      * Returns a copy of this {@code OffsetTime} with the specified period in minutes subtracted.
       
   913      * <p>
       
   914      * This subtracts the specified number of minutes from this time, returning a new time.
       
   915      * The calculation wraps around midnight.
       
   916      * <p>
       
   917      * This instance is immutable and unaffected by this method call.
       
   918      *
       
   919      * @param minutes  the minutes to subtract, may be negative
       
   920      * @return an {@code OffsetTime} based on this time with the minutes subtracted, not null
       
   921      */
       
   922     public OffsetTime minusMinutes(long minutes) {
       
   923         return with(time.minusMinutes(minutes), offset);
       
   924     }
       
   925 
       
   926     /**
       
   927      * Returns a copy of this {@code OffsetTime} with the specified period in seconds subtracted.
       
   928      * <p>
       
   929      * This subtracts the specified number of seconds from this time, returning a new time.
       
   930      * The calculation wraps around midnight.
       
   931      * <p>
       
   932      * This instance is immutable and unaffected by this method call.
       
   933      *
       
   934      * @param seconds  the seconds to subtract, may be negative
       
   935      * @return an {@code OffsetTime} based on this time with the seconds subtracted, not null
       
   936      */
       
   937     public OffsetTime minusSeconds(long seconds) {
       
   938         return with(time.minusSeconds(seconds), offset);
       
   939     }
       
   940 
       
   941     /**
       
   942      * Returns a copy of this {@code OffsetTime} with the specified period in nanoseconds subtracted.
       
   943      * <p>
       
   944      * This subtracts the specified number of nanoseconds from this time, returning a new time.
       
   945      * The calculation wraps around midnight.
       
   946      * <p>
       
   947      * This instance is immutable and unaffected by this method call.
       
   948      *
       
   949      * @param nanos  the nanos to subtract, may be negative
       
   950      * @return an {@code OffsetTime} based on this time with the nanoseconds subtracted, not null
       
   951      */
       
   952     public OffsetTime minusNanos(long nanos) {
       
   953         return with(time.minusNanos(nanos), offset);
       
   954     }
       
   955 
       
   956     //-----------------------------------------------------------------------
       
   957     /**
       
   958      * Queries this time using the specified query.
       
   959      * <p>
       
   960      * This queries this time using the specified query strategy object.
       
   961      * The {@code TemporalQuery} object defines the logic to be used to
       
   962      * obtain the result. Read the documentation of the query to understand
       
   963      * what the result of this method will be.
       
   964      * <p>
       
   965      * The result of this method is obtained by invoking the
       
   966      * {@link TemporalQuery#queryFrom(TemporalAccessor)} method on the
       
   967      * specified query passing {@code this} as the argument.
       
   968      *
       
   969      * @param <R> the type of the result
       
   970      * @param query  the query to invoke, not null
       
   971      * @return the query result, null may be returned (defined by the query)
       
   972      * @throws DateTimeException if unable to query (defined by the query)
       
   973      * @throws ArithmeticException if numeric overflow occurs (defined by the query)
       
   974      */
       
   975     @SuppressWarnings("unchecked")
       
   976     @Override
       
   977     public <R> R query(TemporalQuery<R> query) {
       
   978         if (query == Queries.precision()) {
       
   979             return (R) NANOS;
       
   980         } else if (query == Queries.offset() || query == Queries.zone()) {
       
   981             return (R) getOffset();
       
   982         }
       
   983         return Temporal.super.query(query);
       
   984     }
       
   985 
       
   986     /**
       
   987      * Adjusts the specified temporal object to have the same offset and time
       
   988      * as this object.
       
   989      * <p>
       
   990      * This returns a temporal object of the same observable type as the input
       
   991      * with the offset and time changed to be the same as this.
       
   992      * <p>
       
   993      * The adjustment is equivalent to using {@link Temporal#with(TemporalField, long)}
       
   994      * twice, passing {@link ChronoField#OFFSET_SECONDS} and
       
   995      * {@link ChronoField#NANO_OF_DAY} as the fields.
       
   996      * <p>
       
   997      * In most cases, it is clearer to reverse the calling pattern by using
       
   998      * {@link Temporal#with(TemporalAdjuster)}:
       
   999      * <pre>
       
  1000      *   // these two lines are equivalent, but the second approach is recommended
       
  1001      *   temporal = thisOffsetTime.adjustInto(temporal);
       
  1002      *   temporal = temporal.with(thisOffsetTime);
       
  1003      * </pre>
       
  1004      * <p>
       
  1005      * This instance is immutable and unaffected by this method call.
       
  1006      *
       
  1007      * @param temporal  the target object to be adjusted, not null
       
  1008      * @return the adjusted object, not null
       
  1009      * @throws DateTimeException if unable to make the adjustment
       
  1010      * @throws ArithmeticException if numeric overflow occurs
       
  1011      */
       
  1012     @Override
       
  1013     public Temporal adjustInto(Temporal temporal) {
       
  1014         return temporal
       
  1015                 .with(OFFSET_SECONDS, getOffset().getTotalSeconds())
       
  1016                 .with(NANO_OF_DAY, time.toNanoOfDay());
       
  1017     }
       
  1018 
       
  1019     /**
       
  1020      * Calculates the period between this time and another time in
       
  1021      * terms of the specified unit.
       
  1022      * <p>
       
  1023      * This calculates the period between two times in terms of a single unit.
       
  1024      * The start and end points are {@code this} and the specified time.
       
  1025      * The result will be negative if the end is before the start.
       
  1026      * For example, the period in hours between two times can be calculated
       
  1027      * using {@code startTime.periodUntil(endTime, HOURS)}.
       
  1028      * <p>
       
  1029      * The {@code Temporal} passed to this method must be an {@code OffsetTime}.
       
  1030      * If the offset differs between the two times, then the specified
       
  1031      * end time is normalized to have the same offset as this time.
       
  1032      * <p>
       
  1033      * The calculation returns a whole number, representing the number of
       
  1034      * complete units between the two times.
       
  1035      * For example, the period in hours between 11:30Z and 13:29Z will only
       
  1036      * be one hour as it is one minute short of two hours.
       
  1037      * <p>
       
  1038      * This method operates in association with {@link TemporalUnit#between}.
       
  1039      * The result of this method is a {@code long} representing the amount of
       
  1040      * the specified unit. By contrast, the result of {@code between} is an
       
  1041      * object that can be used directly in addition/subtraction:
       
  1042      * <pre>
       
  1043      *   long period = start.periodUntil(end, HOURS);   // this method
       
  1044      *   dateTime.plus(HOURS.between(start, end));      // use in plus/minus
       
  1045      * </pre>
       
  1046      * <p>
       
  1047      * The calculation is implemented in this method for {@link ChronoUnit}.
       
  1048      * The units {@code NANOS}, {@code MICROS}, {@code MILLIS}, {@code SECONDS},
       
  1049      * {@code MINUTES}, {@code HOURS} and {@code HALF_DAYS} are supported.
       
  1050      * Other {@code ChronoUnit} values will throw an exception.
       
  1051      * <p>
       
  1052      * If the unit is not a {@code ChronoUnit}, then the result of this method
       
  1053      * is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)}
       
  1054      * passing {@code this} as the first argument and the input temporal as
       
  1055      * the second argument.
       
  1056      * <p>
       
  1057      * This instance is immutable and unaffected by this method call.
       
  1058      *
       
  1059      * @param endTime  the end time, which must be an {@code OffsetTime}, not null
       
  1060      * @param unit  the unit to measure the period in, not null
       
  1061      * @return the amount of the period between this time and the end time
       
  1062      * @throws DateTimeException if the period cannot be calculated
       
  1063      * @throws ArithmeticException if numeric overflow occurs
       
  1064      */
       
  1065     @Override
       
  1066     public long periodUntil(Temporal endTime, TemporalUnit unit) {
       
  1067         if (endTime instanceof OffsetTime == false) {
       
  1068             Objects.requireNonNull(endTime, "endTime");
       
  1069             throw new DateTimeException("Unable to calculate period between objects of two different types");
       
  1070         }
       
  1071         if (unit instanceof ChronoUnit) {
       
  1072             OffsetTime end = (OffsetTime) endTime;
       
  1073             long nanosUntil = end.toEpochNano() - toEpochNano();  // no overflow
       
  1074             switch ((ChronoUnit) unit) {
       
  1075                 case NANOS: return nanosUntil;
       
  1076                 case MICROS: return nanosUntil / 1000;
       
  1077                 case MILLIS: return nanosUntil / 1000_000;
       
  1078                 case SECONDS: return nanosUntil / NANOS_PER_SECOND;
       
  1079                 case MINUTES: return nanosUntil / NANOS_PER_MINUTE;
       
  1080                 case HOURS: return nanosUntil / NANOS_PER_HOUR;
       
  1081                 case HALF_DAYS: return nanosUntil / (12 * NANOS_PER_HOUR);
       
  1082             }
       
  1083             throw new DateTimeException("Unsupported unit: " + unit.getName());
       
  1084         }
       
  1085         return unit.between(this, endTime).getAmount();
       
  1086     }
       
  1087 
       
  1088     //-----------------------------------------------------------------------
       
  1089     /**
       
  1090      * Returns an offset date-time formed from this time at the specified date.
       
  1091      * <p>
       
  1092      * This combines this time with the specified date to form an {@code OffsetDateTime}.
       
  1093      * All possible combinations of date and time are valid.
       
  1094      * <p>
       
  1095      * This instance is immutable and unaffected by this method call.
       
  1096      *
       
  1097      * @param date  the date to combine with, not null
       
  1098      * @return the offset date-time formed from this time and the specified date, not null
       
  1099      */
       
  1100     public OffsetDateTime atDate(LocalDate date) {
       
  1101         return OffsetDateTime.of(date, time, offset);
       
  1102     }
       
  1103 
       
  1104     //-----------------------------------------------------------------------
       
  1105     /**
       
  1106      * Converts this time to epoch nanos based on 1970-01-01Z.
       
  1107      *
       
  1108      * @return the epoch nanos value
       
  1109      */
       
  1110     private long toEpochNano() {
       
  1111         long nod = time.toNanoOfDay();
       
  1112         long offsetNanos = offset.getTotalSeconds() * NANOS_PER_SECOND;
       
  1113         return nod - offsetNanos;
       
  1114     }
       
  1115 
       
  1116     //-----------------------------------------------------------------------
       
  1117     /**
       
  1118      * Compares this {@code OffsetTime} to another time.
       
  1119      * <p>
       
  1120      * The comparison is based first on the UTC equivalent instant, then on the local time.
       
  1121      * It is "consistent with equals", as defined by {@link Comparable}.
       
  1122      * <p>
       
  1123      * For example, the following is the comparator order:
       
  1124      * <ol>
       
  1125      * <li>{@code 10:30+01:00}</li>
       
  1126      * <li>{@code 11:00+01:00}</li>
       
  1127      * <li>{@code 12:00+02:00}</li>
       
  1128      * <li>{@code 11:30+01:00}</li>
       
  1129      * <li>{@code 12:00+01:00}</li>
       
  1130      * <li>{@code 12:30+01:00}</li>
       
  1131      * </ol>
       
  1132      * Values #2 and #3 represent the same instant on the time-line.
       
  1133      * When two values represent the same instant, the local time is compared
       
  1134      * to distinguish them. This step is needed to make the ordering
       
  1135      * consistent with {@code equals()}.
       
  1136      * <p>
       
  1137      * To compare the underlying local time of two {@code TemporalAccessor} instances,
       
  1138      * use {@link ChronoField#NANO_OF_DAY} as a comparator.
       
  1139      *
       
  1140      * @param other  the other time to compare to, not null
       
  1141      * @return the comparator value, negative if less, positive if greater
       
  1142      * @throws NullPointerException if {@code other} is null
       
  1143      */
       
  1144     @Override
       
  1145     public int compareTo(OffsetTime other) {
       
  1146         if (offset.equals(other.offset)) {
       
  1147             return time.compareTo(other.time);
       
  1148         }
       
  1149         int compare = Long.compare(toEpochNano(), other.toEpochNano());
       
  1150         if (compare == 0) {
       
  1151             compare = time.compareTo(other.time);
       
  1152         }
       
  1153         return compare;
       
  1154     }
       
  1155 
       
  1156     //-----------------------------------------------------------------------
       
  1157     /**
       
  1158      * Checks if the instant of this {@code OffsetTime} is after that of the
       
  1159      * specified time applying both times to a common date.
       
  1160      * <p>
       
  1161      * This method differs from the comparison in {@link #compareTo} in that it
       
  1162      * only compares the instant of the time. This is equivalent to converting both
       
  1163      * times to an instant using the same date and comparing the instants.
       
  1164      *
       
  1165      * @param other  the other time to compare to, not null
       
  1166      * @return true if this is after the instant of the specified time
       
  1167      */
       
  1168     public boolean isAfter(OffsetTime other) {
       
  1169         return toEpochNano() > other.toEpochNano();
       
  1170     }
       
  1171 
       
  1172     /**
       
  1173      * Checks if the instant of this {@code OffsetTime} is before that of the
       
  1174      * specified time applying both times to a common date.
       
  1175      * <p>
       
  1176      * This method differs from the comparison in {@link #compareTo} in that it
       
  1177      * only compares the instant of the time. This is equivalent to converting both
       
  1178      * times to an instant using the same date and comparing the instants.
       
  1179      *
       
  1180      * @param other  the other time to compare to, not null
       
  1181      * @return true if this is before the instant of the specified time
       
  1182      */
       
  1183     public boolean isBefore(OffsetTime other) {
       
  1184         return toEpochNano() < other.toEpochNano();
       
  1185     }
       
  1186 
       
  1187     /**
       
  1188      * Checks if the instant of this {@code OffsetTime} is equal to that of the
       
  1189      * specified time applying both times to a common date.
       
  1190      * <p>
       
  1191      * This method differs from the comparison in {@link #compareTo} and {@link #equals}
       
  1192      * in that it only compares the instant of the time. This is equivalent to converting both
       
  1193      * times to an instant using the same date and comparing the instants.
       
  1194      *
       
  1195      * @param other  the other time to compare to, not null
       
  1196      * @return true if this is equal to the instant of the specified time
       
  1197      */
       
  1198     public boolean isEqual(OffsetTime other) {
       
  1199         return toEpochNano() == other.toEpochNano();
       
  1200     }
       
  1201 
       
  1202     //-----------------------------------------------------------------------
       
  1203     /**
       
  1204      * Checks if this time is equal to another time.
       
  1205      * <p>
       
  1206      * The comparison is based on the local-time and the offset.
       
  1207      * To compare for the same instant on the time-line, use {@link #isEqual(OffsetTime)}.
       
  1208      * <p>
       
  1209      * Only objects of type {@code OffsetTime} are compared, other types return false.
       
  1210      * To compare the underlying local time of two {@code TemporalAccessor} instances,
       
  1211      * use {@link ChronoField#NANO_OF_DAY} as a comparator.
       
  1212      *
       
  1213      * @param obj  the object to check, null returns false
       
  1214      * @return true if this is equal to the other time
       
  1215      */
       
  1216     @Override
       
  1217     public boolean equals(Object obj) {
       
  1218         if (this == obj) {
       
  1219             return true;
       
  1220         }
       
  1221         if (obj instanceof OffsetTime) {
       
  1222             OffsetTime other = (OffsetTime) obj;
       
  1223             return time.equals(other.time) && offset.equals(other.offset);
       
  1224         }
       
  1225         return false;
       
  1226     }
       
  1227 
       
  1228     /**
       
  1229      * A hash code for this time.
       
  1230      *
       
  1231      * @return a suitable hash code
       
  1232      */
       
  1233     @Override
       
  1234     public int hashCode() {
       
  1235         return time.hashCode() ^ offset.hashCode();
       
  1236     }
       
  1237 
       
  1238     //-----------------------------------------------------------------------
       
  1239     /**
       
  1240      * Outputs this time as a {@code String}, such as {@code 10:15:30+01:00}.
       
  1241      * <p>
       
  1242      * The output will be one of the following ISO-8601 formats:
       
  1243      * <p><ul>
       
  1244      * <li>{@code HH:mmXXXXX}</li>
       
  1245      * <li>{@code HH:mm:ssXXXXX}</li>
       
  1246      * <li>{@code HH:mm:ss.SSSXXXXX}</li>
       
  1247      * <li>{@code HH:mm:ss.SSSSSSXXXXX}</li>
       
  1248      * <li>{@code HH:mm:ss.SSSSSSSSSXXXXX}</li>
       
  1249      * </ul><p>
       
  1250      * The format used will be the shortest that outputs the full value of
       
  1251      * the time where the omitted parts are implied to be zero.
       
  1252      *
       
  1253      * @return a string representation of this time, not null
       
  1254      */
       
  1255     @Override
       
  1256     public String toString() {
       
  1257         return time.toString() + offset.toString();
       
  1258     }
       
  1259 
       
  1260     /**
       
  1261      * Outputs this time as a {@code String} using the formatter.
       
  1262      * <p>
       
  1263      * This time will be passed to the formatter
       
  1264      * {@link DateTimeFormatter#print(TemporalAccessor) print method}.
       
  1265      *
       
  1266      * @param formatter  the formatter to use, not null
       
  1267      * @return the formatted time string, not null
       
  1268      * @throws DateTimeException if an error occurs during printing
       
  1269      */
       
  1270     public String toString(DateTimeFormatter formatter) {
       
  1271         Objects.requireNonNull(formatter, "formatter");
       
  1272         return formatter.print(this);
       
  1273     }
       
  1274 
       
  1275     // -----------------------------------------------------------------------
       
  1276     /**
       
  1277      * Writes the object using a
       
  1278      * <a href="../../../serialized-form.html#java.time.temporal.Ser">dedicated serialized form</a>.
       
  1279      * <pre>
       
  1280      *  out.writeByte(2);  // identifies this as a OffsetDateTime
       
  1281      *  out.writeObject(time);
       
  1282      *  out.writeObject(offset);
       
  1283      * </pre>
       
  1284      *
       
  1285      * @return the instance of {@code Ser}, not null
       
  1286      */
       
  1287     private Object writeReplace() {
       
  1288         return new Ser(Ser.OFFSET_TIME_TYPE, this);
       
  1289     }
       
  1290 
       
  1291     /**
       
  1292      * Defend against malicious streams.
       
  1293      * @return never
       
  1294      * @throws InvalidObjectException always
       
  1295      */
       
  1296     private Object readResolve() throws ObjectStreamException {
       
  1297         throw new InvalidObjectException("Deserialization via serialization delegate");
       
  1298     }
       
  1299 
       
  1300     void writeExternal(ObjectOutput out) throws IOException {
       
  1301         out.writeObject(time);
       
  1302         out.writeObject(offset);
       
  1303     }
       
  1304 
       
  1305     static OffsetTime readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
       
  1306         LocalTime time = (LocalTime) in.readObject();
       
  1307         ZoneOffset offset = (ZoneOffset) in.readObject();
       
  1308         return OffsetTime.of(time, offset);
       
  1309     }
       
  1310 
       
  1311 }