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 (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.SSSZZ).
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 }