Home | History | Annotate | Download | only in time
      1 /*
      2  * Copyright (c) 2012, 2015, 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;
     63 
     64 import static java.time.temporal.ChronoField.HOUR_OF_DAY;
     65 import static java.time.temporal.ChronoField.MICRO_OF_DAY;
     66 import static java.time.temporal.ChronoField.MINUTE_OF_HOUR;
     67 import static java.time.temporal.ChronoField.NANO_OF_DAY;
     68 import static java.time.temporal.ChronoField.NANO_OF_SECOND;
     69 import static java.time.temporal.ChronoField.SECOND_OF_DAY;
     70 import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
     71 import static java.time.temporal.ChronoUnit.NANOS;
     72 
     73 import java.io.DataInput;
     74 import java.io.DataOutput;
     75 import java.io.IOException;
     76 import java.io.InvalidObjectException;
     77 import java.io.ObjectInputStream;
     78 import java.io.Serializable;
     79 import java.time.format.DateTimeFormatter;
     80 import java.time.format.DateTimeParseException;
     81 import java.time.temporal.ChronoField;
     82 import java.time.temporal.ChronoUnit;
     83 import java.time.temporal.Temporal;
     84 import java.time.temporal.TemporalAccessor;
     85 import java.time.temporal.TemporalAdjuster;
     86 import java.time.temporal.TemporalAmount;
     87 import java.time.temporal.TemporalField;
     88 import java.time.temporal.TemporalQueries;
     89 import java.time.temporal.TemporalQuery;
     90 import java.time.temporal.TemporalUnit;
     91 import java.time.temporal.UnsupportedTemporalTypeException;
     92 import java.time.temporal.ValueRange;
     93 import java.util.Objects;
     94 
     95 // Android-changed: removed ValueBased paragraph.
     96 /**
     97  * A time without a time-zone in the ISO-8601 calendar system,
     98  * such as {@code 10:15:30}.
     99  * <p>
    100  * {@code LocalTime} is an immutable date-time object that represents a time,
    101  * often viewed as hour-minute-second.
    102  * Time is represented to nanosecond precision.
    103  * For example, the value "13:45.30.123456789" can be stored in a {@code LocalTime}.
    104  * <p>
    105  * This class does not store or represent a date or time-zone.
    106  * Instead, it is a description of the local time as seen on a wall clock.
    107  * It cannot represent an instant on the time-line without additional information
    108  * such as an offset or time-zone.
    109  * <p>
    110  * The ISO-8601 calendar system is the modern civil calendar system used today
    111  * in most of the world. This API assumes that all calendar systems use the same
    112  * representation, this class, for time-of-day.
    113  *
    114  * @implSpec
    115  * This class is immutable and thread-safe.
    116  *
    117  * @since 1.8
    118  */
    119 public final class LocalTime
    120         implements Temporal, TemporalAdjuster, Comparable<LocalTime>, Serializable {
    121 
    122     /**
    123      * The minimum supported {@code LocalTime}, '00:00'.
    124      * This is the time of midnight at the start of the day.
    125      */
    126     public static final LocalTime MIN;
    127     /**
    128      * The maximum supported {@code LocalTime}, '23:59:59.999999999'.
    129      * This is the time just before midnight at the end of the day.
    130      */
    131     public static final LocalTime MAX;
    132     /**
    133      * The time of midnight at the start of the day, '00:00'.
    134      */
    135     public static final LocalTime MIDNIGHT;
    136     /**
    137      * The time of noon in the middle of the day, '12:00'.
    138      */
    139     public static final LocalTime NOON;
    140     /**
    141      * Constants for the local time of each hour.
    142      */
    143     private static final LocalTime[] HOURS = new LocalTime[24];
    144     static {
    145         for (int i = 0; i < HOURS.length; i++) {
    146             HOURS[i] = new LocalTime(i, 0, 0, 0);
    147         }
    148         MIDNIGHT = HOURS[0];
    149         NOON = HOURS[12];
    150         MIN = HOURS[0];
    151         MAX = new LocalTime(23, 59, 59, 999_999_999);
    152     }
    153 
    154     /**
    155      * Hours per day.
    156      */
    157     static final int HOURS_PER_DAY = 24;
    158     /**
    159      * Minutes per hour.
    160      */
    161     static final int MINUTES_PER_HOUR = 60;
    162     /**
    163      * Minutes per day.
    164      */
    165     static final int MINUTES_PER_DAY = MINUTES_PER_HOUR * HOURS_PER_DAY;
    166     /**
    167      * Seconds per minute.
    168      */
    169     static final int SECONDS_PER_MINUTE = 60;
    170     /**
    171      * Seconds per hour.
    172      */
    173     static final int SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR;
    174     /**
    175      * Seconds per day.
    176      */
    177     static final int SECONDS_PER_DAY = SECONDS_PER_HOUR * HOURS_PER_DAY;
    178     /**
    179      * Milliseconds per day.
    180      */
    181     static final long MILLIS_PER_DAY = SECONDS_PER_DAY * 1000L;
    182     /**
    183      * Microseconds per day.
    184      */
    185     static final long MICROS_PER_DAY = SECONDS_PER_DAY * 1000_000L;
    186     /**
    187      * Nanos per second.
    188      */
    189     static final long NANOS_PER_SECOND = 1000_000_000L;
    190     /**
    191      * Nanos per minute.
    192      */
    193     static final long NANOS_PER_MINUTE = NANOS_PER_SECOND * SECONDS_PER_MINUTE;
    194     /**
    195      * Nanos per hour.
    196      */
    197     static final long NANOS_PER_HOUR = NANOS_PER_MINUTE * MINUTES_PER_HOUR;
    198     /**
    199      * Nanos per day.
    200      */
    201     static final long NANOS_PER_DAY = NANOS_PER_HOUR * HOURS_PER_DAY;
    202 
    203     /**
    204      * Serialization version.
    205      */
    206     private static final long serialVersionUID = 6414437269572265201L;
    207 
    208     /**
    209      * The hour.
    210      */
    211     private final byte hour;
    212     /**
    213      * The minute.
    214      */
    215     private final byte minute;
    216     /**
    217      * The second.
    218      */
    219     private final byte second;
    220     /**
    221      * The nanosecond.
    222      */
    223     private final int nano;
    224 
    225     //-----------------------------------------------------------------------
    226     /**
    227      * Obtains the current time from the system clock in the default time-zone.
    228      * <p>
    229      * This will query the {@link Clock#systemDefaultZone() system clock} in the default
    230      * time-zone to obtain the current time.
    231      * <p>
    232      * Using this method will prevent the ability to use an alternate clock for testing
    233      * because the clock is hard-coded.
    234      *
    235      * @return the current time using the system clock and default time-zone, not null
    236      */
    237     public static LocalTime now() {
    238         return now(Clock.systemDefaultZone());
    239     }
    240 
    241     /**
    242      * Obtains the current time from the system clock in the specified time-zone.
    243      * <p>
    244      * This will query the {@link Clock#system(ZoneId) system clock} to obtain the current time.
    245      * Specifying the time-zone avoids dependence on the default time-zone.
    246      * <p>
    247      * Using this method will prevent the ability to use an alternate clock for testing
    248      * because the clock is hard-coded.
    249      *
    250      * @param zone  the zone ID to use, not null
    251      * @return the current time using the system clock, not null
    252      */
    253     public static LocalTime now(ZoneId zone) {
    254         return now(Clock.system(zone));
    255     }
    256 
    257     /**
    258      * Obtains the current time from the specified clock.
    259      * <p>
    260      * This will query the specified clock to obtain the current time.
    261      * Using this method allows the use of an alternate clock for testing.
    262      * The alternate clock may be introduced using {@link Clock dependency injection}.
    263      *
    264      * @param clock  the clock to use, not null
    265      * @return the current time, not null
    266      */
    267     public static LocalTime now(Clock clock) {
    268         Objects.requireNonNull(clock, "clock");
    269         // inline OffsetTime factory to avoid creating object and InstantProvider checks
    270         final Instant now = clock.instant();  // called once
    271         ZoneOffset offset = clock.getZone().getRules().getOffset(now);
    272         long localSecond = now.getEpochSecond() + offset.getTotalSeconds();  // overflow caught later
    273         int secsOfDay = (int) Math.floorMod(localSecond, SECONDS_PER_DAY);
    274         return ofNanoOfDay(secsOfDay * NANOS_PER_SECOND + now.getNano());
    275     }
    276 
    277     //-----------------------------------------------------------------------
    278     /**
    279      * Obtains an instance of {@code LocalTime} from an hour and minute.
    280      * <p>
    281      * This returns a {@code LocalTime} with the specified hour and minute.
    282      * The second and nanosecond fields will be set to zero.
    283      *
    284      * @param hour  the hour-of-day to represent, from 0 to 23
    285      * @param minute  the minute-of-hour to represent, from 0 to 59
    286      * @return the local time, not null
    287      * @throws DateTimeException if the value of any field is out of range
    288      */
    289     public static LocalTime of(int hour, int minute) {
    290         HOUR_OF_DAY.checkValidValue(hour);
    291         if (minute == 0) {
    292             return HOURS[hour];  // for performance
    293         }
    294         MINUTE_OF_HOUR.checkValidValue(minute);
    295         return new LocalTime(hour, minute, 0, 0);
    296     }
    297 
    298     /**
    299      * Obtains an instance of {@code LocalTime} from an hour, minute and second.
    300      * <p>
    301      * This returns a {@code LocalTime} with the specified hour, minute and second.
    302      * The nanosecond field will be set to zero.
    303      *
    304      * @param hour  the hour-of-day to represent, from 0 to 23
    305      * @param minute  the minute-of-hour to represent, from 0 to 59
    306      * @param second  the second-of-minute to represent, from 0 to 59
    307      * @return the local time, not null
    308      * @throws DateTimeException if the value of any field is out of range
    309      */
    310     public static LocalTime of(int hour, int minute, int second) {
    311         HOUR_OF_DAY.checkValidValue(hour);
    312         if ((minute | second) == 0) {
    313             return HOURS[hour];  // for performance
    314         }
    315         MINUTE_OF_HOUR.checkValidValue(minute);
    316         SECOND_OF_MINUTE.checkValidValue(second);
    317         return new LocalTime(hour, minute, second, 0);
    318     }
    319 
    320     /**
    321      * Obtains an instance of {@code LocalTime} from an hour, minute, second and nanosecond.
    322      * <p>
    323      * This returns a {@code LocalTime} with the specified hour, minute, second and nanosecond.
    324      *
    325      * @param hour  the hour-of-day to represent, from 0 to 23
    326      * @param minute  the minute-of-hour to represent, from 0 to 59
    327      * @param second  the second-of-minute to represent, from 0 to 59
    328      * @param nanoOfSecond  the nano-of-second to represent, from 0 to 999,999,999
    329      * @return the local time, not null
    330      * @throws DateTimeException if the value of any field is out of range
    331      */
    332     public static LocalTime of(int hour, int minute, int second, int nanoOfSecond) {
    333         HOUR_OF_DAY.checkValidValue(hour);
    334         MINUTE_OF_HOUR.checkValidValue(minute);
    335         SECOND_OF_MINUTE.checkValidValue(second);
    336         NANO_OF_SECOND.checkValidValue(nanoOfSecond);
    337         return create(hour, minute, second, nanoOfSecond);
    338     }
    339 
    340     //-----------------------------------------------------------------------
    341     /**
    342      * Obtains an instance of {@code LocalTime} from a second-of-day value.
    343      * <p>
    344      * This returns a {@code LocalTime} with the specified second-of-day.
    345      * The nanosecond field will be set to zero.
    346      *
    347      * @param secondOfDay  the second-of-day, from {@code 0} to {@code 24 * 60 * 60 - 1}
    348      * @return the local time, not null
    349      * @throws DateTimeException if the second-of-day value is invalid
    350      */
    351     public static LocalTime ofSecondOfDay(long secondOfDay) {
    352         SECOND_OF_DAY.checkValidValue(secondOfDay);
    353         int hours = (int) (secondOfDay / SECONDS_PER_HOUR);
    354         secondOfDay -= hours * SECONDS_PER_HOUR;
    355         int minutes = (int) (secondOfDay / SECONDS_PER_MINUTE);
    356         secondOfDay -= minutes * SECONDS_PER_MINUTE;
    357         return create(hours, minutes, (int) secondOfDay, 0);
    358     }
    359 
    360     /**
    361      * Obtains an instance of {@code LocalTime} from a nanos-of-day value.
    362      * <p>
    363      * This returns a {@code LocalTime} with the specified nanosecond-of-day.
    364      *
    365      * @param nanoOfDay  the nano of day, from {@code 0} to {@code 24 * 60 * 60 * 1,000,000,000 - 1}
    366      * @return the local time, not null
    367      * @throws DateTimeException if the nanos of day value is invalid
    368      */
    369     public static LocalTime ofNanoOfDay(long nanoOfDay) {
    370         NANO_OF_DAY.checkValidValue(nanoOfDay);
    371         int hours = (int) (nanoOfDay / NANOS_PER_HOUR);
    372         nanoOfDay -= hours * NANOS_PER_HOUR;
    373         int minutes = (int) (nanoOfDay / NANOS_PER_MINUTE);
    374         nanoOfDay -= minutes * NANOS_PER_MINUTE;
    375         int seconds = (int) (nanoOfDay / NANOS_PER_SECOND);
    376         nanoOfDay -= seconds * NANOS_PER_SECOND;
    377         return create(hours, minutes, seconds, (int) nanoOfDay);
    378     }
    379 
    380     //-----------------------------------------------------------------------
    381     /**
    382      * Obtains an instance of {@code LocalTime} from a temporal object.
    383      * <p>
    384      * This obtains a local time based on the specified temporal.
    385      * A {@code TemporalAccessor} represents an arbitrary set of date and time information,
    386      * which this factory converts to an instance of {@code LocalTime}.
    387      * <p>
    388      * The conversion uses the {@link TemporalQueries#localTime()} query, which relies
    389      * on extracting the {@link ChronoField#NANO_OF_DAY NANO_OF_DAY} field.
    390      * <p>
    391      * This method matches the signature of the functional interface {@link TemporalQuery}
    392      * allowing it to be used as a query via method reference, {@code LocalTime::from}.
    393      *
    394      * @param temporal  the temporal object to convert, not null
    395      * @return the local time, not null
    396      * @throws DateTimeException if unable to convert to a {@code LocalTime}
    397      */
    398     public static LocalTime from(TemporalAccessor temporal) {
    399         Objects.requireNonNull(temporal, "temporal");
    400         LocalTime time = temporal.query(TemporalQueries.localTime());
    401         if (time == null) {
    402             throw new DateTimeException("Unable to obtain LocalTime from TemporalAccessor: " +
    403                     temporal + " of type " + temporal.getClass().getName());
    404         }
    405         return time;
    406     }
    407 
    408     //-----------------------------------------------------------------------
    409     /**
    410      * Obtains an instance of {@code LocalTime} from a text string such as {@code 10:15}.
    411      * <p>
    412      * The string must represent a valid time and is parsed using
    413      * {@link java.time.format.DateTimeFormatter#ISO_LOCAL_TIME}.
    414      *
    415      * @param text  the text to parse such as "10:15:30", not null
    416      * @return the parsed local time, not null
    417      * @throws DateTimeParseException if the text cannot be parsed
    418      */
    419     public static LocalTime parse(CharSequence text) {
    420         return parse(text, DateTimeFormatter.ISO_LOCAL_TIME);
    421     }
    422 
    423     /**
    424      * Obtains an instance of {@code LocalTime} from a text string using a specific formatter.
    425      * <p>
    426      * The text is parsed using the formatter, returning a time.
    427      *
    428      * @param text  the text to parse, not null
    429      * @param formatter  the formatter to use, not null
    430      * @return the parsed local time, not null
    431      * @throws DateTimeParseException if the text cannot be parsed
    432      */
    433     public static LocalTime parse(CharSequence text, DateTimeFormatter formatter) {
    434         Objects.requireNonNull(formatter, "formatter");
    435         return formatter.parse(text, LocalTime::from);
    436     }
    437 
    438     //-----------------------------------------------------------------------
    439     /**
    440      * Creates a local time from the hour, minute, second and nanosecond fields.
    441      * <p>
    442      * This factory may return a cached value, but applications must not rely on this.
    443      *
    444      * @param hour  the hour-of-day to represent, validated from 0 to 23
    445      * @param minute  the minute-of-hour to represent, validated from 0 to 59
    446      * @param second  the second-of-minute to represent, validated from 0 to 59
    447      * @param nanoOfSecond  the nano-of-second to represent, validated from 0 to 999,999,999
    448      * @return the local time, not null
    449      */
    450     private static LocalTime create(int hour, int minute, int second, int nanoOfSecond) {
    451         if ((minute | second | nanoOfSecond) == 0) {
    452             return HOURS[hour];
    453         }
    454         return new LocalTime(hour, minute, second, nanoOfSecond);
    455     }
    456 
    457     /**
    458      * Constructor, previously validated.
    459      *
    460      * @param hour  the hour-of-day to represent, validated from 0 to 23
    461      * @param minute  the minute-of-hour to represent, validated from 0 to 59
    462      * @param second  the second-of-minute to represent, validated from 0 to 59
    463      * @param nanoOfSecond  the nano-of-second to represent, validated from 0 to 999,999,999
    464      */
    465     private LocalTime(int hour, int minute, int second, int nanoOfSecond) {
    466         this.hour = (byte) hour;
    467         this.minute = (byte) minute;
    468         this.second = (byte) second;
    469         this.nano = nanoOfSecond;
    470     }
    471 
    472     //-----------------------------------------------------------------------
    473     /**
    474      * Checks if the specified field is supported.
    475      * <p>
    476      * This checks if this time can be queried for the specified field.
    477      * If false, then calling the {@link #range(TemporalField) range},
    478      * {@link #get(TemporalField) get} and {@link #with(TemporalField, long)}
    479      * methods will throw an exception.
    480      * <p>
    481      * If the field is a {@link ChronoField} then the query is implemented here.
    482      * The supported fields are:
    483      * <ul>
    484      * <li>{@code NANO_OF_SECOND}
    485      * <li>{@code NANO_OF_DAY}
    486      * <li>{@code MICRO_OF_SECOND}
    487      * <li>{@code MICRO_OF_DAY}
    488      * <li>{@code MILLI_OF_SECOND}
    489      * <li>{@code MILLI_OF_DAY}
    490      * <li>{@code SECOND_OF_MINUTE}
    491      * <li>{@code SECOND_OF_DAY}
    492      * <li>{@code MINUTE_OF_HOUR}
    493      * <li>{@code MINUTE_OF_DAY}
    494      * <li>{@code HOUR_OF_AMPM}
    495      * <li>{@code CLOCK_HOUR_OF_AMPM}
    496      * <li>{@code HOUR_OF_DAY}
    497      * <li>{@code CLOCK_HOUR_OF_DAY}
    498      * <li>{@code AMPM_OF_DAY}
    499      * </ul>
    500      * All other {@code ChronoField} instances will return false.
    501      * <p>
    502      * If the field is not a {@code ChronoField}, then the result of this method
    503      * is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}
    504      * passing {@code this} as the argument.
    505      * Whether the field is supported is determined by the field.
    506      *
    507      * @param field  the field to check, null returns false
    508      * @return true if the field is supported on this time, false if not
    509      */
    510     @Override
    511     public boolean isSupported(TemporalField field) {
    512         if (field instanceof ChronoField) {
    513             return field.isTimeBased();
    514         }
    515         return field != null && field.isSupportedBy(this);
    516     }
    517 
    518     /**
    519      * Checks if the specified unit is supported.
    520      * <p>
    521      * This checks if the specified unit can be added to, or subtracted from, this time.
    522      * If false, then calling the {@link #plus(long, TemporalUnit)} and
    523      * {@link #minus(long, TemporalUnit) minus} methods will throw an exception.
    524      * <p>
    525      * If the unit is a {@link ChronoUnit} then the query is implemented here.
    526      * The supported units are:
    527      * <ul>
    528      * <li>{@code NANOS}
    529      * <li>{@code MICROS}
    530      * <li>{@code MILLIS}
    531      * <li>{@code SECONDS}
    532      * <li>{@code MINUTES}
    533      * <li>{@code HOURS}
    534      * <li>{@code HALF_DAYS}
    535      * </ul>
    536      * All other {@code ChronoUnit} instances will return false.
    537      * <p>
    538      * If the unit is not a {@code ChronoUnit}, then the result of this method
    539      * is obtained by invoking {@code TemporalUnit.isSupportedBy(Temporal)}
    540      * passing {@code this} as the argument.
    541      * Whether the unit is supported is determined by the unit.
    542      *
    543      * @param unit  the unit to check, null returns false
    544      * @return true if the unit can be added/subtracted, false if not
    545      */
    546     @Override  // override for Javadoc
    547     public boolean isSupported(TemporalUnit unit) {
    548         if (unit instanceof ChronoUnit) {
    549             return unit.isTimeBased();
    550         }
    551         return unit != null && unit.isSupportedBy(this);
    552     }
    553 
    554     //-----------------------------------------------------------------------
    555     /**
    556      * Gets the range of valid values for the specified field.
    557      * <p>
    558      * The range object expresses the minimum and maximum valid values for a field.
    559      * This time is used to enhance the accuracy of the returned range.
    560      * If it is not possible to return the range, because the field is not supported
    561      * or for some other reason, an exception is thrown.
    562      * <p>
    563      * If the field is a {@link ChronoField} then the query is implemented here.
    564      * The {@link #isSupported(TemporalField) supported fields} will return
    565      * appropriate range instances.
    566      * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
    567      * <p>
    568      * If the field is not a {@code ChronoField}, then the result of this method
    569      * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
    570      * passing {@code this} as the argument.
    571      * Whether the range can be obtained is determined by the field.
    572      *
    573      * @param field  the field to query the range for, not null
    574      * @return the range of valid values for the field, not null
    575      * @throws DateTimeException if the range for the field cannot be obtained
    576      * @throws UnsupportedTemporalTypeException if the field is not supported
    577      */
    578     @Override  // override for Javadoc
    579     public ValueRange range(TemporalField field) {
    580         return Temporal.super.range(field);
    581     }
    582 
    583     /**
    584      * Gets the value of the specified field from this time as an {@code int}.
    585      * <p>
    586      * This queries this time for the value of the specified field.
    587      * The returned value will always be within the valid range of values for the field.
    588      * If it is not possible to return the value, because the field is not supported
    589      * or for some other reason, an exception is thrown.
    590      * <p>
    591      * If the field is a {@link ChronoField} then the query is implemented here.
    592      * The {@link #isSupported(TemporalField) supported fields} will return valid
    593      * values based on this time, except {@code NANO_OF_DAY} and {@code MICRO_OF_DAY}
    594      * which are too large to fit in an {@code int} and throw a {@code DateTimeException}.
    595      * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
    596      * <p>
    597      * If the field is not a {@code ChronoField}, then the result of this method
    598      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
    599      * passing {@code this} as the argument. Whether the value can be obtained,
    600      * and what the value represents, is determined by the field.
    601      *
    602      * @param field  the field to get, not null
    603      * @return the value for the field
    604      * @throws DateTimeException if a value for the field cannot be obtained or
    605      *         the value is outside the range of valid values for the field
    606      * @throws UnsupportedTemporalTypeException if the field is not supported or
    607      *         the range of values exceeds an {@code int}
    608      * @throws ArithmeticException if numeric overflow occurs
    609      */
    610     @Override  // override for Javadoc and performance
    611     public int get(TemporalField field) {
    612         if (field instanceof ChronoField) {
    613             return get0(field);
    614         }
    615         return Temporal.super.get(field);
    616     }
    617 
    618     /**
    619      * Gets the value of the specified field from this time as a {@code long}.
    620      * <p>
    621      * This queries this time for the value of the specified field.
    622      * If it is not possible to return the value, because the field is not supported
    623      * or for some other reason, an exception is thrown.
    624      * <p>
    625      * If the field is a {@link ChronoField} then the query is implemented here.
    626      * The {@link #isSupported(TemporalField) supported fields} will return valid
    627      * values based on this time.
    628      * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
    629      * <p>
    630      * If the field is not a {@code ChronoField}, then the result of this method
    631      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
    632      * passing {@code this} as the argument. Whether the value can be obtained,
    633      * and what the value represents, is determined by the field.
    634      *
    635      * @param field  the field to get, not null
    636      * @return the value for the field
    637      * @throws DateTimeException if a value for the field cannot be obtained
    638      * @throws UnsupportedTemporalTypeException if the field is not supported
    639      * @throws ArithmeticException if numeric overflow occurs
    640      */
    641     @Override
    642     public long getLong(TemporalField field) {
    643         if (field instanceof ChronoField) {
    644             if (field == NANO_OF_DAY) {
    645                 return toNanoOfDay();
    646             }
    647             if (field == MICRO_OF_DAY) {
    648                 return toNanoOfDay() / 1000;
    649             }
    650             return get0(field);
    651         }
    652         return field.getFrom(this);
    653     }
    654 
    655     private int get0(TemporalField field) {
    656         switch ((ChronoField) field) {
    657             case NANO_OF_SECOND: return nano;
    658             case NANO_OF_DAY: throw new UnsupportedTemporalTypeException("Invalid field 'NanoOfDay' for get() method, use getLong() instead");
    659             case MICRO_OF_SECOND: return nano / 1000;
    660             case MICRO_OF_DAY: throw new UnsupportedTemporalTypeException("Invalid field 'MicroOfDay' for get() method, use getLong() instead");
    661             case MILLI_OF_SECOND: return nano / 1000_000;
    662             case MILLI_OF_DAY: return (int) (toNanoOfDay() / 1000_000);
    663             case SECOND_OF_MINUTE: return second;
    664             case SECOND_OF_DAY: return toSecondOfDay();
    665             case MINUTE_OF_HOUR: return minute;
    666             case MINUTE_OF_DAY: return hour * 60 + minute;
    667             case HOUR_OF_AMPM: return hour % 12;
    668             case CLOCK_HOUR_OF_AMPM: int ham = hour % 12; return (ham % 12 == 0 ? 12 : ham);
    669             case HOUR_OF_DAY: return hour;
    670             case CLOCK_HOUR_OF_DAY: return (hour == 0 ? 24 : hour);
    671             case AMPM_OF_DAY: return hour / 12;
    672         }
    673         throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
    674     }
    675 
    676     //-----------------------------------------------------------------------
    677     /**
    678      * Gets the hour-of-day field.
    679      *
    680      * @return the hour-of-day, from 0 to 23
    681      */
    682     public int getHour() {
    683         return hour;
    684     }
    685 
    686     /**
    687      * Gets the minute-of-hour field.
    688      *
    689      * @return the minute-of-hour, from 0 to 59
    690      */
    691     public int getMinute() {
    692         return minute;
    693     }
    694 
    695     /**
    696      * Gets the second-of-minute field.
    697      *
    698      * @return the second-of-minute, from 0 to 59
    699      */
    700     public int getSecond() {
    701         return second;
    702     }
    703 
    704     /**
    705      * Gets the nano-of-second field.
    706      *
    707      * @return the nano-of-second, from 0 to 999,999,999
    708      */
    709     public int getNano() {
    710         return nano;
    711     }
    712 
    713     //-----------------------------------------------------------------------
    714     /**
    715      * Returns an adjusted copy of this time.
    716      * <p>
    717      * This returns a {@code LocalTime}, based on this one, with the time adjusted.
    718      * The adjustment takes place using the specified adjuster strategy object.
    719      * Read the documentation of the adjuster to understand what adjustment will be made.
    720      * <p>
    721      * A simple adjuster might simply set the one of the fields, such as the hour field.
    722      * A more complex adjuster might set the time to the last hour of the day.
    723      * <p>
    724      * The result of this method is obtained by invoking the
    725      * {@link TemporalAdjuster#adjustInto(Temporal)} method on the
    726      * specified adjuster passing {@code this} as the argument.
    727      * <p>
    728      * This instance is immutable and unaffected by this method call.
    729      *
    730      * @param adjuster the adjuster to use, not null
    731      * @return a {@code LocalTime} based on {@code this} with the adjustment made, not null
    732      * @throws DateTimeException if the adjustment cannot be made
    733      * @throws ArithmeticException if numeric overflow occurs
    734      */
    735     @Override
    736     public LocalTime with(TemporalAdjuster adjuster) {
    737         // optimizations
    738         if (adjuster instanceof LocalTime) {
    739             return (LocalTime) adjuster;
    740         }
    741         return (LocalTime) adjuster.adjustInto(this);
    742     }
    743 
    744     /**
    745      * Returns a copy of this time with the specified field set to a new value.
    746      * <p>
    747      * This returns a {@code LocalTime}, based on this one, with the value
    748      * for the specified field changed.
    749      * This can be used to change any supported field, such as the hour, minute or second.
    750      * If it is not possible to set the value, because the field is not supported or for
    751      * some other reason, an exception is thrown.
    752      * <p>
    753      * If the field is a {@link ChronoField} then the adjustment is implemented here.
    754      * The supported fields behave as follows:
    755      * <ul>
    756      * <li>{@code NANO_OF_SECOND} -
    757      *  Returns a {@code LocalTime} with the specified nano-of-second.
    758      *  The hour, minute and second will be unchanged.
    759      * <li>{@code NANO_OF_DAY} -
    760      *  Returns a {@code LocalTime} with the specified nano-of-day.
    761      *  This completely replaces the time and is equivalent to {@link #ofNanoOfDay(long)}.
    762      * <li>{@code MICRO_OF_SECOND} -
    763      *  Returns a {@code LocalTime} with the nano-of-second replaced by the specified
    764      *  micro-of-second multiplied by 1,000.
    765      *  The hour, minute and second will be unchanged.
    766      * <li>{@code MICRO_OF_DAY} -
    767      *  Returns a {@code LocalTime} with the specified micro-of-day.
    768      *  This completely replaces the time and is equivalent to using {@link #ofNanoOfDay(long)}
    769      *  with the micro-of-day multiplied by 1,000.
    770      * <li>{@code MILLI_OF_SECOND} -
    771      *  Returns a {@code LocalTime} with the nano-of-second replaced by the specified
    772      *  milli-of-second multiplied by 1,000,000.
    773      *  The hour, minute and second will be unchanged.
    774      * <li>{@code MILLI_OF_DAY} -
    775      *  Returns a {@code LocalTime} with the specified milli-of-day.
    776      *  This completely replaces the time and is equivalent to using {@link #ofNanoOfDay(long)}
    777      *  with the milli-of-day multiplied by 1,000,000.
    778      * <li>{@code SECOND_OF_MINUTE} -
    779      *  Returns a {@code LocalTime} with the specified second-of-minute.
    780      *  The hour, minute and nano-of-second will be unchanged.
    781      * <li>{@code SECOND_OF_DAY} -
    782      *  Returns a {@code LocalTime} with the specified second-of-day.
    783      *  The nano-of-second will be unchanged.
    784      * <li>{@code MINUTE_OF_HOUR} -
    785      *  Returns a {@code LocalTime} with the specified minute-of-hour.
    786      *  The hour, second-of-minute and nano-of-second will be unchanged.
    787      * <li>{@code MINUTE_OF_DAY} -
    788      *  Returns a {@code LocalTime} with the specified minute-of-day.
    789      *  The second-of-minute and nano-of-second will be unchanged.
    790      * <li>{@code HOUR_OF_AMPM} -
    791      *  Returns a {@code LocalTime} with the specified hour-of-am-pm.
    792      *  The AM/PM, minute-of-hour, second-of-minute and nano-of-second will be unchanged.
    793      * <li>{@code CLOCK_HOUR_OF_AMPM} -
    794      *  Returns a {@code LocalTime} with the specified clock-hour-of-am-pm.
    795      *  The AM/PM, minute-of-hour, second-of-minute and nano-of-second will be unchanged.
    796      * <li>{@code HOUR_OF_DAY} -
    797      *  Returns a {@code LocalTime} with the specified hour-of-day.
    798      *  The minute-of-hour, second-of-minute and nano-of-second will be unchanged.
    799      * <li>{@code CLOCK_HOUR_OF_DAY} -
    800      *  Returns a {@code LocalTime} with the specified clock-hour-of-day.
    801      *  The minute-of-hour, second-of-minute and nano-of-second will be unchanged.
    802      * <li>{@code AMPM_OF_DAY} -
    803      *  Returns a {@code LocalTime} with the specified AM/PM.
    804      *  The hour-of-am-pm, minute-of-hour, second-of-minute and nano-of-second will be unchanged.
    805      * </ul>
    806      * <p>
    807      * In all cases, if the new value is outside the valid range of values for the field
    808      * then a {@code DateTimeException} will be thrown.
    809      * <p>
    810      * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
    811      * <p>
    812      * If the field is not a {@code ChronoField}, then the result of this method
    813      * is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)}
    814      * passing {@code this} as the argument. In this case, the field determines
    815      * whether and how to adjust the instant.
    816      * <p>
    817      * This instance is immutable and unaffected by this method call.
    818      *
    819      * @param field  the field to set in the result, not null
    820      * @param newValue  the new value of the field in the result
    821      * @return a {@code LocalTime} based on {@code this} with the specified field set, not null
    822      * @throws DateTimeException if the field cannot be set
    823      * @throws UnsupportedTemporalTypeException if the field is not supported
    824      * @throws ArithmeticException if numeric overflow occurs
    825      */
    826     @Override
    827     public LocalTime with(TemporalField field, long newValue) {
    828         if (field instanceof ChronoField) {
    829             ChronoField f = (ChronoField) field;
    830             f.checkValidValue(newValue);
    831             switch (f) {
    832                 case NANO_OF_SECOND: return withNano((int) newValue);
    833                 case NANO_OF_DAY: return LocalTime.ofNanoOfDay(newValue);
    834                 case MICRO_OF_SECOND: return withNano((int) newValue * 1000);
    835                 case MICRO_OF_DAY: return LocalTime.ofNanoOfDay(newValue * 1000);
    836                 case MILLI_OF_SECOND: return withNano((int) newValue * 1000_000);
    837                 case MILLI_OF_DAY: return LocalTime.ofNanoOfDay(newValue * 1000_000);
    838                 case SECOND_OF_MINUTE: return withSecond((int) newValue);
    839                 case SECOND_OF_DAY: return plusSeconds(newValue - toSecondOfDay());
    840                 case MINUTE_OF_HOUR: return withMinute((int) newValue);
    841                 case MINUTE_OF_DAY: return plusMinutes(newValue - (hour * 60 + minute));
    842                 case HOUR_OF_AMPM: return plusHours(newValue - (hour % 12));
    843                 case CLOCK_HOUR_OF_AMPM: return plusHours((newValue == 12 ? 0 : newValue) - (hour % 12));
    844                 case HOUR_OF_DAY: return withHour((int) newValue);
    845                 case CLOCK_HOUR_OF_DAY: return withHour((int) (newValue == 24 ? 0 : newValue));
    846                 case AMPM_OF_DAY: return plusHours((newValue - (hour / 12)) * 12);
    847             }
    848             throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
    849         }
    850         return field.adjustInto(this, newValue);
    851     }
    852 
    853     //-----------------------------------------------------------------------
    854     /**
    855      * Returns a copy of this {@code LocalTime} with the hour-of-day altered.
    856      * <p>
    857      * This instance is immutable and unaffected by this method call.
    858      *
    859      * @param hour  the hour-of-day to set in the result, from 0 to 23
    860      * @return a {@code LocalTime} based on this time with the requested hour, not null
    861      * @throws DateTimeException if the hour value is invalid
    862      */
    863     public LocalTime withHour(int hour) {
    864         if (this.hour == hour) {
    865             return this;
    866         }
    867         HOUR_OF_DAY.checkValidValue(hour);
    868         return create(hour, minute, second, nano);
    869     }
    870 
    871     /**
    872      * Returns a copy of this {@code LocalTime} with the minute-of-hour altered.
    873      * <p>
    874      * This instance is immutable and unaffected by this method call.
    875      *
    876      * @param minute  the minute-of-hour to set in the result, from 0 to 59
    877      * @return a {@code LocalTime} based on this time with the requested minute, not null
    878      * @throws DateTimeException if the minute value is invalid
    879      */
    880     public LocalTime withMinute(int minute) {
    881         if (this.minute == minute) {
    882             return this;
    883         }
    884         MINUTE_OF_HOUR.checkValidValue(minute);
    885         return create(hour, minute, second, nano);
    886     }
    887 
    888     /**
    889      * Returns a copy of this {@code LocalTime} with the second-of-minute altered.
    890      * <p>
    891      * This instance is immutable and unaffected by this method call.
    892      *
    893      * @param second  the second-of-minute to set in the result, from 0 to 59
    894      * @return a {@code LocalTime} based on this time with the requested second, not null
    895      * @throws DateTimeException if the second value is invalid
    896      */
    897     public LocalTime withSecond(int second) {
    898         if (this.second == second) {
    899             return this;
    900         }
    901         SECOND_OF_MINUTE.checkValidValue(second);
    902         return create(hour, minute, second, nano);
    903     }
    904 
    905     /**
    906      * Returns a copy of this {@code LocalTime} with the nano-of-second altered.
    907      * <p>
    908      * This instance is immutable and unaffected by this method call.
    909      *
    910      * @param nanoOfSecond  the nano-of-second to set in the result, from 0 to 999,999,999
    911      * @return a {@code LocalTime} based on this time with the requested nanosecond, not null
    912      * @throws DateTimeException if the nanos value is invalid
    913      */
    914     public LocalTime withNano(int nanoOfSecond) {
    915         if (this.nano == nanoOfSecond) {
    916             return this;
    917         }
    918         NANO_OF_SECOND.checkValidValue(nanoOfSecond);
    919         return create(hour, minute, second, nanoOfSecond);
    920     }
    921 
    922     //-----------------------------------------------------------------------
    923     /**
    924      * Returns a copy of this {@code LocalTime} with the time truncated.
    925      * <p>
    926      * Truncation returns a copy of the original time with fields
    927      * smaller than the specified unit set to zero.
    928      * For example, truncating with the {@link ChronoUnit#MINUTES minutes} unit
    929      * will set the second-of-minute and nano-of-second field to zero.
    930      * <p>
    931      * The unit must have a {@linkplain TemporalUnit#getDuration() duration}
    932      * that divides into the length of a standard day without remainder.
    933      * This includes all supplied time units on {@link ChronoUnit} and
    934      * {@link ChronoUnit#DAYS DAYS}. Other units throw an exception.
    935      * <p>
    936      * This instance is immutable and unaffected by this method call.
    937      *
    938      * @param unit  the unit to truncate to, not null
    939      * @return a {@code LocalTime} based on this time with the time truncated, not null
    940      * @throws DateTimeException if unable to truncate
    941      * @throws UnsupportedTemporalTypeException if the unit is not supported
    942      */
    943     public LocalTime truncatedTo(TemporalUnit unit) {
    944         if (unit == ChronoUnit.NANOS) {
    945             return this;
    946         }
    947         Duration unitDur = unit.getDuration();
    948         if (unitDur.getSeconds() > SECONDS_PER_DAY) {
    949             throw new UnsupportedTemporalTypeException("Unit is too large to be used for truncation");
    950         }
    951         long dur = unitDur.toNanos();
    952         if ((NANOS_PER_DAY % dur) != 0) {
    953             throw new UnsupportedTemporalTypeException("Unit must divide into a standard day without remainder");
    954         }
    955         long nod = toNanoOfDay();
    956         return ofNanoOfDay((nod / dur) * dur);
    957     }
    958 
    959     //-----------------------------------------------------------------------
    960     /**
    961      * Returns a copy of this time with the specified amount added.
    962      * <p>
    963      * This returns a {@code LocalTime}, based on this one, with the specified amount added.
    964      * The amount is typically {@link Duration} but may be any other type implementing
    965      * the {@link TemporalAmount} interface.
    966      * <p>
    967      * The calculation is delegated to the amount object by calling
    968      * {@link TemporalAmount#addTo(Temporal)}. The amount implementation is free
    969      * to implement the addition in any way it wishes, however it typically
    970      * calls back to {@link #plus(long, TemporalUnit)}. Consult the documentation
    971      * of the amount implementation to determine if it can be successfully added.
    972      * <p>
    973      * This instance is immutable and unaffected by this method call.
    974      *
    975      * @param amountToAdd  the amount to add, not null
    976      * @return a {@code LocalTime} based on this time with the addition made, not null
    977      * @throws DateTimeException if the addition cannot be made
    978      * @throws ArithmeticException if numeric overflow occurs
    979      */
    980     @Override
    981     public LocalTime plus(TemporalAmount amountToAdd) {
    982         return (LocalTime) amountToAdd.addTo(this);
    983     }
    984 
    985     /**
    986      * Returns a copy of this time with the specified amount added.
    987      * <p>
    988      * This returns a {@code LocalTime}, based on this one, with the amount
    989      * in terms of the unit added. If it is not possible to add the amount, because the
    990      * unit is not supported or for some other reason, an exception is thrown.
    991      * <p>
    992      * If the field is a {@link ChronoUnit} then the addition is implemented here.
    993      * The supported fields behave as follows:
    994      * <ul>
    995      * <li>{@code NANOS} -
    996      *  Returns a {@code LocalTime} with the specified number of nanoseconds added.
    997      *  This is equivalent to {@link #plusNanos(long)}.
    998      * <li>{@code MICROS} -
    999      *  Returns a {@code LocalTime} with the specified number of microseconds added.
   1000      *  This is equivalent to {@link #plusNanos(long)} with the amount
   1001      *  multiplied by 1,000.
   1002      * <li>{@code MILLIS} -
   1003      *  Returns a {@code LocalTime} with the specified number of milliseconds added.
   1004      *  This is equivalent to {@link #plusNanos(long)} with the amount
   1005      *  multiplied by 1,000,000.
   1006      * <li>{@code SECONDS} -
   1007      *  Returns a {@code LocalTime} with the specified number of seconds added.
   1008      *  This is equivalent to {@link #plusSeconds(long)}.
   1009      * <li>{@code MINUTES} -
   1010      *  Returns a {@code LocalTime} with the specified number of minutes added.
   1011      *  This is equivalent to {@link #plusMinutes(long)}.
   1012      * <li>{@code HOURS} -
   1013      *  Returns a {@code LocalTime} with the specified number of hours added.
   1014      *  This is equivalent to {@link #plusHours(long)}.
   1015      * <li>{@code HALF_DAYS} -
   1016      *  Returns a {@code LocalTime} with the specified number of half-days added.
   1017      *  This is equivalent to {@link #plusHours(long)} with the amount
   1018      *  multiplied by 12.
   1019      * </ul>
   1020      * <p>
   1021      * All other {@code ChronoUnit} instances will throw an {@code UnsupportedTemporalTypeException}.
   1022      * <p>
   1023      * If the field is not a {@code ChronoUnit}, then the result of this method
   1024      * is obtained by invoking {@code TemporalUnit.addTo(Temporal, long)}
   1025      * passing {@code this} as the argument. In this case, the unit determines
   1026      * whether and how to perform the addition.
   1027      * <p>
   1028      * This instance is immutable and unaffected by this method call.
   1029      *
   1030      * @param amountToAdd  the amount of the unit to add to the result, may be negative
   1031      * @param unit  the unit of the amount to add, not null
   1032      * @return a {@code LocalTime} based on this time with the specified amount added, not null
   1033      * @throws DateTimeException if the addition cannot be made
   1034      * @throws UnsupportedTemporalTypeException if the unit is not supported
   1035      * @throws ArithmeticException if numeric overflow occurs
   1036      */
   1037     @Override
   1038     public LocalTime plus(long amountToAdd, TemporalUnit unit) {
   1039         if (unit instanceof ChronoUnit) {
   1040             switch ((ChronoUnit) unit) {
   1041                 case NANOS: return plusNanos(amountToAdd);
   1042                 case MICROS: return plusNanos((amountToAdd % MICROS_PER_DAY) * 1000);
   1043                 case MILLIS: return plusNanos((amountToAdd % MILLIS_PER_DAY) * 1000_000);
   1044                 case SECONDS: return plusSeconds(amountToAdd);
   1045                 case MINUTES: return plusMinutes(amountToAdd);
   1046                 case HOURS: return plusHours(amountToAdd);
   1047                 case HALF_DAYS: return plusHours((amountToAdd % 2) * 12);
   1048             }
   1049             throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);
   1050         }
   1051         return unit.addTo(this, amountToAdd);
   1052     }
   1053 
   1054     //-----------------------------------------------------------------------
   1055     /**
   1056      * Returns a copy of this {@code LocalTime} with the specified number of hours added.
   1057      * <p>
   1058      * This adds the specified number of hours to this time, returning a new time.
   1059      * The calculation wraps around midnight.
   1060      * <p>
   1061      * This instance is immutable and unaffected by this method call.
   1062      *
   1063      * @param hoursToAdd  the hours to add, may be negative
   1064      * @return a {@code LocalTime} based on this time with the hours added, not null
   1065      */
   1066     public LocalTime plusHours(long hoursToAdd) {
   1067         if (hoursToAdd == 0) {
   1068             return this;
   1069         }
   1070         int newHour = ((int) (hoursToAdd % HOURS_PER_DAY) + hour + HOURS_PER_DAY) % HOURS_PER_DAY;
   1071         return create(newHour, minute, second, nano);
   1072     }
   1073 
   1074     /**
   1075      * Returns a copy of this {@code LocalTime} with the specified number of minutes added.
   1076      * <p>
   1077      * This adds the specified number of minutes to this time, returning a new time.
   1078      * The calculation wraps around midnight.
   1079      * <p>
   1080      * This instance is immutable and unaffected by this method call.
   1081      *
   1082      * @param minutesToAdd  the minutes to add, may be negative
   1083      * @return a {@code LocalTime} based on this time with the minutes added, not null
   1084      */
   1085     public LocalTime plusMinutes(long minutesToAdd) {
   1086         if (minutesToAdd == 0) {
   1087             return this;
   1088         }
   1089         int mofd = hour * MINUTES_PER_HOUR + minute;
   1090         int newMofd = ((int) (minutesToAdd % MINUTES_PER_DAY) + mofd + MINUTES_PER_DAY) % MINUTES_PER_DAY;
   1091         if (mofd == newMofd) {
   1092             return this;
   1093         }
   1094         int newHour = newMofd / MINUTES_PER_HOUR;
   1095         int newMinute = newMofd % MINUTES_PER_HOUR;
   1096         return create(newHour, newMinute, second, nano);
   1097     }
   1098 
   1099     /**
   1100      * Returns a copy of this {@code LocalTime} with the specified number of seconds added.
   1101      * <p>
   1102      * This adds the specified number of seconds to this time, returning a new time.
   1103      * The calculation wraps around midnight.
   1104      * <p>
   1105      * This instance is immutable and unaffected by this method call.
   1106      *
   1107      * @param secondstoAdd  the seconds to add, may be negative
   1108      * @return a {@code LocalTime} based on this time with the seconds added, not null
   1109      */
   1110     public LocalTime plusSeconds(long secondstoAdd) {
   1111         if (secondstoAdd == 0) {
   1112             return this;
   1113         }
   1114         int sofd = hour * SECONDS_PER_HOUR +
   1115                     minute * SECONDS_PER_MINUTE + second;
   1116         int newSofd = ((int) (secondstoAdd % SECONDS_PER_DAY) + sofd + SECONDS_PER_DAY) % SECONDS_PER_DAY;
   1117         if (sofd == newSofd) {
   1118             return this;
   1119         }
   1120         int newHour = newSofd / SECONDS_PER_HOUR;
   1121         int newMinute = (newSofd / SECONDS_PER_MINUTE) % MINUTES_PER_HOUR;
   1122         int newSecond = newSofd % SECONDS_PER_MINUTE;
   1123         return create(newHour, newMinute, newSecond, nano);
   1124     }
   1125 
   1126     /**
   1127      * Returns a copy of this {@code LocalTime} with the specified number of nanoseconds added.
   1128      * <p>
   1129      * This adds the specified number of nanoseconds to this time, returning a new time.
   1130      * The calculation wraps around midnight.
   1131      * <p>
   1132      * This instance is immutable and unaffected by this method call.
   1133      *
   1134      * @param nanosToAdd  the nanos to add, may be negative
   1135      * @return a {@code LocalTime} based on this time with the nanoseconds added, not null
   1136      */
   1137     public LocalTime plusNanos(long nanosToAdd) {
   1138         if (nanosToAdd == 0) {
   1139             return this;
   1140         }
   1141         long nofd = toNanoOfDay();
   1142         long newNofd = ((nanosToAdd % NANOS_PER_DAY) + nofd + NANOS_PER_DAY) % NANOS_PER_DAY;
   1143         if (nofd == newNofd) {
   1144             return this;
   1145         }
   1146         int newHour = (int) (newNofd / NANOS_PER_HOUR);
   1147         int newMinute = (int) ((newNofd / NANOS_PER_MINUTE) % MINUTES_PER_HOUR);
   1148         int newSecond = (int) ((newNofd / NANOS_PER_SECOND) % SECONDS_PER_MINUTE);
   1149         int newNano = (int) (newNofd % NANOS_PER_SECOND);
   1150         return create(newHour, newMinute, newSecond, newNano);
   1151     }
   1152 
   1153     //-----------------------------------------------------------------------
   1154     /**
   1155      * Returns a copy of this time with the specified amount subtracted.
   1156      * <p>
   1157      * This returns a {@code LocalTime}, based on this one, with the specified amount subtracted.
   1158      * The amount is typically {@link Duration} but may be any other type implementing
   1159      * the {@link TemporalAmount} interface.
   1160      * <p>
   1161      * The calculation is delegated to the amount object by calling
   1162      * {@link TemporalAmount#subtractFrom(Temporal)}. The amount implementation is free
   1163      * to implement the subtraction in any way it wishes, however it typically
   1164      * calls back to {@link #minus(long, TemporalUnit)}. Consult the documentation
   1165      * of the amount implementation to determine if it can be successfully subtracted.
   1166      * <p>
   1167      * This instance is immutable and unaffected by this method call.
   1168      *
   1169      * @param amountToSubtract  the amount to subtract, not null
   1170      * @return a {@code LocalTime} based on this time with the subtraction made, not null
   1171      * @throws DateTimeException if the subtraction cannot be made
   1172      * @throws ArithmeticException if numeric overflow occurs
   1173      */
   1174     @Override
   1175     public LocalTime minus(TemporalAmount amountToSubtract) {
   1176         return (LocalTime) amountToSubtract.subtractFrom(this);
   1177     }
   1178 
   1179     /**
   1180      * Returns a copy of this time with the specified amount subtracted.
   1181      * <p>
   1182      * This returns a {@code LocalTime}, based on this one, with the amount
   1183      * in terms of the unit subtracted. If it is not possible to subtract the amount,
   1184      * because the unit is not supported or for some other reason, an exception is thrown.
   1185      * <p>
   1186      * This method is equivalent to {@link #plus(long, TemporalUnit)} with the amount negated.
   1187      * See that method for a full description of how addition, and thus subtraction, works.
   1188      * <p>
   1189      * This instance is immutable and unaffected by this method call.
   1190      *
   1191      * @param amountToSubtract  the amount of the unit to subtract from the result, may be negative
   1192      * @param unit  the unit of the amount to subtract, not null
   1193      * @return a {@code LocalTime} based on this time with the specified amount subtracted, not null
   1194      * @throws DateTimeException if the subtraction cannot be made
   1195      * @throws UnsupportedTemporalTypeException if the unit is not supported
   1196      * @throws ArithmeticException if numeric overflow occurs
   1197      */
   1198     @Override
   1199     public LocalTime minus(long amountToSubtract, TemporalUnit unit) {
   1200         return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit));
   1201     }
   1202 
   1203     //-----------------------------------------------------------------------
   1204     /**
   1205      * Returns a copy of this {@code LocalTime} with the specified number of hours subtracted.
   1206      * <p>
   1207      * This subtracts the specified number of hours from this time, returning a new time.
   1208      * The calculation wraps around midnight.
   1209      * <p>
   1210      * This instance is immutable and unaffected by this method call.
   1211      *
   1212      * @param hoursToSubtract  the hours to subtract, may be negative
   1213      * @return a {@code LocalTime} based on this time with the hours subtracted, not null
   1214      */
   1215     public LocalTime minusHours(long hoursToSubtract) {
   1216         return plusHours(-(hoursToSubtract % HOURS_PER_DAY));
   1217     }
   1218 
   1219     /**
   1220      * Returns a copy of this {@code LocalTime} with the specified number of minutes subtracted.
   1221      * <p>
   1222      * This subtracts the specified number of minutes from this time, returning a new time.
   1223      * The calculation wraps around midnight.
   1224      * <p>
   1225      * This instance is immutable and unaffected by this method call.
   1226      *
   1227      * @param minutesToSubtract  the minutes to subtract, may be negative
   1228      * @return a {@code LocalTime} based on this time with the minutes subtracted, not null
   1229      */
   1230     public LocalTime minusMinutes(long minutesToSubtract) {
   1231         return plusMinutes(-(minutesToSubtract % MINUTES_PER_DAY));
   1232     }
   1233 
   1234     /**
   1235      * Returns a copy of this {@code LocalTime} with the specified number of seconds subtracted.
   1236      * <p>
   1237      * This subtracts the specified number of seconds from this time, returning a new time.
   1238      * The calculation wraps around midnight.
   1239      * <p>
   1240      * This instance is immutable and unaffected by this method call.
   1241      *
   1242      * @param secondsToSubtract  the seconds to subtract, may be negative
   1243      * @return a {@code LocalTime} based on this time with the seconds subtracted, not null
   1244      */
   1245     public LocalTime minusSeconds(long secondsToSubtract) {
   1246         return plusSeconds(-(secondsToSubtract % SECONDS_PER_DAY));
   1247     }
   1248 
   1249     /**
   1250      * Returns a copy of this {@code LocalTime} with the specified number of nanoseconds subtracted.
   1251      * <p>
   1252      * This subtracts the specified number of nanoseconds from this time, returning a new time.
   1253      * The calculation wraps around midnight.
   1254      * <p>
   1255      * This instance is immutable and unaffected by this method call.
   1256      *
   1257      * @param nanosToSubtract  the nanos to subtract, may be negative
   1258      * @return a {@code LocalTime} based on this time with the nanoseconds subtracted, not null
   1259      */
   1260     public LocalTime minusNanos(long nanosToSubtract) {
   1261         return plusNanos(-(nanosToSubtract % NANOS_PER_DAY));
   1262     }
   1263 
   1264     //-----------------------------------------------------------------------
   1265     /**
   1266      * Queries this time using the specified query.
   1267      * <p>
   1268      * This queries this time using the specified query strategy object.
   1269      * The {@code TemporalQuery} object defines the logic to be used to
   1270      * obtain the result. Read the documentation of the query to understand
   1271      * what the result of this method will be.
   1272      * <p>
   1273      * The result of this method is obtained by invoking the
   1274      * {@link TemporalQuery#queryFrom(TemporalAccessor)} method on the
   1275      * specified query passing {@code this} as the argument.
   1276      *
   1277      * @param <R> the type of the result
   1278      * @param query  the query to invoke, not null
   1279      * @return the query result, null may be returned (defined by the query)
   1280      * @throws DateTimeException if unable to query (defined by the query)
   1281      * @throws ArithmeticException if numeric overflow occurs (defined by the query)
   1282      */
   1283     @SuppressWarnings("unchecked")
   1284     @Override
   1285     public <R> R query(TemporalQuery<R> query) {
   1286         if (query == TemporalQueries.chronology() || query == TemporalQueries.zoneId() ||
   1287                 query == TemporalQueries.zone() || query == TemporalQueries.offset()) {
   1288             return null;
   1289         } else if (query == TemporalQueries.localTime()) {
   1290             return (R) this;
   1291         } else if (query == TemporalQueries.localDate()) {
   1292             return null;
   1293         } else if (query == TemporalQueries.precision()) {
   1294             return (R) NANOS;
   1295         }
   1296         // inline TemporalAccessor.super.query(query) as an optimization
   1297         // non-JDK classes are not permitted to make this optimization
   1298         return query.queryFrom(this);
   1299     }
   1300 
   1301     /**
   1302      * Adjusts the specified temporal object to have the same time as this object.
   1303      * <p>
   1304      * This returns a temporal object of the same observable type as the input
   1305      * with the time changed to be the same as this.
   1306      * <p>
   1307      * The adjustment is equivalent to using {@link Temporal#with(TemporalField, long)}
   1308      * passing {@link ChronoField#NANO_OF_DAY} as the field.
   1309      * <p>
   1310      * In most cases, it is clearer to reverse the calling pattern by using
   1311      * {@link Temporal#with(TemporalAdjuster)}:
   1312      * <pre>
   1313      *   // these two lines are equivalent, but the second approach is recommended
   1314      *   temporal = thisLocalTime.adjustInto(temporal);
   1315      *   temporal = temporal.with(thisLocalTime);
   1316      * </pre>
   1317      * <p>
   1318      * This instance is immutable and unaffected by this method call.
   1319      *
   1320      * @param temporal  the target object to be adjusted, not null
   1321      * @return the adjusted object, not null
   1322      * @throws DateTimeException if unable to make the adjustment
   1323      * @throws ArithmeticException if numeric overflow occurs
   1324      */
   1325     @Override
   1326     public Temporal adjustInto(Temporal temporal) {
   1327         return temporal.with(NANO_OF_DAY, toNanoOfDay());
   1328     }
   1329 
   1330     /**
   1331      * Calculates the amount of time until another time in terms of the specified unit.
   1332      * <p>
   1333      * This calculates the amount of time between two {@code LocalTime}
   1334      * objects in terms of a single {@code TemporalUnit}.
   1335      * The start and end points are {@code this} and the specified time.
   1336      * The result will be negative if the end is before the start.
   1337      * The {@code Temporal} passed to this method is converted to a
   1338      * {@code LocalTime} using {@link #from(TemporalAccessor)}.
   1339      * For example, the amount in hours between two times can be calculated
   1340      * using {@code startTime.until(endTime, HOURS)}.
   1341      * <p>
   1342      * The calculation returns a whole number, representing the number of
   1343      * complete units between the two times.
   1344      * For example, the amount in hours between 11:30 and 13:29 will only
   1345      * be one hour as it is one minute short of two hours.
   1346      * <p>
   1347      * There are two equivalent ways of using this method.
   1348      * The first is to invoke this method.
   1349      * The second is to use {@link TemporalUnit#between(Temporal, Temporal)}:
   1350      * <pre>
   1351      *   // these two lines are equivalent
   1352      *   amount = start.until(end, MINUTES);
   1353      *   amount = MINUTES.between(start, end);
   1354      * </pre>
   1355      * The choice should be made based on which makes the code more readable.
   1356      * <p>
   1357      * The calculation is implemented in this method for {@link ChronoUnit}.
   1358      * The units {@code NANOS}, {@code MICROS}, {@code MILLIS}, {@code SECONDS},
   1359      * {@code MINUTES}, {@code HOURS} and {@code HALF_DAYS} are supported.
   1360      * Other {@code ChronoUnit} values will throw an exception.
   1361      * <p>
   1362      * If the unit is not a {@code ChronoUnit}, then the result of this method
   1363      * is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)}
   1364      * passing {@code this} as the first argument and the converted input temporal
   1365      * as the second argument.
   1366      * <p>
   1367      * This instance is immutable and unaffected by this method call.
   1368      *
   1369      * @param endExclusive  the end time, exclusive, which is converted to a {@code LocalTime}, not null
   1370      * @param unit  the unit to measure the amount in, not null
   1371      * @return the amount of time between this time and the end time
   1372      * @throws DateTimeException if the amount cannot be calculated, or the end
   1373      *  temporal cannot be converted to a {@code LocalTime}
   1374      * @throws UnsupportedTemporalTypeException if the unit is not supported
   1375      * @throws ArithmeticException if numeric overflow occurs
   1376      */
   1377     @Override
   1378     public long until(Temporal endExclusive, TemporalUnit unit) {
   1379         LocalTime end = LocalTime.from(endExclusive);
   1380         if (unit instanceof ChronoUnit) {
   1381             long nanosUntil = end.toNanoOfDay() - toNanoOfDay();  // no overflow
   1382             switch ((ChronoUnit) unit) {
   1383                 case NANOS: return nanosUntil;
   1384                 case MICROS: return nanosUntil / 1000;
   1385                 case MILLIS: return nanosUntil / 1000_000;
   1386                 case SECONDS: return nanosUntil / NANOS_PER_SECOND;
   1387                 case MINUTES: return nanosUntil / NANOS_PER_MINUTE;
   1388                 case HOURS: return nanosUntil / NANOS_PER_HOUR;
   1389                 case HALF_DAYS: return nanosUntil / (12 * NANOS_PER_HOUR);
   1390             }
   1391             throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);
   1392         }
   1393         return unit.between(this, end);
   1394     }
   1395 
   1396     /**
   1397      * Formats this time using the specified formatter.
   1398      * <p>
   1399      * This time will be passed to the formatter to produce a string.
   1400      *
   1401      * @param formatter  the formatter to use, not null
   1402      * @return the formatted time string, not null
   1403      * @throws DateTimeException if an error occurs during printing
   1404      */
   1405     public String format(DateTimeFormatter formatter) {
   1406         Objects.requireNonNull(formatter, "formatter");
   1407         return formatter.format(this);
   1408     }
   1409 
   1410     //-----------------------------------------------------------------------
   1411     /**
   1412      * Combines this time with a date to create a {@code LocalDateTime}.
   1413      * <p>
   1414      * This returns a {@code LocalDateTime} formed from this time at the specified date.
   1415      * All possible combinations of date and time are valid.
   1416      *
   1417      * @param date  the date to combine with, not null
   1418      * @return the local date-time formed from this time and the specified date, not null
   1419      */
   1420     public LocalDateTime atDate(LocalDate date) {
   1421         return LocalDateTime.of(date, this);
   1422     }
   1423 
   1424     /**
   1425      * Combines this time with an offset to create an {@code OffsetTime}.
   1426      * <p>
   1427      * This returns an {@code OffsetTime} formed from this time at the specified offset.
   1428      * All possible combinations of time and offset are valid.
   1429      *
   1430      * @param offset  the offset to combine with, not null
   1431      * @return the offset time formed from this time and the specified offset, not null
   1432      */
   1433     public OffsetTime atOffset(ZoneOffset offset) {
   1434         return OffsetTime.of(this, offset);
   1435     }
   1436 
   1437     //-----------------------------------------------------------------------
   1438     /**
   1439      * Extracts the time as seconds of day,
   1440      * from {@code 0} to {@code 24 * 60 * 60 - 1}.
   1441      *
   1442      * @return the second-of-day equivalent to this time
   1443      */
   1444     public int toSecondOfDay() {
   1445         int total = hour * SECONDS_PER_HOUR;
   1446         total += minute * SECONDS_PER_MINUTE;
   1447         total += second;
   1448         return total;
   1449     }
   1450 
   1451     /**
   1452      * Extracts the time as nanos of day,
   1453      * from {@code 0} to {@code 24 * 60 * 60 * 1,000,000,000 - 1}.
   1454      *
   1455      * @return the nano of day equivalent to this time
   1456      */
   1457     public long toNanoOfDay() {
   1458         long total = hour * NANOS_PER_HOUR;
   1459         total += minute * NANOS_PER_MINUTE;
   1460         total += second * NANOS_PER_SECOND;
   1461         total += nano;
   1462         return total;
   1463     }
   1464 
   1465     //-----------------------------------------------------------------------
   1466     /**
   1467      * Compares this time to another time.
   1468      * <p>
   1469      * The comparison is based on the time-line position of the local times within a day.
   1470      * It is "consistent with equals", as defined by {@link Comparable}.
   1471      *
   1472      * @param other  the other time to compare to, not null
   1473      * @return the comparator value, negative if less, positive if greater
   1474      * @throws NullPointerException if {@code other} is null
   1475      */
   1476     @Override
   1477     public int compareTo(LocalTime other) {
   1478         int cmp = Integer.compare(hour, other.hour);
   1479         if (cmp == 0) {
   1480             cmp = Integer.compare(minute, other.minute);
   1481             if (cmp == 0) {
   1482                 cmp = Integer.compare(second, other.second);
   1483                 if (cmp == 0) {
   1484                     cmp = Integer.compare(nano, other.nano);
   1485                 }
   1486             }
   1487         }
   1488         return cmp;
   1489     }
   1490 
   1491     /**
   1492      * Checks if this time is after the specified time.
   1493      * <p>
   1494      * The comparison is based on the time-line position of the time within a day.
   1495      *
   1496      * @param other  the other time to compare to, not null
   1497      * @return true if this is after the specified time
   1498      * @throws NullPointerException if {@code other} is null
   1499      */
   1500     public boolean isAfter(LocalTime other) {
   1501         return compareTo(other) > 0;
   1502     }
   1503 
   1504     /**
   1505      * Checks if this time is before the specified time.
   1506      * <p>
   1507      * The comparison is based on the time-line position of the time within a day.
   1508      *
   1509      * @param other  the other time to compare to, not null
   1510      * @return true if this point is before the specified time
   1511      * @throws NullPointerException if {@code other} is null
   1512      */
   1513     public boolean isBefore(LocalTime other) {
   1514         return compareTo(other) < 0;
   1515     }
   1516 
   1517     //-----------------------------------------------------------------------
   1518     /**
   1519      * Checks if this time is equal to another time.
   1520      * <p>
   1521      * The comparison is based on the time-line position of the time within a day.
   1522      * <p>
   1523      * Only objects of type {@code LocalTime} are compared, other types return false.
   1524      * To compare the date of two {@code TemporalAccessor} instances, use
   1525      * {@link ChronoField#NANO_OF_DAY} as a comparator.
   1526      *
   1527      * @param obj  the object to check, null returns false
   1528      * @return true if this is equal to the other time
   1529      */
   1530     @Override
   1531     public boolean equals(Object obj) {
   1532         if (this == obj) {
   1533             return true;
   1534         }
   1535         if (obj instanceof LocalTime) {
   1536             LocalTime other = (LocalTime) obj;
   1537             return hour == other.hour && minute == other.minute &&
   1538                     second == other.second && nano == other.nano;
   1539         }
   1540         return false;
   1541     }
   1542 
   1543     /**
   1544      * A hash code for this time.
   1545      *
   1546      * @return a suitable hash code
   1547      */
   1548     @Override
   1549     public int hashCode() {
   1550         long nod = toNanoOfDay();
   1551         return (int) (nod ^ (nod >>> 32));
   1552     }
   1553 
   1554     //-----------------------------------------------------------------------
   1555     /**
   1556      * Outputs this time as a {@code String}, such as {@code 10:15}.
   1557      * <p>
   1558      * The output will be one of the following ISO-8601 formats:
   1559      * <ul>
   1560      * <li>{@code HH:mm}</li>
   1561      * <li>{@code HH:mm:ss}</li>
   1562      * <li>{@code HH:mm:ss.SSS}</li>
   1563      * <li>{@code HH:mm:ss.SSSSSS}</li>
   1564      * <li>{@code HH:mm:ss.SSSSSSSSS}</li>
   1565      * </ul>
   1566      * The format used will be the shortest that outputs the full value of
   1567      * the time where the omitted parts are implied to be zero.
   1568      *
   1569      * @return a string representation of this time, not null
   1570      */
   1571     @Override
   1572     public String toString() {
   1573         StringBuilder buf = new StringBuilder(18);
   1574         int hourValue = hour;
   1575         int minuteValue = minute;
   1576         int secondValue = second;
   1577         int nanoValue = nano;
   1578         buf.append(hourValue < 10 ? "0" : "").append(hourValue)
   1579             .append(minuteValue < 10 ? ":0" : ":").append(minuteValue);
   1580         if (secondValue > 0 || nanoValue > 0) {
   1581             buf.append(secondValue < 10 ? ":0" : ":").append(secondValue);
   1582             if (nanoValue > 0) {
   1583                 buf.append('.');
   1584                 if (nanoValue % 1000_000 == 0) {
   1585                     buf.append(Integer.toString((nanoValue / 1000_000) + 1000).substring(1));
   1586                 } else if (nanoValue % 1000 == 0) {
   1587                     buf.append(Integer.toString((nanoValue / 1000) + 1000_000).substring(1));
   1588                 } else {
   1589                     buf.append(Integer.toString((nanoValue) + 1000_000_000).substring(1));
   1590                 }
   1591             }
   1592         }
   1593         return buf.toString();
   1594     }
   1595 
   1596     //-----------------------------------------------------------------------
   1597     /**
   1598      * Writes the object using a
   1599      * <a href="../../serialized-form.html#java.time.Ser">dedicated serialized form</a>.
   1600      * @serialData
   1601      * A twos-complement value indicates the remaining values are not in the stream
   1602      * and should be set to zero.
   1603      * <pre>
   1604      *  out.writeByte(4);  // identifies a LocalTime
   1605      *  if (nano == 0) {
   1606      *    if (second == 0) {
   1607      *      if (minute == 0) {
   1608      *        out.writeByte(~hour);
   1609      *      } else {
   1610      *        out.writeByte(hour);
   1611      *        out.writeByte(~minute);
   1612      *      }
   1613      *    } else {
   1614      *      out.writeByte(hour);
   1615      *      out.writeByte(minute);
   1616      *      out.writeByte(~second);
   1617      *    }
   1618      *  } else {
   1619      *    out.writeByte(hour);
   1620      *    out.writeByte(minute);
   1621      *    out.writeByte(second);
   1622      *    out.writeInt(nano);
   1623      *  }
   1624      * </pre>
   1625      *
   1626      * @return the instance of {@code Ser}, not null
   1627      */
   1628     private Object writeReplace() {
   1629         return new Ser(Ser.LOCAL_TIME_TYPE, this);
   1630     }
   1631 
   1632     /**
   1633      * Defend against malicious streams.
   1634      *
   1635      * @param s the stream to read
   1636      * @throws InvalidObjectException always
   1637      */
   1638     private void readObject(ObjectInputStream s) throws InvalidObjectException {
   1639         throw new InvalidObjectException("Deserialization via serialization delegate");
   1640     }
   1641 
   1642     void writeExternal(DataOutput out) throws IOException {
   1643         if (nano == 0) {
   1644             if (second == 0) {
   1645                 if (minute == 0) {
   1646                     out.writeByte(~hour);
   1647                 } else {
   1648                     out.writeByte(hour);
   1649                     out.writeByte(~minute);
   1650                 }
   1651             } else {
   1652                 out.writeByte(hour);
   1653                 out.writeByte(minute);
   1654                 out.writeByte(~second);
   1655             }
   1656         } else {
   1657             out.writeByte(hour);
   1658             out.writeByte(minute);
   1659             out.writeByte(second);
   1660             out.writeInt(nano);
   1661         }
   1662     }
   1663 
   1664     static LocalTime readExternal(DataInput in) throws IOException {
   1665         int hour = in.readByte();
   1666         int minute = 0;
   1667         int second = 0;
   1668         int nano = 0;
   1669         if (hour < 0) {
   1670             hour = ~hour;
   1671         } else {
   1672             minute = in.readByte();
   1673             if (minute < 0) {
   1674                 minute = ~minute;
   1675             } else {
   1676                 second = in.readByte();
   1677                 if (second < 0) {
   1678                     second = ~second;
   1679                 } else {
   1680                     nano = in.readInt();
   1681                 }
   1682             }
   1683         }
   1684         return LocalTime.of(hour, minute, second, nano);
   1685     }
   1686 
   1687 }
   1688