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