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