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, from 0 to 23 445 * @param minuteOfHour the minute of the hour, from 0 to 59 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, from 0 to 23 458 * @param minuteOfHour the minute of the hour, from 0 to 59 459 * @param secondOfMinute the second of the minute, from 0 to 59 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, from 0 to 23 473 * @param minuteOfHour the minute of the hour, from 0 to 59 474 * @param secondOfMinute the second of the minute, from 0 to 59 475 * @param millisOfSecond the millisecond of the second, from 0 to 999 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, valid values defined by the chronology 493 * @param minuteOfHour the minute of the hour, valid values defined by the chronology 494 * @param secondOfMinute the second of the minute, valid values defined by the chronology 495 * @param millisOfSecond the millisecond of the second, valid values defined by the chronology 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 (iChronology == null) { 518 return new LocalTime(iLocalMillis, ISOChronology.getInstanceUTC()); 519 } 520 if (DateTimeZone.UTC.equals(iChronology.getZone()) == false) { 521 return new LocalTime(iLocalMillis, iChronology.withUTC()); 522 } 523 return this; 524 } 525 526 //----------------------------------------------------------------------- 527 /** 528 * Gets the number of fields in this partial, which is four. 529 * The supported fields are HourOfDay, MinuteOfHour, SecondOfMinute 530 * and MillisOfSecond. 531 * 532 * @return the field count, four 533 */ 534 public int size() { 535 return 4; 536 } 537 538 /** 539 * Gets the field for a specific index in the chronology specified. 540 * <p> 541 * This method must not use any instance variables. 542 * 543 * @param index the index to retrieve 544 * @param chrono the chronology to use 545 * @return the field 546 */ 547 protected DateTimeField getField(int index, Chronology chrono) { 548 switch (index) { 549 case HOUR_OF_DAY: 550 return chrono.hourOfDay(); 551 case MINUTE_OF_HOUR: 552 return chrono.minuteOfHour(); 553 case SECOND_OF_MINUTE: 554 return chrono.secondOfMinute(); 555 case MILLIS_OF_SECOND: 556 return chrono.millisOfSecond(); 557 default: 558 throw new IndexOutOfBoundsException("Invalid index: " + index); 559 } 560 } 561 562 /** 563 * Gets the value of the field at the specifed index. 564 * <p> 565 * This method is required to support the <code>ReadablePartial</code> 566 * interface. The supported fields are HourOfDay, MinuteOfHour, 567 * SecondOfMinute and MillisOfSecond. 568 * 569 * @param index the index, zero to three 570 * @return the value 571 * @throws IndexOutOfBoundsException if the index is invalid 572 */ 573 public int getValue(int index) { 574 switch (index) { 575 case HOUR_OF_DAY: 576 return getChronology().hourOfDay().get(getLocalMillis()); 577 case MINUTE_OF_HOUR: 578 return getChronology().minuteOfHour().get(getLocalMillis()); 579 case SECOND_OF_MINUTE: 580 return getChronology().secondOfMinute().get(getLocalMillis()); 581 case MILLIS_OF_SECOND: 582 return getChronology().millisOfSecond().get(getLocalMillis()); 583 default: 584 throw new IndexOutOfBoundsException("Invalid index: " + index); 585 } 586 } 587 588 //----------------------------------------------------------------------- 589 /** 590 * Get the value of one of the fields of time. 591 * <p> 592 * This method gets the value of the specified field. 593 * For example: 594 * <pre> 595 * DateTime dt = new DateTime(); 596 * int hourOfDay = dt.get(DateTimeFieldType.hourOfDay()); 597 * </pre> 598 * 599 * @param fieldType a field type, usually obtained from DateTimeFieldType, not null 600 * @return the value of that field 601 * @throws IllegalArgumentException if the field type is null 602 */ 603 public int get(DateTimeFieldType fieldType) { 604 if (fieldType == null) { 605 throw new IllegalArgumentException("The DateTimeFieldType must not be null"); 606 } 607 if (isSupported(fieldType) == false) { 608 throw new IllegalArgumentException("Field '" + fieldType + "' is not supported"); 609 } 610 return fieldType.getField(getChronology()).get(getLocalMillis()); 611 } 612 613 /** 614 * Checks if the field type specified is supported by this 615 * local time and chronology. 616 * This can be used to avoid exceptions in {@link #get(DateTimeFieldType)}. 617 * 618 * @param type a field type, usually obtained from DateTimeFieldType 619 * @return true if the field type is supported 620 */ 621 public boolean isSupported(DateTimeFieldType type) { 622 if (type == null) { 623 return false; 624 } 625 if (isSupported(type.getDurationType()) == false) { 626 return false; 627 } 628 DurationFieldType range = type.getRangeDurationType(); 629 return (isSupported(range) || range == DurationFieldType.days()); 630 } 631 632 /** 633 * Checks if the duration type specified is supported by this 634 * local time and chronology. 635 * 636 * @param type a duration type, usually obtained from DurationFieldType 637 * @return true if the field type is supported 638 */ 639 public boolean isSupported(DurationFieldType type) { 640 if (type == null) { 641 return false; 642 } 643 DurationField field = type.getField(getChronology()); 644 if (TIME_DURATION_TYPES.contains(type) || 645 field.getUnitMillis() < getChronology().days().getUnitMillis()) { 646 return field.isSupported(); 647 } 648 return false; 649 } 650 651 //----------------------------------------------------------------------- 652 /** 653 * Gets the local milliseconds from the Java epoch 654 * of 1970-01-01T00:00:00 (not fixed to any specific time zone). 655 * 656 * @return the number of milliseconds since 1970-01-01T00:00:00 657 * @since 1.5 (previously private) 658 */ 659 protected long getLocalMillis() { 660 return iLocalMillis; 661 } 662 663 /** 664 * Gets the chronology of the time. 665 * 666 * @return the Chronology that the time is using 667 */ 668 public Chronology getChronology() { 669 return iChronology; 670 } 671 672 //----------------------------------------------------------------------- 673 /** 674 * Compares this ReadablePartial with another returning true if the chronology, 675 * field types and values are equal. 676 * 677 * @param partial an object to check against 678 * @return true if fields and values are equal 679 */ 680 public boolean equals(Object partial) { 681 // override to perform faster 682 if (this == partial) { 683 return true; 684 } 685 if (partial instanceof LocalTime) { 686 LocalTime other = (LocalTime) partial; 687 if (iChronology.equals(other.iChronology)) { 688 return iLocalMillis == other.iLocalMillis; 689 } 690 } 691 return super.equals(partial); 692 } 693 694 /** 695 * Compares this partial with another returning an integer 696 * indicating the order. 697 * <p> 698 * The fields are compared in order, from largest to smallest. 699 * The first field that is non-equal is used to determine the result. 700 * <p> 701 * The specified object must be a partial instance whose field types 702 * match those of this partial. 703 * 704 * @param partial an object to check against 705 * @return negative if this is less, zero if equal, positive if greater 706 * @throws ClassCastException if the partial is the wrong class 707 * or if it has field types that don't match 708 * @throws NullPointerException if the partial is null 709 */ 710 public int compareTo(ReadablePartial partial) { 711 // override to perform faster 712 if (this == partial) { 713 return 0; 714 } 715 if (partial instanceof LocalTime) { 716 LocalTime other = (LocalTime) partial; 717 if (iChronology.equals(other.iChronology)) { 718 return (iLocalMillis < other.iLocalMillis ? -1 : 719 (iLocalMillis == other.iLocalMillis ? 0 : 1)); 720 721 } 722 } 723 return super.compareTo(partial); 724 } 725 726 //----------------------------------------------------------------------- 727 /** 728 * Returns a copy of this time with different local millis. 729 * <p> 730 * The returned object will be a new instance of the same type. 731 * Only the millis will change, the chronology is kept. 732 * The returned object will be either be a new instance or <code>this</code>. 733 * 734 * @param newMillis the new millis, from 1970-01-01T00:00:00 735 * @return a copy of this time with different millis 736 */ 737 LocalTime withLocalMillis(long newMillis) { 738 return (newMillis == getLocalMillis() ? this : new LocalTime(newMillis, getChronology())); 739 } 740 741 //----------------------------------------------------------------------- 742 /** 743 * Returns a copy of this time with the partial set of fields replacing 744 * those from this instance. 745 * <p> 746 * For example, if the partial contains an hour and minute then those two 747 * fields will be changed in the returned instance. 748 * Unsupported fields are ignored. 749 * If the partial is null, then <code>this</code> is returned. 750 * 751 * @param partial the partial set of fields to apply to this time, null ignored 752 * @return a copy of this time with a different set of fields 753 * @throws IllegalArgumentException if any value is invalid 754 */ 755 public LocalTime withFields(ReadablePartial partial) { 756 if (partial == null) { 757 return this; 758 } 759 return withLocalMillis(getChronology().set(partial, getLocalMillis())); 760 } 761 762 /** 763 * Returns a copy of this time with the specified field set 764 * to a new value. 765 * <p> 766 * For example, if the field type is <code>hourOfDay</code> then the hour of day 767 * field would be changed in the returned instance. 768 * If the field type is null, then <code>this</code> is returned. 769 * <p> 770 * These lines are equivalent: 771 * <pre> 772 * LocalTime updated = dt.withHourOfDay(6); 773 * LocalTime updated = dt.withField(DateTimeFieldType.hourOfDay(), 6); 774 * </pre> 775 * 776 * @param fieldType the field type to set, not null 777 * @param value the value to set 778 * @return a copy of this time with the field set 779 * @throws IllegalArgumentException if the value is null or invalid 780 */ 781 public LocalTime withField(DateTimeFieldType fieldType, int value) { 782 if (fieldType == null) { 783 throw new IllegalArgumentException("Field must not be null"); 784 } 785 if (isSupported(fieldType) == false) { 786 throw new IllegalArgumentException("Field '" + fieldType + "' is not supported"); 787 } 788 long instant = fieldType.getField(getChronology()).set(getLocalMillis(), value); 789 return withLocalMillis(instant); 790 } 791 792 /** 793 * Returns a copy of this time with the value of the specified 794 * field increased. 795 * <p> 796 * If the addition is zero or the field is null, then <code>this</code> 797 * is returned. 798 * <p> 799 * If the addition causes the maximum value of the field to be exceeded, 800 * then the value will wrap. Thus 23:59 plus two minutes yields 00:01. 801 * <p> 802 * These lines are equivalent: 803 * <pre> 804 * LocalTime added = dt.plusHours(6); 805 * LocalTime added = dt.withFieldAdded(DurationFieldType.hours(), 6); 806 * </pre> 807 * 808 * @param fieldType the field type to add to, not null 809 * @param amount the amount to add 810 * @return a copy of this time with the field updated 811 * @throws IllegalArgumentException if the value is null or invalid 812 * @throws ArithmeticException if the result exceeds the internal capacity 813 */ 814 public LocalTime withFieldAdded(DurationFieldType fieldType, int amount) { 815 if (fieldType == null) { 816 throw new IllegalArgumentException("Field must not be null"); 817 } 818 if (isSupported(fieldType) == false) { 819 throw new IllegalArgumentException("Field '" + fieldType + "' is not supported"); 820 } 821 if (amount == 0) { 822 return this; 823 } 824 long instant = fieldType.getField(getChronology()).add(getLocalMillis(), amount); 825 return withLocalMillis(instant); 826 } 827 828 //----------------------------------------------------------------------- 829 /** 830 * Returns a copy of this time with the specified period added. 831 * <p> 832 * If the addition is zero, then <code>this</code> is returned. 833 * <p> 834 * This method is typically used to add multiple copies of complex 835 * period instances. Adding one field is best achieved using methods 836 * like {@link #withFieldAdded(DurationFieldType, int)} 837 * or {@link #plusHours(int)}. 838 * 839 * @param period the period to add to this one, null means zero 840 * @param scalar the amount of times to add, such as -1 to subtract once 841 * @return a copy of this time with the period added 842 * @throws ArithmeticException if the result exceeds the internal capacity 843 */ 844 public LocalTime withPeriodAdded(ReadablePeriod period, int scalar) { 845 if (period == null || scalar == 0) { 846 return this; 847 } 848 long instant = getChronology().add(period, getLocalMillis(), scalar); 849 return withLocalMillis(instant); 850 } 851 852 //----------------------------------------------------------------------- 853 /** 854 * Returns a copy of this time with the specified period added. 855 * <p> 856 * If the amount is zero or null, then <code>this</code> is returned. 857 * <p> 858 * This method is typically used to add complex period instances. 859 * Adding one field is best achieved using methods 860 * like {@link #plusHours(int)}. 861 * 862 * @param period the period to add to this one, null means zero 863 * @return a copy of this time with the period added 864 * @throws ArithmeticException if the result exceeds the internal capacity 865 */ 866 public LocalTime plus(ReadablePeriod period) { 867 return withPeriodAdded(period, 1); 868 } 869 870 //----------------------------------------------------------------------- 871 /** 872 * Returns a copy of this time plus the specified number of hours. 873 * <p> 874 * This LocalTime instance is immutable and unaffected by this method call. 875 * <p> 876 * The following three lines are identical in effect: 877 * <pre> 878 * LocalTime added = dt.plusHours(6); 879 * LocalTime added = dt.plus(Period.hours(6)); 880 * LocalTime added = dt.withFieldAdded(DurationFieldType.hours(), 6); 881 * </pre> 882 * 883 * @param hours the amount of hours to add, may be negative 884 * @return the new LocalTime plus the increased hours 885 */ 886 public LocalTime plusHours(int hours) { 887 if (hours == 0) { 888 return this; 889 } 890 long instant = getChronology().hours().add(getLocalMillis(), hours); 891 return withLocalMillis(instant); 892 } 893 894 /** 895 * Returns a copy of this time plus the specified number of minutes. 896 * <p> 897 * This LocalTime instance is immutable and unaffected by this method call. 898 * <p> 899 * The following three lines are identical in effect: 900 * <pre> 901 * LocalTime added = dt.plusMinutes(6); 902 * LocalTime added = dt.plus(Period.minutes(6)); 903 * LocalTime added = dt.withFieldAdded(DurationFieldType.minutes(), 6); 904 * </pre> 905 * 906 * @param minutes the amount of minutes to add, may be negative 907 * @return the new LocalTime plus the increased minutes 908 */ 909 public LocalTime plusMinutes(int minutes) { 910 if (minutes == 0) { 911 return this; 912 } 913 long instant = getChronology().minutes().add(getLocalMillis(), minutes); 914 return withLocalMillis(instant); 915 } 916 917 /** 918 * Returns a copy of this time plus the specified number of seconds. 919 * <p> 920 * This LocalTime instance is immutable and unaffected by this method call. 921 * <p> 922 * The following three lines are identical in effect: 923 * <pre> 924 * LocalTime added = dt.plusSeconds(6); 925 * LocalTime added = dt.plus(Period.seconds(6)); 926 * LocalTime added = dt.withFieldAdded(DurationFieldType.seconds(), 6); 927 * </pre> 928 * 929 * @param seconds the amount of seconds to add, may be negative 930 * @return the new LocalTime plus the increased seconds 931 */ 932 public LocalTime plusSeconds(int seconds) { 933 if (seconds == 0) { 934 return this; 935 } 936 long instant = getChronology().seconds().add(getLocalMillis(), seconds); 937 return withLocalMillis(instant); 938 } 939 940 /** 941 * Returns a copy of this time plus the specified number of millis. 942 * <p> 943 * This LocalTime instance is immutable and unaffected by this method call. 944 * <p> 945 * The following three lines are identical in effect: 946 * <pre> 947 * LocalTime added = dt.plusMillis(6); 948 * LocalTime added = dt.plus(Period.millis(6)); 949 * LocalTime added = dt.withFieldAdded(DurationFieldType.millis(), 6); 950 * </pre> 951 * 952 * @param millis the amount of millis to add, may be negative 953 * @return the new LocalTime plus the increased millis 954 */ 955 public LocalTime plusMillis(int millis) { 956 if (millis == 0) { 957 return this; 958 } 959 long instant = getChronology().millis().add(getLocalMillis(), millis); 960 return withLocalMillis(instant); 961 } 962 963 //----------------------------------------------------------------------- 964 /** 965 * Returns a copy of this time with the specified period taken away. 966 * <p> 967 * If the amount is zero or null, then <code>this</code> is returned. 968 * <p> 969 * This method is typically used to subtract complex period instances. 970 * Subtracting one field is best achieved using methods 971 * like {@link #minusHours(int)}. 972 * 973 * @param period the period to reduce this instant by 974 * @return a copy of this time with the period taken away 975 * @throws ArithmeticException if the result exceeds the internal capacity 976 */ 977 public LocalTime minus(ReadablePeriod period) { 978 return withPeriodAdded(period, -1); 979 } 980 981 //----------------------------------------------------------------------- 982 /** 983 * Returns a copy of this time minus the specified number of hours. 984 * <p> 985 * This LocalTime instance is immutable and unaffected by this method call. 986 * <p> 987 * The following three lines are identical in effect: 988 * <pre> 989 * LocalTime subtracted = dt.minusHours(6); 990 * LocalTime subtracted = dt.minus(Period.hours(6)); 991 * LocalTime subtracted = dt.withFieldAdded(DurationFieldType.hours(), -6); 992 * </pre> 993 * 994 * @param hours the amount of hours to subtract, may be negative 995 * @return the new LocalTime minus the increased hours 996 */ 997 public LocalTime minusHours(int hours) { 998 if (hours == 0) { 999 return this; 1000 } 1001 long instant = getChronology().hours().subtract(getLocalMillis(), hours); 1002 return withLocalMillis(instant); 1003 } 1004 1005 /** 1006 * Returns a copy of this time minus the specified number of minutes. 1007 * <p> 1008 * This LocalTime instance is immutable and unaffected by this method call. 1009 * <p> 1010 * The following three lines are identical in effect: 1011 * <pre> 1012 * LocalTime subtracted = dt.minusMinutes(6); 1013 * LocalTime subtracted = dt.minus(Period.minutes(6)); 1014 * LocalTime subtracted = dt.withFieldAdded(DurationFieldType.minutes(), -6); 1015 * </pre> 1016 * 1017 * @param minutes the amount of minutes to subtract, may be negative 1018 * @return the new LocalTime minus the increased minutes 1019 */ 1020 public LocalTime minusMinutes(int minutes) { 1021 if (minutes == 0) { 1022 return this; 1023 } 1024 long instant = getChronology().minutes().subtract(getLocalMillis(), minutes); 1025 return withLocalMillis(instant); 1026 } 1027 1028 /** 1029 * Returns a copy of this time minus the specified number of seconds. 1030 * <p> 1031 * This LocalTime instance is immutable and unaffected by this method call. 1032 * <p> 1033 * The following three lines are identical in effect: 1034 * <pre> 1035 * LocalTime subtracted = dt.minusSeconds(6); 1036 * LocalTime subtracted = dt.minus(Period.seconds(6)); 1037 * LocalTime subtracted = dt.withFieldAdded(DurationFieldType.seconds(), -6); 1038 * </pre> 1039 * 1040 * @param seconds the amount of seconds to subtract, may be negative 1041 * @return the new LocalTime minus the increased seconds 1042 */ 1043 public LocalTime minusSeconds(int seconds) { 1044 if (seconds == 0) { 1045 return this; 1046 } 1047 long instant = getChronology().seconds().subtract(getLocalMillis(), seconds); 1048 return withLocalMillis(instant); 1049 } 1050 1051 /** 1052 * Returns a copy of this time minus the specified number of millis. 1053 * <p> 1054 * This LocalTime instance is immutable and unaffected by this method call. 1055 * <p> 1056 * The following three lines are identical in effect: 1057 * <pre> 1058 * LocalTime subtracted = dt.minusMillis(6); 1059 * LocalTime subtracted = dt.minus(Period.millis(6)); 1060 * LocalTime subtracted = dt.withFieldAdded(DurationFieldType.millis(), -6); 1061 * </pre> 1062 * 1063 * @param millis the amount of millis to subtract, may be negative 1064 * @return the new LocalTime minus the increased millis 1065 */ 1066 public LocalTime minusMillis(int millis) { 1067 if (millis == 0) { 1068 return this; 1069 } 1070 long instant = getChronology().millis().subtract(getLocalMillis(), millis); 1071 return withLocalMillis(instant); 1072 } 1073 1074 //----------------------------------------------------------------------- 1075 /** 1076 * Gets the property object for the specified type, which contains 1077 * many useful methods. 1078 * 1079 * @param fieldType the field type to get the chronology for 1080 * @return the property object 1081 * @throws IllegalArgumentException if the field is null or unsupported 1082 */ 1083 public Property property(DateTimeFieldType fieldType) { 1084 if (fieldType == null) { 1085 throw new IllegalArgumentException("The DateTimeFieldType must not be null"); 1086 } 1087 if (isSupported(fieldType) == false) { 1088 throw new IllegalArgumentException("Field '" + fieldType + "' is not supported"); 1089 } 1090 return new Property(this, fieldType.getField(getChronology())); 1091 } 1092 1093 //----------------------------------------------------------------------- 1094 /** 1095 * Get the hour of day field value. 1096 * 1097 * @return the hour of day 1098 */ 1099 public int getHourOfDay() { 1100 return getChronology().hourOfDay().get(getLocalMillis()); 1101 } 1102 1103 /** 1104 * Get the minute of hour field value. 1105 * 1106 * @return the minute of hour 1107 */ 1108 public int getMinuteOfHour() { 1109 return getChronology().minuteOfHour().get(getLocalMillis()); 1110 } 1111 1112 /** 1113 * Get the second of minute field value. 1114 * 1115 * @return the second of minute 1116 */ 1117 public int getSecondOfMinute() { 1118 return getChronology().secondOfMinute().get(getLocalMillis()); 1119 } 1120 1121 /** 1122 * Get the millis of second field value. 1123 * 1124 * @return the millis of second 1125 */ 1126 public int getMillisOfSecond() { 1127 return getChronology().millisOfSecond().get(getLocalMillis()); 1128 } 1129 1130 /** 1131 * Get the millis of day field value. 1132 * 1133 * @return the millis of day 1134 */ 1135 public int getMillisOfDay() { 1136 return getChronology().millisOfDay().get(getLocalMillis()); 1137 } 1138 1139 //----------------------------------------------------------------------- 1140 /** 1141 * Returns a copy of this time with the hour of day field updated. 1142 * <p> 1143 * LocalTime is immutable, so there are no set methods. 1144 * Instead, this method returns a new instance with the value of 1145 * hour of day changed. 1146 * 1147 * @param hour the hour of day to set 1148 * @return a copy of this object with the field set 1149 * @throws IllegalArgumentException if the value is invalid 1150 */ 1151 public LocalTime withHourOfDay(int hour) { 1152 return withLocalMillis(getChronology().hourOfDay().set(getLocalMillis(), hour)); 1153 } 1154 1155 /** 1156 * Returns a copy of this time with the minute of hour field updated. 1157 * <p> 1158 * LocalTime is immutable, so there are no set methods. 1159 * Instead, this method returns a new instance with the value of 1160 * minute of hour changed. 1161 * 1162 * @param minute the minute of hour to set 1163 * @return a copy of this object with the field set 1164 * @throws IllegalArgumentException if the value is invalid 1165 */ 1166 public LocalTime withMinuteOfHour(int minute) { 1167 return withLocalMillis(getChronology().minuteOfHour().set(getLocalMillis(), minute)); 1168 } 1169 1170 /** 1171 * Returns a copy of this time with the second of minute field updated. 1172 * <p> 1173 * LocalTime is immutable, so there are no set methods. 1174 * Instead, this method returns a new instance with the value of 1175 * second of minute changed. 1176 * 1177 * @param second the second of minute to set 1178 * @return a copy of this object with the field set 1179 * @throws IllegalArgumentException if the value is invalid 1180 */ 1181 public LocalTime withSecondOfMinute(int second) { 1182 return withLocalMillis(getChronology().secondOfMinute().set(getLocalMillis(), second)); 1183 } 1184 1185 /** 1186 * Returns a copy of this time with the millis of second field updated. 1187 * <p> 1188 * LocalTime is immutable, so there are no set methods. 1189 * Instead, this method returns a new instance with the value of 1190 * millis of second changed. 1191 * 1192 * @param millis the millis of second to set 1193 * @return a copy of this object with the field set 1194 * @throws IllegalArgumentException if the value is invalid 1195 */ 1196 public LocalTime withMillisOfSecond(int millis) { 1197 return withLocalMillis(getChronology().millisOfSecond().set(getLocalMillis(), millis)); 1198 } 1199 1200 /** 1201 * Returns a copy of this time with the millis of day field updated. 1202 * <p> 1203 * LocalTime is immutable, so there are no set methods. 1204 * Instead, this method returns a new instance with the value of 1205 * millis of day changed. 1206 * 1207 * @param millis the millis of day to set 1208 * @return a copy of this object with the field set 1209 * @throws IllegalArgumentException if the value is invalid 1210 */ 1211 public LocalTime withMillisOfDay(int millis) { 1212 return withLocalMillis(getChronology().millisOfDay().set(getLocalMillis(), millis)); 1213 } 1214 1215 //----------------------------------------------------------------------- 1216 /** 1217 * Get the hour of day field property which provides access to advanced functionality. 1218 * 1219 * @return the hour of day property 1220 */ 1221 public Property hourOfDay() { 1222 return new Property(this, getChronology().hourOfDay()); 1223 } 1224 1225 /** 1226 * Get the minute of hour field property which provides access to advanced functionality. 1227 * 1228 * @return the minute of hour property 1229 */ 1230 public Property minuteOfHour() { 1231 return new Property(this, getChronology().minuteOfHour()); 1232 } 1233 1234 /** 1235 * Get the second of minute field property which provides access to advanced functionality. 1236 * 1237 * @return the second of minute property 1238 */ 1239 public Property secondOfMinute() { 1240 return new Property(this, getChronology().secondOfMinute()); 1241 } 1242 1243 /** 1244 * Get the millis of second property which provides access to advanced functionality. 1245 * 1246 * @return the millis of second property 1247 */ 1248 public Property millisOfSecond() { 1249 return new Property(this, getChronology().millisOfSecond()); 1250 } 1251 1252 /** 1253 * Get the millis of day property which provides access to advanced functionality. 1254 * 1255 * @return the millis of day property 1256 */ 1257 public Property millisOfDay() { 1258 return new Property(this, getChronology().millisOfDay()); 1259 } 1260 1261 //----------------------------------------------------------------------- 1262 /** 1263 * Converts this LocalTime to a full datetime using the default time zone 1264 * setting the time fields from this instance and the date fields from 1265 * the current date. 1266 * 1267 * @return this time as a datetime using todays date 1268 */ 1269 public DateTime toDateTimeToday() { 1270 return toDateTimeToday(null); 1271 } 1272 1273 /** 1274 * Converts this LocalTime to a full datetime using the specified time zone 1275 * setting the time fields from this instance and the date fields from 1276 * the current time. 1277 * <p> 1278 * This method uses the chronology from this instance plus the time zone 1279 * specified. 1280 * 1281 * @param zone the zone to use, null means default 1282 * @return this time as a datetime using todays date 1283 */ 1284 public DateTime toDateTimeToday(DateTimeZone zone) { 1285 Chronology chrono = getChronology().withZone(zone); 1286 long instantMillis = DateTimeUtils.currentTimeMillis(); 1287 long resolved = chrono.set(this, instantMillis); 1288 return new DateTime(resolved, chrono); 1289 } 1290 1291 //----------------------------------------------------------------------- 1292 /** 1293 * Output the time in ISO8601 format (HH:mm:ss.SSS). 1294 * 1295 * @return ISO8601 time formatted string. 1296 */ 1297 @ToString 1298 public String toString() { 1299 return ISODateTimeFormat.time().print(this); 1300 } 1301 1302 /** 1303 * Output the time using the specified format pattern. 1304 * 1305 * @param pattern the pattern specification, null means use <code>toString</code> 1306 * @see org.joda.time.format.DateTimeFormat 1307 */ 1308 public String toString(String pattern) { 1309 if (pattern == null) { 1310 return toString(); 1311 } 1312 return DateTimeFormat.forPattern(pattern).print(this); 1313 } 1314 1315 /** 1316 * Output the time using the specified format pattern. 1317 * 1318 * @param pattern the pattern specification, null means use <code>toString</code> 1319 * @param locale Locale to use, null means default 1320 * @see org.joda.time.format.DateTimeFormat 1321 */ 1322 public String toString(String pattern, Locale locale) throws IllegalArgumentException { 1323 if (pattern == null) { 1324 return toString(); 1325 } 1326 return DateTimeFormat.forPattern(pattern).withLocale(locale).print(this); 1327 } 1328 1329 //----------------------------------------------------------------------- 1330 /** 1331 * LocalTime.Property binds a LocalTime to a DateTimeField allowing 1332 * powerful datetime functionality to be easily accessed. 1333 * <p> 1334 * The simplest use of this class is as an alternative get method, here used to 1335 * get the minute '30'. 1336 * <pre> 1337 * LocalTime dt = new LocalTime(12, 30); 1338 * int year = dt.minuteOfHour().get(); 1339 * </pre> 1340 * <p> 1341 * Methods are also provided that allow time modification. These return 1342 * new instances of LocalTime - they do not modify the original. The example 1343 * below yields two independent immutable date objects 2 hours apart. 1344 * <pre> 1345 * LocalTime dt1230 = new LocalTime(12, 30); 1346 * LocalTime dt1430 = dt1230.hourOfDay().setCopy(14); 1347 * </pre> 1348 * <p> 1349 * LocalTime.Property itself is thread-safe and immutable, as well as the 1350 * LocalTime being operated on. 1351 * 1352 * @author Stephen Colebourne 1353 * @author Brian S O'Neill 1354 * @since 1.3 1355 */ 1356 public static final class Property extends AbstractReadableInstantFieldProperty { 1357 1358 /** Serialization version */ 1359 private static final long serialVersionUID = -325842547277223L; 1360 1361 /** The instant this property is working against */ 1362 private transient LocalTime iInstant; 1363 /** The field this property is working against */ 1364 private transient DateTimeField iField; 1365 1366 /** 1367 * Constructor. 1368 * 1369 * @param instant the instant to set 1370 * @param field the field to use 1371 */ 1372 Property(LocalTime instant, DateTimeField field) { 1373 super(); 1374 iInstant = instant; 1375 iField = field; 1376 } 1377 1378 /** 1379 * Writes the property in a safe serialization format. 1380 */ 1381 private void writeObject(ObjectOutputStream oos) throws IOException { 1382 oos.writeObject(iInstant); 1383 oos.writeObject(iField.getType()); 1384 } 1385 1386 /** 1387 * Reads the property from a safe serialization format. 1388 */ 1389 private void readObject(ObjectInputStream oos) throws IOException, ClassNotFoundException { 1390 iInstant = (LocalTime) oos.readObject(); 1391 DateTimeFieldType type = (DateTimeFieldType) oos.readObject(); 1392 iField = type.getField(iInstant.getChronology()); 1393 } 1394 1395 //----------------------------------------------------------------------- 1396 /** 1397 * Gets the field being used. 1398 * 1399 * @return the field 1400 */ 1401 public DateTimeField getField() { 1402 return iField; 1403 } 1404 1405 /** 1406 * Gets the milliseconds of the time that this property is linked to. 1407 * 1408 * @return the milliseconds 1409 */ 1410 protected long getMillis() { 1411 return iInstant.getLocalMillis(); 1412 } 1413 1414 /** 1415 * Gets the chronology of the datetime that this property is linked to. 1416 * 1417 * @return the chronology 1418 * @since 1.4 1419 */ 1420 protected Chronology getChronology() { 1421 return iInstant.getChronology(); 1422 } 1423 1424 /** 1425 * Gets the LocalTime object linked to this property. 1426 * 1427 * @return the linked LocalTime 1428 */ 1429 public LocalTime getLocalTime() { 1430 return iInstant; 1431 } 1432 1433 //----------------------------------------------------------------------- 1434 /** 1435 * Adds to this field in a copy of this LocalTime. 1436 * <p> 1437 * The LocalTime attached to this property is unchanged by this call. 1438 * 1439 * @param value the value to add to the field in the copy 1440 * @return a copy of the LocalTime with the field value changed 1441 */ 1442 public LocalTime addCopy(int value) { 1443 return iInstant.withLocalMillis(iField.add(iInstant.getLocalMillis(), value)); 1444 } 1445 1446 /** 1447 * Adds to this field in a copy of this LocalTime. 1448 * If the addition exceeds the maximum value (eg. 23:59) it will 1449 * wrap to the minimum value (eg. 00:00). 1450 * <p> 1451 * The LocalTime attached to this property is unchanged by this call. 1452 * 1453 * @param value the value to add to the field in the copy 1454 * @return a copy of the LocalTime with the field value changed 1455 */ 1456 public LocalTime addCopy(long value) { 1457 return iInstant.withLocalMillis(iField.add(iInstant.getLocalMillis(), value)); 1458 } 1459 1460 /** 1461 * Adds to this field in a copy of this LocalTime. 1462 * If the addition exceeds the maximum value (eg. 23:59) then 1463 * an exception will be thrown. 1464 * Contrast this behaviour to {@link #addCopy(int)}. 1465 * <p> 1466 * The LocalTime attached to this property is unchanged by this call. 1467 * 1468 * @param value the value to add to the field in the copy 1469 * @return a copy of the LocalTime with the field value changed 1470 * @throws IllegalArgumentException if the result is invalid 1471 */ 1472 public LocalTime addNoWrapToCopy(int value) { 1473 long millis = iField.add(iInstant.getLocalMillis(), value); 1474 long rounded = iInstant.getChronology().millisOfDay().get(millis); 1475 if (rounded != millis) { 1476 throw new IllegalArgumentException("The addition exceeded the boundaries of LocalTime"); 1477 } 1478 return iInstant.withLocalMillis(millis); 1479 } 1480 1481 /** 1482 * Adds to this field, possibly wrapped, in a copy of this LocalTime. 1483 * A field wrapped operation only changes this field. 1484 * Thus 10:59 plusWrapField one minute goes to 10:00. 1485 * <p> 1486 * The LocalTime attached to this property is unchanged by this call. 1487 * 1488 * @param value the value to add to the field in the copy 1489 * @return a copy of the LocalTime with the field value changed 1490 * @throws IllegalArgumentException if the value isn't valid 1491 */ 1492 public LocalTime addWrapFieldToCopy(int value) { 1493 return iInstant.withLocalMillis(iField.addWrapField(iInstant.getLocalMillis(), value)); 1494 } 1495 1496 //----------------------------------------------------------------------- 1497 /** 1498 * Sets this field in a copy of the LocalTime. 1499 * <p> 1500 * The LocalTime attached to this property is unchanged by this call. 1501 * 1502 * @param value the value to set the field in the copy to 1503 * @return a copy of the LocalTime with the field value changed 1504 * @throws IllegalArgumentException if the value isn't valid 1505 */ 1506 public LocalTime setCopy(int value) { 1507 return iInstant.withLocalMillis(iField.set(iInstant.getLocalMillis(), value)); 1508 } 1509 1510 /** 1511 * Sets this field in a copy of the LocalTime to a parsed text value. 1512 * <p> 1513 * The LocalTime attached to this property is unchanged by this call. 1514 * 1515 * @param text the text value to set 1516 * @param locale optional locale to use for selecting a text symbol 1517 * @return a copy of the LocalTime with the field value changed 1518 * @throws IllegalArgumentException if the text value isn't valid 1519 */ 1520 public LocalTime setCopy(String text, Locale locale) { 1521 return iInstant.withLocalMillis(iField.set(iInstant.getLocalMillis(), text, locale)); 1522 } 1523 1524 /** 1525 * Sets this field in a copy of the LocalTime to a parsed text value. 1526 * <p> 1527 * The LocalTime attached to this property is unchanged by this call. 1528 * 1529 * @param text the text value to set 1530 * @return a copy of the LocalTime with the field value changed 1531 * @throws IllegalArgumentException if the text value isn't valid 1532 */ 1533 public LocalTime setCopy(String text) { 1534 return setCopy(text, null); 1535 } 1536 1537 //----------------------------------------------------------------------- 1538 /** 1539 * Returns a new LocalTime with this field set to the maximum value 1540 * for this field. 1541 * <p> 1542 * The LocalTime attached to this property is unchanged by this call. 1543 * 1544 * @return a copy of the LocalTime with this field set to its maximum 1545 */ 1546 public LocalTime withMaximumValue() { 1547 return setCopy(getMaximumValue()); 1548 } 1549 1550 /** 1551 * Returns a new LocalTime with this field set to the minimum value 1552 * for this field. 1553 * <p> 1554 * The LocalTime attached to this property is unchanged by this call. 1555 * 1556 * @return a copy of the LocalTime with this field set to its minimum 1557 */ 1558 public LocalTime withMinimumValue() { 1559 return setCopy(getMinimumValue()); 1560 } 1561 1562 //----------------------------------------------------------------------- 1563 /** 1564 * Rounds to the lowest whole unit of this field on a copy of this 1565 * LocalTime. 1566 * <p> 1567 * For example, rounding floor on the hourOfDay field of a LocalTime 1568 * where the time is 10:30 would result in new LocalTime with the 1569 * time of 10:00. 1570 * 1571 * @return a copy of the LocalTime with the field value changed 1572 */ 1573 public LocalTime roundFloorCopy() { 1574 return iInstant.withLocalMillis(iField.roundFloor(iInstant.getLocalMillis())); 1575 } 1576 1577 /** 1578 * Rounds to the highest whole unit of this field on a copy of this 1579 * LocalTime. 1580 * <p> 1581 * For example, rounding floor on the hourOfDay field of a LocalTime 1582 * where the time is 10:30 would result in new LocalTime with the 1583 * time of 11:00. 1584 * 1585 * @return a copy of the LocalTime with the field value changed 1586 */ 1587 public LocalTime roundCeilingCopy() { 1588 return iInstant.withLocalMillis(iField.roundCeiling(iInstant.getLocalMillis())); 1589 } 1590 1591 /** 1592 * Rounds to the nearest whole unit of this field on a copy of this 1593 * LocalTime, favoring the floor if halfway. 1594 * 1595 * @return a copy of the LocalTime with the field value changed 1596 */ 1597 public LocalTime roundHalfFloorCopy() { 1598 return iInstant.withLocalMillis(iField.roundHalfFloor(iInstant.getLocalMillis())); 1599 } 1600 1601 /** 1602 * Rounds to the nearest whole unit of this field on a copy of this 1603 * LocalTime, favoring the ceiling if halfway. 1604 * 1605 * @return a copy of the LocalTime with the field value changed 1606 */ 1607 public LocalTime roundHalfCeilingCopy() { 1608 return iInstant.withLocalMillis(iField.roundHalfCeiling(iInstant.getLocalMillis())); 1609 } 1610 1611 /** 1612 * Rounds to the nearest whole unit of this field on a copy of this 1613 * LocalTime. If halfway, the ceiling is favored over the floor 1614 * only if it makes this field's value even. 1615 * 1616 * @return a copy of the LocalTime with the field value changed 1617 */ 1618 public LocalTime roundHalfEvenCopy() { 1619 return iInstant.withLocalMillis(iField.roundHalfEven(iInstant.getLocalMillis())); 1620 } 1621 } 1622 1623 }