001 /* 002 * Copyright 2001-2011 Stephen Colebourne 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.joda.time; 017 018 import java.io.IOException; 019 import java.io.ObjectInputStream; 020 import java.io.ObjectOutputStream; 021 import java.io.Serializable; 022 import java.util.Calendar; 023 import java.util.Date; 024 import java.util.HashSet; 025 import java.util.Locale; 026 import java.util.Set; 027 028 import org.joda.convert.FromString; 029 import org.joda.convert.ToString; 030 import org.joda.time.base.BaseLocal; 031 import org.joda.time.chrono.ISOChronology; 032 import org.joda.time.convert.ConverterManager; 033 import org.joda.time.convert.PartialConverter; 034 import org.joda.time.field.AbstractReadableInstantFieldProperty; 035 import org.joda.time.format.DateTimeFormat; 036 import org.joda.time.format.DateTimeFormatter; 037 import org.joda.time.format.ISODateTimeFormat; 038 039 /** 040 * LocalTime is an immutable time class representing a time 041 * without a time zone. 042 * <p> 043 * LocalTime implements the {@link ReadablePartial} interface. 044 * To do this, the interface methods focus on the key fields - 045 * HourOfDay, MinuteOfHour, SecondOfMinute and MillisOfSecond. 046 * However, <b>all</b> time fields may in fact be queried. 047 * <p> 048 * Calculations on LocalTime are performed using a {@link Chronology}. 049 * This chronology will be set internally to be in the UTC time zone 050 * for all calculations. 051 * 052 * <p>Each individual field can be queried in two ways: 053 * <ul> 054 * <li><code>getHourOfDay()</code> 055 * <li><code>hourOfDay().get()</code> 056 * </ul> 057 * The second technique also provides access to other useful methods on the 058 * field: 059 * <ul> 060 * <li>numeric value 061 * <li>text value 062 * <li>short text value 063 * <li>maximum/minimum values 064 * <li>add/subtract 065 * <li>set 066 * <li>rounding 067 * </ul> 068 * 069 * <p> 070 * LocalTime is thread-safe and immutable, provided that the Chronology is as well. 071 * All standard Chronology classes supplied are thread-safe and immutable. 072 * 073 * @author Stephen Colebourne 074 * @since 1.3 075 */ 076 public final class LocalTime 077 extends BaseLocal 078 implements ReadablePartial, Serializable { 079 080 /** Serialization lock */ 081 private static final long serialVersionUID = -12873158713873L; 082 083 /** Constant for midnight. */ 084 public static final LocalTime MIDNIGHT = new LocalTime(0, 0, 0, 0); 085 086 /** The index of the hourOfDay field in the field array */ 087 private static final int HOUR_OF_DAY = 0; 088 /** The index of the minuteOfHour field in the field array */ 089 private static final int MINUTE_OF_HOUR = 1; 090 /** The index of the secondOfMinute field in the field array */ 091 private static final int SECOND_OF_MINUTE = 2; 092 /** The index of the millisOfSecond field in the field array */ 093 private static final int MILLIS_OF_SECOND = 3; 094 /** Set of known duration types. */ 095 private static final Set<DurationFieldType> TIME_DURATION_TYPES = new HashSet<DurationFieldType>(); 096 static { 097 TIME_DURATION_TYPES.add(DurationFieldType.millis()); 098 TIME_DURATION_TYPES.add(DurationFieldType.seconds()); 099 TIME_DURATION_TYPES.add(DurationFieldType.minutes()); 100 TIME_DURATION_TYPES.add(DurationFieldType.hours()); 101 } 102 103 /** The local millis from 1970-01-01T00:00:00 */ 104 private final long iLocalMillis; 105 /** The chronology to use, in UTC */ 106 private final Chronology iChronology; 107 108 //----------------------------------------------------------------------- 109 /** 110 * Obtains a {@code LocalTime} set to the current system millisecond time 111 * using <code>ISOChronology</code> in the default time zone. 112 * The resulting object does not use the zone. 113 * 114 * @return the current time, not null 115 * @since 2.0 116 */ 117 public static LocalTime now() { 118 return new LocalTime(); 119 } 120 121 /** 122 * Obtains a {@code LocalTime} set to the current system millisecond time 123 * using <code>ISOChronology</code> in the specified time zone. 124 * The resulting object does not use the zone. 125 * 126 * @param zone the time zone, not null 127 * @return the current time, not null 128 * @since 2.0 129 */ 130 public static LocalTime now(DateTimeZone zone) { 131 if (zone == null) { 132 throw new NullPointerException("Zone must not be null"); 133 } 134 return new LocalTime(zone); 135 } 136 137 /** 138 * Obtains a {@code LocalTime} set to the current system millisecond time 139 * using the specified chronology. 140 * The resulting object does not use the zone. 141 * 142 * @param chronology the chronology, not null 143 * @return the current time, not null 144 * @since 2.0 145 */ 146 public static LocalTime now(Chronology chronology) { 147 if (chronology == null) { 148 throw new NullPointerException("Chronology must not be null"); 149 } 150 return new LocalTime(chronology); 151 } 152 153 //----------------------------------------------------------------------- 154 /** 155 * Parses a {@code LocalTime} from the specified string. 156 * <p> 157 * This uses {@link ISODateTimeFormat#localTimeParser()}. 158 * 159 * @param str the string to parse, not null 160 * @since 2.0 161 */ 162 @FromString 163 public static LocalTime parse(String str) { 164 return parse(str, ISODateTimeFormat.localTimeParser()); 165 } 166 167 /** 168 * Parses a {@code LocalTime} from the specified string using a formatter. 169 * 170 * @param str the string to parse, not null 171 * @param formatter the formatter to use, not null 172 * @since 2.0 173 */ 174 public static LocalTime parse(String str, DateTimeFormatter formatter) { 175 return formatter.parseLocalTime(str); 176 } 177 178 //----------------------------------------------------------------------- 179 /** 180 * Constructs a LocalTime from the specified millis of day using the 181 * ISO chronology. 182 * <p> 183 * The millisOfDay value may exceed the number of millis in one day, 184 * but additional days will be ignored. 185 * This method uses the UTC time zone internally. 186 * 187 * @param millisOfDay the number of milliseconds into a day to convert 188 */ 189 public static LocalTime fromMillisOfDay(long millisOfDay) { 190 return fromMillisOfDay(millisOfDay, null); 191 } 192 193 /** 194 * Constructs a LocalTime from the specified millis of day using the 195 * specified chronology. 196 * <p> 197 * The millisOfDay value may exceed the number of millis in one day, 198 * but additional days will be ignored. 199 * This method uses the UTC time zone internally. 200 * 201 * @param millisOfDay the number of milliseconds into a day to convert 202 * @param chrono the chronology, null means ISO chronology 203 */ 204 public static LocalTime fromMillisOfDay(long millisOfDay, Chronology chrono) { 205 chrono = DateTimeUtils.getChronology(chrono).withUTC(); 206 return new LocalTime(millisOfDay, chrono); 207 } 208 209 //----------------------------------------------------------------------- 210 /** 211 * Constructs a LocalTime from a <code>java.util.Calendar</code> 212 * using exactly the same field values. 213 * <p> 214 * Each field is queried from the Calendar and assigned to the LocalTime. 215 * This is useful if you have been using the Calendar as a local time, 216 * ignoring the zone. 217 * <p> 218 * One advantage of this method is that this method is unaffected if the 219 * version of the time zone data differs between the JDK and Joda-Time. 220 * That is because the local field values are transferred, calculated using 221 * the JDK time zone data and without using the Joda-Time time zone data. 222 * <p> 223 * This factory method ignores the type of the calendar and always 224 * creates a LocalTime with ISO chronology. It is expected that you 225 * will only pass in instances of <code>GregorianCalendar</code> however 226 * this is not validated. 227 * 228 * @param calendar the Calendar to extract fields from 229 * @return the created LocalTime 230 * @throws IllegalArgumentException if the calendar is null 231 * @throws IllegalArgumentException if the date is invalid for the ISO chronology 232 */ 233 public static LocalTime fromCalendarFields(Calendar calendar) { 234 if (calendar == null) { 235 throw new IllegalArgumentException("The calendar must not be null"); 236 } 237 return new LocalTime( 238 calendar.get(Calendar.HOUR_OF_DAY), 239 calendar.get(Calendar.MINUTE), 240 calendar.get(Calendar.SECOND), 241 calendar.get(Calendar.MILLISECOND) 242 ); 243 } 244 245 /** 246 * Constructs a LocalTime from a <code>java.util.Date</code> 247 * using exactly the same field values. 248 * <p> 249 * Each field is queried from the Date and assigned to the LocalTime. 250 * This is useful if you have been using the Date as a local time, 251 * ignoring the zone. 252 * <p> 253 * One advantage of this method is that this method is unaffected if the 254 * version of the time zone data differs between the JDK and Joda-Time. 255 * That is because the local field values are transferred, calculated using 256 * the JDK time zone data and without using the Joda-Time time zone data. 257 * <p> 258 * This factory method always creates a LocalTime with ISO chronology. 259 * 260 * @param date the Date to extract fields from 261 * @return the created LocalTime 262 * @throws IllegalArgumentException if the calendar is null 263 * @throws IllegalArgumentException if the date is invalid for the ISO chronology 264 */ 265 @SuppressWarnings("deprecation") 266 public static LocalTime fromDateFields(Date date) { 267 if (date == null) { 268 throw new IllegalArgumentException("The date must not be null"); 269 } 270 return new LocalTime( 271 date.getHours(), 272 date.getMinutes(), 273 date.getSeconds(), 274 (((int) (date.getTime() % 1000)) + 1000) % 1000 275 ); 276 } 277 278 //----------------------------------------------------------------------- 279 /** 280 * Constructs an instance set to the current local time evaluated using 281 * ISO chronology in the default zone. 282 * <p> 283 * Once the constructor is completed, the zone is no longer used. 284 * 285 * @see #now() 286 */ 287 public LocalTime() { 288 this(DateTimeUtils.currentTimeMillis(), ISOChronology.getInstance()); 289 } 290 291 /** 292 * Constructs an instance set to the current local time evaluated using 293 * ISO chronology in the specified zone. 294 * <p> 295 * If the specified time zone is null, the default zone is used. 296 * Once the constructor is completed, the zone is no longer used. 297 * 298 * @param zone the time zone, null means default zone 299 * @see #now(DateTimeZone) 300 */ 301 public LocalTime(DateTimeZone zone) { 302 this(DateTimeUtils.currentTimeMillis(), ISOChronology.getInstance(zone)); 303 } 304 305 /** 306 * Constructs an instance set to the current local time evaluated using 307 * specified chronology and zone. 308 * <p> 309 * If the chronology is null, ISO chronology in the default time zone is used. 310 * Once the constructor is completed, the zone is no longer used. 311 * 312 * @param chronology the chronology, null means ISOChronology in default zone 313 * @see #now(Chronology) 314 */ 315 public LocalTime(Chronology chronology) { 316 this(DateTimeUtils.currentTimeMillis(), chronology); 317 } 318 319 //----------------------------------------------------------------------- 320 /** 321 * Constructs an instance set to the local time defined by the specified 322 * instant evaluated using ISO chronology in the default zone. 323 * <p> 324 * Once the constructor is completed, the zone is no longer used. 325 * 326 * @param instant the milliseconds from 1970-01-01T00:00:00Z 327 */ 328 public LocalTime(long instant) { 329 this(instant, ISOChronology.getInstance()); 330 } 331 332 /** 333 * Constructs an instance set to the local time defined by the specified 334 * instant evaluated using ISO chronology in the specified zone. 335 * <p> 336 * If the specified time zone is null, the default zone is used. 337 * Once the constructor is completed, the zone is no longer used. 338 * 339 * @param instant the milliseconds from 1970-01-01T00:00:00Z 340 * @param zone the time zone, null means default zone 341 */ 342 public LocalTime(long instant, DateTimeZone zone) { 343 this(instant, ISOChronology.getInstance(zone)); 344 } 345 346 /** 347 * Constructs an instance set to the local time defined by the specified 348 * instant evaluated using the specified chronology. 349 * <p> 350 * If the chronology is null, ISO chronology in the default zone is used. 351 * Once the constructor is completed, the zone is no longer used. 352 * 353 * @param instant the milliseconds from 1970-01-01T00:00:00Z 354 * @param chronology the chronology, null means ISOChronology in default zone 355 */ 356 public LocalTime(long instant, Chronology chronology) { 357 chronology = DateTimeUtils.getChronology(chronology); 358 359 long localMillis = chronology.getZone().getMillisKeepLocal(DateTimeZone.UTC, instant); 360 chronology = chronology.withUTC(); 361 iLocalMillis = chronology.millisOfDay().get(localMillis); 362 iChronology = chronology; 363 } 364 365 //----------------------------------------------------------------------- 366 /** 367 * Constructs an instance from an Object that represents a datetime. 368 * <p> 369 * If the object contains no chronology, <code>ISOChronology</code> is used. 370 * If the object contains no time zone, the default zone is used. 371 * Once the constructor is completed, the zone is no longer used. 372 * <p> 373 * The recognised object types are defined in 374 * {@link org.joda.time.convert.ConverterManager ConverterManager} and 375 * include ReadablePartial, ReadableInstant, String, Calendar and Date. 376 * The String formats are described by {@link ISODateTimeFormat#localTimeParser()}. 377 * The default String converter ignores the zone and only parses the field values. 378 * 379 * @param instant the datetime object 380 * @throws IllegalArgumentException if the instant is invalid 381 */ 382 public LocalTime(Object instant) { 383 this(instant, (Chronology) null); 384 } 385 386 /** 387 * Constructs an instance from an Object that represents a datetime, 388 * forcing the time zone to that specified. 389 * <p> 390 * If the object contains no chronology, <code>ISOChronology</code> is used. 391 * If the specified time zone is null, the default zone is used. 392 * Once the constructor is completed, the zone is no longer used. 393 * <p> 394 * The recognised object types are defined in 395 * {@link org.joda.time.convert.ConverterManager ConverterManager} and 396 * include ReadablePartial, ReadableInstant, String, Calendar and Date. 397 * The String formats are described by {@link ISODateTimeFormat#localTimeParser()}. 398 * The default String converter ignores the zone and only parses the field values. 399 * 400 * @param instant the datetime object 401 * @param zone the time zone 402 * @throws IllegalArgumentException if the instant is invalid 403 */ 404 public LocalTime(Object instant, DateTimeZone zone) { 405 PartialConverter converter = ConverterManager.getInstance().getPartialConverter(instant); 406 Chronology chronology = converter.getChronology(instant, zone); 407 chronology = DateTimeUtils.getChronology(chronology); 408 iChronology = chronology.withUTC(); 409 int[] values = converter.getPartialValues(this, instant, chronology, ISODateTimeFormat.localTimeParser()); 410 iLocalMillis = iChronology.getDateTimeMillis(0L, values[0], values[1], values[2], values[3]); 411 } 412 413 /** 414 * Constructs an instance from an Object that represents a datetime, 415 * using the specified chronology. 416 * <p> 417 * If the chronology is null, ISO in the default time zone is used. 418 * Once the constructor is completed, the zone is no longer used. 419 * <p> 420 * The recognised object types are defined in 421 * {@link org.joda.time.convert.ConverterManager ConverterManager} and 422 * include ReadablePartial, ReadableInstant, String, Calendar and Date. 423 * The String formats are described by {@link ISODateTimeFormat#localTimeParser()}. 424 * The default String converter ignores the zone and only parses the field values. 425 * 426 * @param instant the datetime object 427 * @param chronology the chronology 428 * @throws IllegalArgumentException if the instant is invalid 429 */ 430 public LocalTime(Object instant, Chronology chronology) { 431 PartialConverter converter = ConverterManager.getInstance().getPartialConverter(instant); 432 chronology = converter.getChronology(instant, chronology); 433 chronology = DateTimeUtils.getChronology(chronology); 434 iChronology = chronology.withUTC(); 435 int[] values = converter.getPartialValues(this, instant, chronology, ISODateTimeFormat.localTimeParser()); 436 iLocalMillis = iChronology.getDateTimeMillis(0L, values[0], values[1], values[2], values[3]); 437 } 438 439 //----------------------------------------------------------------------- 440 /** 441 * Constructs an instance set to the specified time 442 * using <code>ISOChronology</code>. 443 * 444 * @param hourOfDay the hour of the day 445 * @param minuteOfHour the minute of the hour 446 */ 447 public LocalTime( 448 int hourOfDay, 449 int minuteOfHour) { 450 this(hourOfDay, minuteOfHour, 0, 0, ISOChronology.getInstanceUTC()); 451 } 452 453 /** 454 * Constructs an instance set to the specified time 455 * using <code>ISOChronology</code>. 456 * 457 * @param hourOfDay the hour of the day 458 * @param minuteOfHour the minute of the hour 459 * @param secondOfMinute the second of the minute 460 */ 461 public LocalTime( 462 int hourOfDay, 463 int minuteOfHour, 464 int secondOfMinute) { 465 this(hourOfDay, minuteOfHour, secondOfMinute, 0, ISOChronology.getInstanceUTC()); 466 } 467 468 /** 469 * Constructs an instance set to the specified time 470 * using <code>ISOChronology</code>. 471 * 472 * @param hourOfDay the hour of the day 473 * @param minuteOfHour the minute of the hour 474 * @param secondOfMinute the second of the minute 475 * @param millisOfSecond the millisecond of the second 476 */ 477 public LocalTime( 478 int hourOfDay, 479 int minuteOfHour, 480 int secondOfMinute, 481 int millisOfSecond) { 482 this(hourOfDay, minuteOfHour, secondOfMinute, 483 millisOfSecond, ISOChronology.getInstanceUTC()); 484 } 485 486 /** 487 * Constructs an instance set to the specified time 488 * using the specified chronology, whose zone is ignored. 489 * <p> 490 * If the chronology is null, <code>ISOChronology</code> is used. 491 * 492 * @param hourOfDay the hour of the day 493 * @param minuteOfHour the minute of the hour 494 * @param secondOfMinute the second of the minute 495 * @param millisOfSecond the millisecond of the second 496 * @param chronology the chronology, null means ISOChronology in default zone 497 */ 498 public LocalTime( 499 int hourOfDay, 500 int minuteOfHour, 501 int secondOfMinute, 502 int millisOfSecond, 503 Chronology chronology) { 504 super(); 505 chronology = DateTimeUtils.getChronology(chronology).withUTC(); 506 long instant = chronology.getDateTimeMillis( 507 0L, hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond); 508 iChronology = chronology; 509 iLocalMillis = instant; 510 } 511 512 /** 513 * Handle broken serialization from other tools. 514 * @return the resolved object, not null 515 */ 516 private Object readResolve() { 517 if (DateTimeZone.UTC.equals(iChronology.getZone()) == false) { 518 return new LocalTime(iLocalMillis, iChronology.withUTC()); 519 } 520 return this; 521 } 522 523 //----------------------------------------------------------------------- 524 /** 525 * Gets the number of fields in this partial, which is four. 526 * The supported fields are HourOfDay, MinuteOfHour, SecondOfMinute 527 * and MillisOfSecond. 528 * 529 * @return the field count, four 530 */ 531 public int size() { 532 return 4; 533 } 534 535 /** 536 * Gets the field for a specific index in the chronology specified. 537 * <p> 538 * This method must not use any instance variables. 539 * 540 * @param index the index to retrieve 541 * @param chrono the chronology to use 542 * @return the field 543 */ 544 protected DateTimeField getField(int index, Chronology chrono) { 545 switch (index) { 546 case HOUR_OF_DAY: 547 return chrono.hourOfDay(); 548 case MINUTE_OF_HOUR: 549 return chrono.minuteOfHour(); 550 case SECOND_OF_MINUTE: 551 return chrono.secondOfMinute(); 552 case MILLIS_OF_SECOND: 553 return chrono.millisOfSecond(); 554 default: 555 throw new IndexOutOfBoundsException("Invalid index: " + index); 556 } 557 } 558 559 /** 560 * Gets the value of the field at the specifed index. 561 * <p> 562 * This method is required to support the <code>ReadablePartial</code> 563 * interface. The supported fields are HourOfDay, MinuteOfHour, 564 * SecondOfMinute and MillisOfSecond. 565 * 566 * @param index the index, zero to three 567 * @return the value 568 * @throws IndexOutOfBoundsException if the index is invalid 569 */ 570 public int getValue(int index) { 571 switch (index) { 572 case HOUR_OF_DAY: 573 return getChronology().hourOfDay().get(getLocalMillis()); 574 case MINUTE_OF_HOUR: 575 return getChronology().minuteOfHour().get(getLocalMillis()); 576 case SECOND_OF_MINUTE: 577 return getChronology().secondOfMinute().get(getLocalMillis()); 578 case MILLIS_OF_SECOND: 579 return getChronology().millisOfSecond().get(getLocalMillis()); 580 default: 581 throw new IndexOutOfBoundsException("Invalid index: " + index); 582 } 583 } 584 585 //----------------------------------------------------------------------- 586 /** 587 * Get the value of one of the fields of time. 588 * <p> 589 * This method gets the value of the specified field. 590 * For example: 591 * <pre> 592 * DateTime dt = new DateTime(); 593 * int hourOfDay = dt.get(DateTimeFieldType.hourOfDay()); 594 * </pre> 595 * 596 * @param fieldType a field type, usually obtained from DateTimeFieldType, not null 597 * @return the value of that field 598 * @throws IllegalArgumentException if the field type is null 599 */ 600 public int get(DateTimeFieldType fieldType) { 601 if (fieldType == null) { 602 throw new IllegalArgumentException("The DateTimeFieldType must not be null"); 603 } 604 if (isSupported(fieldType) == false) { 605 throw new IllegalArgumentException("Field '" + fieldType + "' is not supported"); 606 } 607 return fieldType.getField(getChronology()).get(getLocalMillis()); 608 } 609 610 /** 611 * Checks if the field type specified is supported by this 612 * local time and chronology. 613 * This can be used to avoid exceptions in {@link #get(DateTimeFieldType)}. 614 * 615 * @param type a field type, usually obtained from DateTimeFieldType 616 * @return true if the field type is supported 617 */ 618 public boolean isSupported(DateTimeFieldType type) { 619 if (type == null) { 620 return false; 621 } 622 if (isSupported(type.getDurationType()) == false) { 623 return false; 624 } 625 DurationFieldType range = type.getRangeDurationType(); 626 return (isSupported(range) || range == DurationFieldType.days()); 627 } 628 629 /** 630 * Checks if the duration type specified is supported by this 631 * local time and chronology. 632 * 633 * @param type a duration type, usually obtained from DurationFieldType 634 * @return true if the field type is supported 635 */ 636 public boolean isSupported(DurationFieldType type) { 637 if (type == null) { 638 return false; 639 } 640 DurationField field = type.getField(getChronology()); 641 if (TIME_DURATION_TYPES.contains(type) || 642 field.getUnitMillis() < getChronology().days().getUnitMillis()) { 643 return field.isSupported(); 644 } 645 return false; 646 } 647 648 //----------------------------------------------------------------------- 649 /** 650 * Gets the local milliseconds from the Java epoch 651 * of 1970-01-01T00:00:00 (not fixed to any specific time zone). 652 * 653 * @return the number of milliseconds since 1970-01-01T00:00:00 654 * @since 1.5 (previously private) 655 */ 656 protected long getLocalMillis() { 657 return iLocalMillis; 658 } 659 660 /** 661 * Gets the chronology of the time. 662 * 663 * @return the Chronology that the time is using 664 */ 665 public Chronology getChronology() { 666 return iChronology; 667 } 668 669 //----------------------------------------------------------------------- 670 /** 671 * Compares this ReadablePartial with another returning true if the chronology, 672 * field types and values are equal. 673 * 674 * @param partial an object to check against 675 * @return true if fields and values are equal 676 */ 677 public boolean equals(Object partial) { 678 // override to perform faster 679 if (this == partial) { 680 return true; 681 } 682 if (partial instanceof LocalTime) { 683 LocalTime other = (LocalTime) partial; 684 if (iChronology.equals(other.iChronology)) { 685 return iLocalMillis == other.iLocalMillis; 686 } 687 } 688 return super.equals(partial); 689 } 690 691 /** 692 * Compares this partial with another returning an integer 693 * indicating the order. 694 * <p> 695 * The fields are compared in order, from largest to smallest. 696 * The first field that is non-equal is used to determine the result. 697 * <p> 698 * The specified object must be a partial instance whose field types 699 * match those of this partial. 700 * 701 * @param partial an object to check against 702 * @return negative if this is less, zero if equal, positive if greater 703 * @throws ClassCastException if the partial is the wrong class 704 * or if it has field types that don't match 705 * @throws NullPointerException if the partial is null 706 */ 707 public int compareTo(ReadablePartial partial) { 708 // override to perform faster 709 if (this == partial) { 710 return 0; 711 } 712 if (partial instanceof LocalTime) { 713 LocalTime other = (LocalTime) partial; 714 if (iChronology.equals(other.iChronology)) { 715 return (iLocalMillis < other.iLocalMillis ? -1 : 716 (iLocalMillis == other.iLocalMillis ? 0 : 1)); 717 718 } 719 } 720 return super.compareTo(partial); 721 } 722 723 //----------------------------------------------------------------------- 724 /** 725 * Returns a copy of this time with different local millis. 726 * <p> 727 * The returned object will be a new instance of the same type. 728 * Only the millis will change, the chronology is kept. 729 * The returned object will be either be a new instance or <code>this</code>. 730 * 731 * @param newMillis the new millis, from 1970-01-01T00:00:00 732 * @return a copy of this time with different millis 733 */ 734 LocalTime withLocalMillis(long newMillis) { 735 return (newMillis == getLocalMillis() ? this : new LocalTime(newMillis, getChronology())); 736 } 737 738 //----------------------------------------------------------------------- 739 /** 740 * Returns a copy of this time with the partial set of fields replacing 741 * those from this instance. 742 * <p> 743 * For example, if the partial contains an hour and minute then those two 744 * fields will be changed in the returned instance. 745 * Unsupported fields are ignored. 746 * If the partial is null, then <code>this</code> is returned. 747 * 748 * @param partial the partial set of fields to apply to this time, null ignored 749 * @return a copy of this time with a different set of fields 750 * @throws IllegalArgumentException if any value is invalid 751 */ 752 public LocalTime withFields(ReadablePartial partial) { 753 if (partial == null) { 754 return this; 755 } 756 return withLocalMillis(getChronology().set(partial, getLocalMillis())); 757 } 758 759 /** 760 * Returns a copy of this time with the specified field set 761 * to a new value. 762 * <p> 763 * For example, if the field type is <code>hourOfDay</code> then the hour of day 764 * field would be changed in the returned instance. 765 * If the field type is null, then <code>this</code> is returned. 766 * <p> 767 * These lines are equivalent: 768 * <pre> 769 * LocalTime updated = dt.withHourOfDay(6); 770 * LocalTime updated = dt.withField(DateTimeFieldType.hourOfDay(), 6); 771 * </pre> 772 * 773 * @param fieldType the field type to set, not null 774 * @param value the value to set 775 * @return a copy of this time with the field set 776 * @throws IllegalArgumentException if the value is null or invalid 777 */ 778 public LocalTime withField(DateTimeFieldType fieldType, int value) { 779 if (fieldType == null) { 780 throw new IllegalArgumentException("Field must not be null"); 781 } 782 if (isSupported(fieldType) == false) { 783 throw new IllegalArgumentException("Field '" + fieldType + "' is not supported"); 784 } 785 long instant = fieldType.getField(getChronology()).set(getLocalMillis(), value); 786 return withLocalMillis(instant); 787 } 788 789 /** 790 * Returns a copy of this time with the value of the specified 791 * field increased. 792 * <p> 793 * If the addition is zero or the field is null, then <code>this</code> 794 * is returned. 795 * <p> 796 * If the addition causes the maximum value of the field to be exceeded, 797 * then the value will wrap. Thus 23:59 plus two minutes yields 00:01. 798 * <p> 799 * These lines are equivalent: 800 * <pre> 801 * LocalTime added = dt.plusHours(6); 802 * LocalTime added = dt.withFieldAdded(DurationFieldType.hours(), 6); 803 * </pre> 804 * 805 * @param fieldType the field type to add to, not null 806 * @param amount the amount to add 807 * @return a copy of this time with the field updated 808 * @throws IllegalArgumentException if the value is null or invalid 809 * @throws ArithmeticException if the result exceeds the internal capacity 810 */ 811 public LocalTime withFieldAdded(DurationFieldType fieldType, int amount) { 812 if (fieldType == null) { 813 throw new IllegalArgumentException("Field must not be null"); 814 } 815 if (isSupported(fieldType) == false) { 816 throw new IllegalArgumentException("Field '" + fieldType + "' is not supported"); 817 } 818 if (amount == 0) { 819 return this; 820 } 821 long instant = fieldType.getField(getChronology()).add(getLocalMillis(), amount); 822 return withLocalMillis(instant); 823 } 824 825 //----------------------------------------------------------------------- 826 /** 827 * Returns a copy of this time with the specified period added. 828 * <p> 829 * If the addition is zero, then <code>this</code> is returned. 830 * <p> 831 * This method is typically used to add multiple copies of complex 832 * period instances. Adding one field is best achieved using methods 833 * like {@link #withFieldAdded(DurationFieldType, int)} 834 * or {@link #plusHours(int)}. 835 * 836 * @param period the period to add to this one, null means zero 837 * @param scalar the amount of times to add, such as -1 to subtract once 838 * @return a copy of this time with the period added 839 * @throws ArithmeticException if the result exceeds the internal capacity 840 */ 841 public LocalTime withPeriodAdded(ReadablePeriod period, int scalar) { 842 if (period == null || scalar == 0) { 843 return this; 844 } 845 long instant = getChronology().add(period, getLocalMillis(), scalar); 846 return withLocalMillis(instant); 847 } 848 849 //----------------------------------------------------------------------- 850 /** 851 * Returns a copy of this time with the specified period added. 852 * <p> 853 * If the amount is zero or null, then <code>this</code> is returned. 854 * <p> 855 * This method is typically used to add complex period instances. 856 * Adding one field is best achieved using methods 857 * like {@link #plusHours(int)}. 858 * 859 * @param period the period to add to this one, null means zero 860 * @return a copy of this time with the period added 861 * @throws ArithmeticException if the result exceeds the internal capacity 862 */ 863 public LocalTime plus(ReadablePeriod period) { 864 return withPeriodAdded(period, 1); 865 } 866 867 //----------------------------------------------------------------------- 868 /** 869 * Returns a copy of this time plus the specified number of hours. 870 * <p> 871 * This LocalTime instance is immutable and unaffected by this method call. 872 * <p> 873 * The following three lines are identical in effect: 874 * <pre> 875 * LocalTime added = dt.plusHours(6); 876 * LocalTime added = dt.plus(Period.hours(6)); 877 * LocalTime added = dt.withFieldAdded(DurationFieldType.hours(), 6); 878 * </pre> 879 * 880 * @param hours the amount of hours to add, may be negative 881 * @return the new LocalTime plus the increased hours 882 */ 883 public LocalTime plusHours(int hours) { 884 if (hours == 0) { 885 return this; 886 } 887 long instant = getChronology().hours().add(getLocalMillis(), hours); 888 return withLocalMillis(instant); 889 } 890 891 /** 892 * Returns a copy of this time plus the specified number of minutes. 893 * <p> 894 * This LocalTime instance is immutable and unaffected by this method call. 895 * <p> 896 * The following three lines are identical in effect: 897 * <pre> 898 * LocalTime added = dt.plusMinutes(6); 899 * LocalTime added = dt.plus(Period.minutes(6)); 900 * LocalTime added = dt.withFieldAdded(DurationFieldType.minutes(), 6); 901 * </pre> 902 * 903 * @param minutes the amount of minutes to add, may be negative 904 * @return the new LocalTime plus the increased minutes 905 */ 906 public LocalTime plusMinutes(int minutes) { 907 if (minutes == 0) { 908 return this; 909 } 910 long instant = getChronology().minutes().add(getLocalMillis(), minutes); 911 return withLocalMillis(instant); 912 } 913 914 /** 915 * Returns a copy of this time plus the specified number of seconds. 916 * <p> 917 * This LocalTime instance is immutable and unaffected by this method call. 918 * <p> 919 * The following three lines are identical in effect: 920 * <pre> 921 * LocalTime added = dt.plusSeconds(6); 922 * LocalTime added = dt.plus(Period.seconds(6)); 923 * LocalTime added = dt.withFieldAdded(DurationFieldType.seconds(), 6); 924 * </pre> 925 * 926 * @param seconds the amount of seconds to add, may be negative 927 * @return the new LocalTime plus the increased seconds 928 */ 929 public LocalTime plusSeconds(int seconds) { 930 if (seconds == 0) { 931 return this; 932 } 933 long instant = getChronology().seconds().add(getLocalMillis(), seconds); 934 return withLocalMillis(instant); 935 } 936 937 /** 938 * Returns a copy of this time plus the specified number of millis. 939 * <p> 940 * This LocalTime instance is immutable and unaffected by this method call. 941 * <p> 942 * The following three lines are identical in effect: 943 * <pre> 944 * LocalTime added = dt.plusMillis(6); 945 * LocalTime added = dt.plus(Period.millis(6)); 946 * LocalTime added = dt.withFieldAdded(DurationFieldType.millis(), 6); 947 * </pre> 948 * 949 * @param millis the amount of millis to add, may be negative 950 * @return the new LocalTime plus the increased millis 951 */ 952 public LocalTime plusMillis(int millis) { 953 if (millis == 0) { 954 return this; 955 } 956 long instant = getChronology().millis().add(getLocalMillis(), millis); 957 return withLocalMillis(instant); 958 } 959 960 //----------------------------------------------------------------------- 961 /** 962 * Returns a copy of this time with the specified period taken away. 963 * <p> 964 * If the amount is zero or null, then <code>this</code> is returned. 965 * <p> 966 * This method is typically used to subtract complex period instances. 967 * Subtracting one field is best achieved using methods 968 * like {@link #minusHours(int)}. 969 * 970 * @param period the period to reduce this instant by 971 * @return a copy of this time with the period taken away 972 * @throws ArithmeticException if the result exceeds the internal capacity 973 */ 974 public LocalTime minus(ReadablePeriod period) { 975 return withPeriodAdded(period, -1); 976 } 977 978 //----------------------------------------------------------------------- 979 /** 980 * Returns a copy of this time minus the specified number of hours. 981 * <p> 982 * This LocalTime instance is immutable and unaffected by this method call. 983 * <p> 984 * The following three lines are identical in effect: 985 * <pre> 986 * LocalTime subtracted = dt.minusHours(6); 987 * LocalTime subtracted = dt.minus(Period.hours(6)); 988 * LocalTime subtracted = dt.withFieldAdded(DurationFieldType.hours(), -6); 989 * </pre> 990 * 991 * @param hours the amount of hours to subtract, may be negative 992 * @return the new LocalTime minus the increased hours 993 */ 994 public LocalTime minusHours(int hours) { 995 if (hours == 0) { 996 return this; 997 } 998 long instant = getChronology().hours().subtract(getLocalMillis(), hours); 999 return withLocalMillis(instant); 1000 } 1001 1002 /** 1003 * Returns a copy of this time minus the specified number of minutes. 1004 * <p> 1005 * This LocalTime instance is immutable and unaffected by this method call. 1006 * <p> 1007 * The following three lines are identical in effect: 1008 * <pre> 1009 * LocalTime subtracted = dt.minusMinutes(6); 1010 * LocalTime subtracted = dt.minus(Period.minutes(6)); 1011 * LocalTime subtracted = dt.withFieldAdded(DurationFieldType.minutes(), -6); 1012 * </pre> 1013 * 1014 * @param minutes the amount of minutes to subtract, may be negative 1015 * @return the new LocalTime minus the increased minutes 1016 */ 1017 public LocalTime minusMinutes(int minutes) { 1018 if (minutes == 0) { 1019 return this; 1020 } 1021 long instant = getChronology().minutes().subtract(getLocalMillis(), minutes); 1022 return withLocalMillis(instant); 1023 } 1024 1025 /** 1026 * Returns a copy of this time minus the specified number of seconds. 1027 * <p> 1028 * This LocalTime instance is immutable and unaffected by this method call. 1029 * <p> 1030 * The following three lines are identical in effect: 1031 * <pre> 1032 * LocalTime subtracted = dt.minusSeconds(6); 1033 * LocalTime subtracted = dt.minus(Period.seconds(6)); 1034 * LocalTime subtracted = dt.withFieldAdded(DurationFieldType.seconds(), -6); 1035 * </pre> 1036 * 1037 * @param seconds the amount of seconds to subtract, may be negative 1038 * @return the new LocalTime minus the increased seconds 1039 */ 1040 public LocalTime minusSeconds(int seconds) { 1041 if (seconds == 0) { 1042 return this; 1043 } 1044 long instant = getChronology().seconds().subtract(getLocalMillis(), seconds); 1045 return withLocalMillis(instant); 1046 } 1047 1048 /** 1049 * Returns a copy of this time minus the specified number of millis. 1050 * <p> 1051 * This LocalTime instance is immutable and unaffected by this method call. 1052 * <p> 1053 * The following three lines are identical in effect: 1054 * <pre> 1055 * LocalTime subtracted = dt.minusMillis(6); 1056 * LocalTime subtracted = dt.minus(Period.millis(6)); 1057 * LocalTime subtracted = dt.withFieldAdded(DurationFieldType.millis(), -6); 1058 * </pre> 1059 * 1060 * @param millis the amount of millis to subtract, may be negative 1061 * @return the new LocalTime minus the increased millis 1062 */ 1063 public LocalTime minusMillis(int millis) { 1064 if (millis == 0) { 1065 return this; 1066 } 1067 long instant = getChronology().millis().subtract(getLocalMillis(), millis); 1068 return withLocalMillis(instant); 1069 } 1070 1071 //----------------------------------------------------------------------- 1072 /** 1073 * Gets the property object for the specified type, which contains 1074 * many useful methods. 1075 * 1076 * @param fieldType the field type to get the chronology for 1077 * @return the property object 1078 * @throws IllegalArgumentException if the field is null or unsupported 1079 */ 1080 public Property property(DateTimeFieldType fieldType) { 1081 if (fieldType == null) { 1082 throw new IllegalArgumentException("The DateTimeFieldType must not be null"); 1083 } 1084 if (isSupported(fieldType) == false) { 1085 throw new IllegalArgumentException("Field '" + fieldType + "' is not supported"); 1086 } 1087 return new Property(this, fieldType.getField(getChronology())); 1088 } 1089 1090 //----------------------------------------------------------------------- 1091 /** 1092 * Get the hour of day field value. 1093 * 1094 * @return the hour of day 1095 */ 1096 public int getHourOfDay() { 1097 return getChronology().hourOfDay().get(getLocalMillis()); 1098 } 1099 1100 /** 1101 * Get the minute of hour field value. 1102 * 1103 * @return the minute of hour 1104 */ 1105 public int getMinuteOfHour() { 1106 return getChronology().minuteOfHour().get(getLocalMillis()); 1107 } 1108 1109 /** 1110 * Get the second of minute field value. 1111 * 1112 * @return the second of minute 1113 */ 1114 public int getSecondOfMinute() { 1115 return getChronology().secondOfMinute().get(getLocalMillis()); 1116 } 1117 1118 /** 1119 * Get the millis of second field value. 1120 * 1121 * @return the millis of second 1122 */ 1123 public int getMillisOfSecond() { 1124 return getChronology().millisOfSecond().get(getLocalMillis()); 1125 } 1126 1127 /** 1128 * Get the millis of day field value. 1129 * 1130 * @return the millis of day 1131 */ 1132 public int getMillisOfDay() { 1133 return getChronology().millisOfDay().get(getLocalMillis()); 1134 } 1135 1136 //----------------------------------------------------------------------- 1137 /** 1138 * Returns a copy of this time with the hour of day field updated. 1139 * <p> 1140 * LocalTime is immutable, so there are no set methods. 1141 * Instead, this method returns a new instance with the value of 1142 * hour of day changed. 1143 * 1144 * @param hour the hour of day to set 1145 * @return a copy of this object with the field set 1146 * @throws IllegalArgumentException if the value is invalid 1147 */ 1148 public LocalTime withHourOfDay(int hour) { 1149 return withLocalMillis(getChronology().hourOfDay().set(getLocalMillis(), hour)); 1150 } 1151 1152 /** 1153 * Returns a copy of this time with the minute of hour field updated. 1154 * <p> 1155 * LocalTime is immutable, so there are no set methods. 1156 * Instead, this method returns a new instance with the value of 1157 * minute of hour changed. 1158 * 1159 * @param minute the minute of hour to set 1160 * @return a copy of this object with the field set 1161 * @throws IllegalArgumentException if the value is invalid 1162 */ 1163 public LocalTime withMinuteOfHour(int minute) { 1164 return withLocalMillis(getChronology().minuteOfHour().set(getLocalMillis(), minute)); 1165 } 1166 1167 /** 1168 * Returns a copy of this time with the second of minute field updated. 1169 * <p> 1170 * LocalTime is immutable, so there are no set methods. 1171 * Instead, this method returns a new instance with the value of 1172 * second of minute changed. 1173 * 1174 * @param second the second of minute to set 1175 * @return a copy of this object with the field set 1176 * @throws IllegalArgumentException if the value is invalid 1177 */ 1178 public LocalTime withSecondOfMinute(int second) { 1179 return withLocalMillis(getChronology().secondOfMinute().set(getLocalMillis(), second)); 1180 } 1181 1182 /** 1183 * Returns a copy of this time with the millis of second field updated. 1184 * <p> 1185 * LocalTime is immutable, so there are no set methods. 1186 * Instead, this method returns a new instance with the value of 1187 * millis of second changed. 1188 * 1189 * @param millis the millis of second to set 1190 * @return a copy of this object with the field set 1191 * @throws IllegalArgumentException if the value is invalid 1192 */ 1193 public LocalTime withMillisOfSecond(int millis) { 1194 return withLocalMillis(getChronology().millisOfSecond().set(getLocalMillis(), millis)); 1195 } 1196 1197 /** 1198 * Returns a copy of this time with the millis of day field updated. 1199 * <p> 1200 * LocalTime is immutable, so there are no set methods. 1201 * Instead, this method returns a new instance with the value of 1202 * millis of day changed. 1203 * 1204 * @param millis the millis of day to set 1205 * @return a copy of this object with the field set 1206 * @throws IllegalArgumentException if the value is invalid 1207 */ 1208 public LocalTime withMillisOfDay(int millis) { 1209 return withLocalMillis(getChronology().millisOfDay().set(getLocalMillis(), millis)); 1210 } 1211 1212 //----------------------------------------------------------------------- 1213 /** 1214 * Get the hour of day field property which provides access to advanced functionality. 1215 * 1216 * @return the hour of day property 1217 */ 1218 public Property hourOfDay() { 1219 return new Property(this, getChronology().hourOfDay()); 1220 } 1221 1222 /** 1223 * Get the minute of hour field property which provides access to advanced functionality. 1224 * 1225 * @return the minute of hour property 1226 */ 1227 public Property minuteOfHour() { 1228 return new Property(this, getChronology().minuteOfHour()); 1229 } 1230 1231 /** 1232 * Get the second of minute field property which provides access to advanced functionality. 1233 * 1234 * @return the second of minute property 1235 */ 1236 public Property secondOfMinute() { 1237 return new Property(this, getChronology().secondOfMinute()); 1238 } 1239 1240 /** 1241 * Get the millis of second property which provides access to advanced functionality. 1242 * 1243 * @return the millis of second property 1244 */ 1245 public Property millisOfSecond() { 1246 return new Property(this, getChronology().millisOfSecond()); 1247 } 1248 1249 /** 1250 * Get the millis of day property which provides access to advanced functionality. 1251 * 1252 * @return the millis of day property 1253 */ 1254 public Property millisOfDay() { 1255 return new Property(this, getChronology().millisOfDay()); 1256 } 1257 1258 //----------------------------------------------------------------------- 1259 /** 1260 * Converts this LocalTime to a full datetime using the default time zone 1261 * setting the time fields from this instance and the date fields from 1262 * the current date. 1263 * 1264 * @return this time as a datetime using todays date 1265 */ 1266 public DateTime toDateTimeToday() { 1267 return toDateTimeToday(null); 1268 } 1269 1270 /** 1271 * Converts this LocalTime to a full datetime using the specified time zone 1272 * setting the time fields from this instance and the date fields from 1273 * the current time. 1274 * <p> 1275 * This method uses the chronology from this instance plus the time zone 1276 * specified. 1277 * 1278 * @param zone the zone to use, null means default 1279 * @return this time as a datetime using todays date 1280 */ 1281 public DateTime toDateTimeToday(DateTimeZone zone) { 1282 Chronology chrono = getChronology().withZone(zone); 1283 long instantMillis = DateTimeUtils.currentTimeMillis(); 1284 long resolved = chrono.set(this, instantMillis); 1285 return new DateTime(resolved, chrono); 1286 } 1287 1288 //----------------------------------------------------------------------- 1289 /** 1290 * Output the time in ISO8601 format (HH:mm:ss.SSSZZ). 1291 * 1292 * @return ISO8601 time formatted string. 1293 */ 1294 @ToString 1295 public String toString() { 1296 return ISODateTimeFormat.time().print(this); 1297 } 1298 1299 /** 1300 * Output the time using the specified format pattern. 1301 * 1302 * @param pattern the pattern specification, null means use <code>toString</code> 1303 * @see org.joda.time.format.DateTimeFormat 1304 */ 1305 public String toString(String pattern) { 1306 if (pattern == null) { 1307 return toString(); 1308 } 1309 return DateTimeFormat.forPattern(pattern).print(this); 1310 } 1311 1312 /** 1313 * Output the time using the specified format pattern. 1314 * 1315 * @param pattern the pattern specification, null means use <code>toString</code> 1316 * @param locale Locale to use, null means default 1317 * @see org.joda.time.format.DateTimeFormat 1318 */ 1319 public String toString(String pattern, Locale locale) throws IllegalArgumentException { 1320 if (pattern == null) { 1321 return toString(); 1322 } 1323 return DateTimeFormat.forPattern(pattern).withLocale(locale).print(this); 1324 } 1325 1326 //----------------------------------------------------------------------- 1327 /** 1328 * LocalTime.Property binds a LocalTime to a DateTimeField allowing 1329 * powerful datetime functionality to be easily accessed. 1330 * <p> 1331 * The simplest use of this class is as an alternative get method, here used to 1332 * get the minute '30'. 1333 * <pre> 1334 * LocalTime dt = new LocalTime(12, 30); 1335 * int year = dt.minuteOfHour().get(); 1336 * </pre> 1337 * <p> 1338 * Methods are also provided that allow time modification. These return 1339 * new instances of LocalTime - they do not modify the original. The example 1340 * below yields two independent immutable date objects 2 hours apart. 1341 * <pre> 1342 * LocalTime dt1230 = new LocalTime(12, 30); 1343 * LocalTime dt1430 = dt1230.hourOfDay().setCopy(14); 1344 * </pre> 1345 * <p> 1346 * LocalTime.Property itself is thread-safe and immutable, as well as the 1347 * LocalTime being operated on. 1348 * 1349 * @author Stephen Colebourne 1350 * @author Brian S O'Neill 1351 * @since 1.3 1352 */ 1353 public static final class Property extends AbstractReadableInstantFieldProperty { 1354 1355 /** Serialization version */ 1356 private static final long serialVersionUID = -325842547277223L; 1357 1358 /** The instant this property is working against */ 1359 private transient LocalTime iInstant; 1360 /** The field this property is working against */ 1361 private transient DateTimeField iField; 1362 1363 /** 1364 * Constructor. 1365 * 1366 * @param instant the instant to set 1367 * @param field the field to use 1368 */ 1369 Property(LocalTime instant, DateTimeField field) { 1370 super(); 1371 iInstant = instant; 1372 iField = field; 1373 } 1374 1375 /** 1376 * Writes the property in a safe serialization format. 1377 */ 1378 private void writeObject(ObjectOutputStream oos) throws IOException { 1379 oos.writeObject(iInstant); 1380 oos.writeObject(iField.getType()); 1381 } 1382 1383 /** 1384 * Reads the property from a safe serialization format. 1385 */ 1386 private void readObject(ObjectInputStream oos) throws IOException, ClassNotFoundException { 1387 iInstant = (LocalTime) oos.readObject(); 1388 DateTimeFieldType type = (DateTimeFieldType) oos.readObject(); 1389 iField = type.getField(iInstant.getChronology()); 1390 } 1391 1392 //----------------------------------------------------------------------- 1393 /** 1394 * Gets the field being used. 1395 * 1396 * @return the field 1397 */ 1398 public DateTimeField getField() { 1399 return iField; 1400 } 1401 1402 /** 1403 * Gets the milliseconds of the time that this property is linked to. 1404 * 1405 * @return the milliseconds 1406 */ 1407 protected long getMillis() { 1408 return iInstant.getLocalMillis(); 1409 } 1410 1411 /** 1412 * Gets the chronology of the datetime that this property is linked to. 1413 * 1414 * @return the chronology 1415 * @since 1.4 1416 */ 1417 protected Chronology getChronology() { 1418 return iInstant.getChronology(); 1419 } 1420 1421 /** 1422 * Gets the LocalTime object linked to this property. 1423 * 1424 * @return the linked LocalTime 1425 */ 1426 public LocalTime getLocalTime() { 1427 return iInstant; 1428 } 1429 1430 //----------------------------------------------------------------------- 1431 /** 1432 * Adds to this field in a copy of this LocalTime. 1433 * <p> 1434 * The LocalTime attached to this property is unchanged by this call. 1435 * 1436 * @param value the value to add to the field in the copy 1437 * @return a copy of the LocalTime with the field value changed 1438 */ 1439 public LocalTime addCopy(int value) { 1440 return iInstant.withLocalMillis(iField.add(iInstant.getLocalMillis(), value)); 1441 } 1442 1443 /** 1444 * Adds to this field in a copy of this LocalTime. 1445 * If the addition exceeds the maximum value (eg. 23:59) it will 1446 * wrap to the minimum value (eg. 00:00). 1447 * <p> 1448 * The LocalTime attached to this property is unchanged by this call. 1449 * 1450 * @param value the value to add to the field in the copy 1451 * @return a copy of the LocalTime with the field value changed 1452 */ 1453 public LocalTime addCopy(long value) { 1454 return iInstant.withLocalMillis(iField.add(iInstant.getLocalMillis(), value)); 1455 } 1456 1457 /** 1458 * Adds to this field in a copy of this LocalTime. 1459 * If the addition exceeds the maximum value (eg. 23:59) then 1460 * an exception will be thrown. 1461 * Contrast this behaviour to {@link #addCopy(int)}. 1462 * <p> 1463 * The LocalTime attached to this property is unchanged by this call. 1464 * 1465 * @param value the value to add to the field in the copy 1466 * @return a copy of the LocalTime with the field value changed 1467 * @throws IllegalArgumentException if the result is invalid 1468 */ 1469 public LocalTime addNoWrapToCopy(int value) { 1470 long millis = iField.add(iInstant.getLocalMillis(), value); 1471 long rounded = iInstant.getChronology().millisOfDay().get(millis); 1472 if (rounded != millis) { 1473 throw new IllegalArgumentException("The addition exceeded the boundaries of LocalTime"); 1474 } 1475 return iInstant.withLocalMillis(millis); 1476 } 1477 1478 /** 1479 * Adds to this field, possibly wrapped, in a copy of this LocalTime. 1480 * A field wrapped operation only changes this field. 1481 * Thus 10:59 plusWrapField one minute goes to 10:00. 1482 * <p> 1483 * The LocalTime attached to this property is unchanged by this call. 1484 * 1485 * @param value the value to add to the field in the copy 1486 * @return a copy of the LocalTime with the field value changed 1487 * @throws IllegalArgumentException if the value isn't valid 1488 */ 1489 public LocalTime addWrapFieldToCopy(int value) { 1490 return iInstant.withLocalMillis(iField.addWrapField(iInstant.getLocalMillis(), value)); 1491 } 1492 1493 //----------------------------------------------------------------------- 1494 /** 1495 * Sets this field in a copy of the LocalTime. 1496 * <p> 1497 * The LocalTime attached to this property is unchanged by this call. 1498 * 1499 * @param value the value to set the field in the copy to 1500 * @return a copy of the LocalTime with the field value changed 1501 * @throws IllegalArgumentException if the value isn't valid 1502 */ 1503 public LocalTime setCopy(int value) { 1504 return iInstant.withLocalMillis(iField.set(iInstant.getLocalMillis(), value)); 1505 } 1506 1507 /** 1508 * Sets this field in a copy of the LocalTime to a parsed text value. 1509 * <p> 1510 * The LocalTime attached to this property is unchanged by this call. 1511 * 1512 * @param text the text value to set 1513 * @param locale optional locale to use for selecting a text symbol 1514 * @return a copy of the LocalTime with the field value changed 1515 * @throws IllegalArgumentException if the text value isn't valid 1516 */ 1517 public LocalTime setCopy(String text, Locale locale) { 1518 return iInstant.withLocalMillis(iField.set(iInstant.getLocalMillis(), text, locale)); 1519 } 1520 1521 /** 1522 * Sets this field in a copy of the LocalTime to a parsed text value. 1523 * <p> 1524 * The LocalTime attached to this property is unchanged by this call. 1525 * 1526 * @param text the text value to set 1527 * @return a copy of the LocalTime with the field value changed 1528 * @throws IllegalArgumentException if the text value isn't valid 1529 */ 1530 public LocalTime setCopy(String text) { 1531 return setCopy(text, null); 1532 } 1533 1534 //----------------------------------------------------------------------- 1535 /** 1536 * Returns a new LocalTime with this field set to the maximum value 1537 * for this field. 1538 * <p> 1539 * The LocalTime attached to this property is unchanged by this call. 1540 * 1541 * @return a copy of the LocalTime with this field set to its maximum 1542 */ 1543 public LocalTime withMaximumValue() { 1544 return setCopy(getMaximumValue()); 1545 } 1546 1547 /** 1548 * Returns a new LocalTime with this field set to the minimum value 1549 * for this field. 1550 * <p> 1551 * The LocalTime attached to this property is unchanged by this call. 1552 * 1553 * @return a copy of the LocalTime with this field set to its minimum 1554 */ 1555 public LocalTime withMinimumValue() { 1556 return setCopy(getMinimumValue()); 1557 } 1558 1559 //----------------------------------------------------------------------- 1560 /** 1561 * Rounds to the lowest whole unit of this field on a copy of this 1562 * LocalTime. 1563 * <p> 1564 * For example, rounding floor on the hourOfDay field of a LocalTime 1565 * where the time is 10:30 would result in new LocalTime with the 1566 * time of 10:00. 1567 * 1568 * @return a copy of the LocalTime with the field value changed 1569 */ 1570 public LocalTime roundFloorCopy() { 1571 return iInstant.withLocalMillis(iField.roundFloor(iInstant.getLocalMillis())); 1572 } 1573 1574 /** 1575 * Rounds to the highest whole unit of this field on a copy of this 1576 * LocalTime. 1577 * <p> 1578 * For example, rounding floor on the hourOfDay field of a LocalTime 1579 * where the time is 10:30 would result in new LocalTime with the 1580 * time of 11:00. 1581 * 1582 * @return a copy of the LocalTime with the field value changed 1583 */ 1584 public LocalTime roundCeilingCopy() { 1585 return iInstant.withLocalMillis(iField.roundCeiling(iInstant.getLocalMillis())); 1586 } 1587 1588 /** 1589 * Rounds to the nearest whole unit of this field on a copy of this 1590 * LocalTime, favoring the floor if halfway. 1591 * 1592 * @return a copy of the LocalTime with the field value changed 1593 */ 1594 public LocalTime roundHalfFloorCopy() { 1595 return iInstant.withLocalMillis(iField.roundHalfFloor(iInstant.getLocalMillis())); 1596 } 1597 1598 /** 1599 * Rounds to the nearest whole unit of this field on a copy of this 1600 * LocalTime, favoring the ceiling if halfway. 1601 * 1602 * @return a copy of the LocalTime with the field value changed 1603 */ 1604 public LocalTime roundHalfCeilingCopy() { 1605 return iInstant.withLocalMillis(iField.roundHalfCeiling(iInstant.getLocalMillis())); 1606 } 1607 1608 /** 1609 * Rounds to the nearest whole unit of this field on a copy of this 1610 * LocalTime. If halfway, the ceiling is favored over the floor 1611 * only if it makes this field's value even. 1612 * 1613 * @return a copy of the LocalTime with the field value changed 1614 */ 1615 public LocalTime roundHalfEvenCopy() { 1616 return iInstant.withLocalMillis(iField.roundHalfEven(iInstant.getLocalMillis())); 1617 } 1618 } 1619 1620 }