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