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.Serializable;
019    import java.util.Calendar;
020    import java.util.Date;
021    import java.util.Locale;
022    
023    import org.joda.time.base.BasePartial;
024    import org.joda.time.chrono.ISOChronology;
025    import org.joda.time.field.AbstractPartialFieldProperty;
026    import org.joda.time.field.FieldUtils;
027    import org.joda.time.format.ISODateTimeFormat;
028    
029    /**
030     * TimeOfDay is an immutable partial supporting the hour, minute, second
031     * and millisecond fields.
032     * <p>
033     * NOTE: This class only supports the four fields listed above. Thus, you
034     * cannot query the millisOfDay or secondOfDay fields for example.
035     * The new <code>LocalTime</code> class removes this restriction.
036     * <p>
037     * Calculations on TimeOfDay are performed using a {@link Chronology}.
038     * This chronology is set to be in the UTC time zone for all calculations.
039     * <p>
040     * Each individual field can be queried in two ways:
041     * <ul>
042     * <li><code>getHourOfDay()</code>
043     * <li><code>hourOfDay().get()</code>
044     * </ul>
045     * The second technique also provides access to other useful methods on the
046     * field:
047     * <ul>
048     * <li>numeric value - <code>hourOfDay().get()</code>
049     * <li>text value - <code>hourOfDay().getAsText()</code>
050     * <li>short text value - <code>hourOfDay().getAsShortText()</code>
051     * <li>maximum/minimum values - <code>hourOfDay().getMaximumValue()</code>
052     * <li>add/subtract - <code>hourOfDay().addToCopy()</code>
053     * <li>set - <code>hourOfDay().setCopy()</code>
054     * </ul>
055     * <p>
056     * TimeOfDay is thread-safe and immutable, provided that the Chronology is as well.
057     * All standard Chronology classes supplied are thread-safe and immutable.
058     *
059     * @author Stephen Colebourne
060     * @author Brian S O'Neill
061     * @since 1.0
062     * @deprecated Use LocalTime which has a much better internal implementation and
063     *  has been available since 1.3
064     */
065    @Deprecated
066    public final class TimeOfDay
067            extends BasePartial
068            implements ReadablePartial, Serializable {
069        // NOTE: No toDateTime(YearMonthDay) as semantics are confusing when
070        // different chronologies
071    
072        /** Serialization version */
073        private static final long serialVersionUID = 3633353405803318660L;
074        /** The singleton set of field types */
075        private static final DateTimeFieldType[] FIELD_TYPES = new DateTimeFieldType[] {
076            DateTimeFieldType.hourOfDay(),
077            DateTimeFieldType.minuteOfHour(),
078            DateTimeFieldType.secondOfMinute(),
079            DateTimeFieldType.millisOfSecond(),
080        };
081    
082        /** Constant for midnight. */
083        public static final TimeOfDay MIDNIGHT = new TimeOfDay(0, 0, 0, 0);
084    
085        /** The index of the hourOfDay field in the field array */
086        public static final int HOUR_OF_DAY = 0;
087        /** The index of the minuteOfHour field in the field array */
088        public static final int MINUTE_OF_HOUR = 1;
089        /** The index of the secondOfMinute field in the field array */
090        public static final int SECOND_OF_MINUTE = 2;
091        /** The index of the millisOfSecond field in the field array */
092        public static final int MILLIS_OF_SECOND = 3;
093    
094        //-----------------------------------------------------------------------
095        /**
096         * Constructs a TimeOfDay from a <code>java.util.Calendar</code>
097         * using exactly the same field values avoiding any time zone effects.
098         * <p>
099         * Each field is queried from the Calendar and assigned to the TimeOfDay.
100         * This is useful to ensure that the field values are the same in the
101         * created TimeOfDay no matter what the time zone is. For example, if
102         * the Calendar states that the time is 04:29, then the created TimeOfDay
103         * will always have the time 04:29 irrespective of time zone issues.
104         * <p>
105         * This factory method ignores the type of the calendar and always
106         * creates a TimeOfDay with ISO chronology.
107         *
108         * @param calendar  the Calendar to extract fields from
109         * @return the created TimeOfDay
110         * @throws IllegalArgumentException if the calendar is null
111         * @throws IllegalArgumentException if the time is invalid for the ISO chronology
112         * @since 1.2
113         */
114        public static TimeOfDay fromCalendarFields(Calendar calendar) {
115            if (calendar == null) {
116                throw new IllegalArgumentException("The calendar must not be null");
117            }
118            return new TimeOfDay(
119                calendar.get(Calendar.HOUR_OF_DAY),
120                calendar.get(Calendar.MINUTE),
121                calendar.get(Calendar.SECOND),
122                calendar.get(Calendar.MILLISECOND)
123            );
124        }
125    
126        /**
127         * Constructs a TimeOfDay from a <code>java.util.Date</code>
128         * using exactly the same field values avoiding any time zone effects.
129         * <p>
130         * Each field is queried from the Date and assigned to the TimeOfDay.
131         * This is useful to ensure that the field values are the same in the
132         * created TimeOfDay no matter what the time zone is. For example, if
133         * the Calendar states that the time is 04:29, then the created TimeOfDay
134         * will always have the time 04:29 irrespective of time zone issues.
135         * <p>
136         * This factory method always creates a TimeOfDay with ISO chronology.
137         *
138         * @param date  the Date to extract fields from
139         * @return the created TimeOfDay
140         * @throws IllegalArgumentException if the calendar is null
141         * @throws IllegalArgumentException if the date is invalid for the ISO chronology
142         * @since 1.2
143         */
144        public static TimeOfDay fromDateFields(Date date) {
145            if (date == null) {
146                throw new IllegalArgumentException("The date must not be null");
147            }
148            return new TimeOfDay(
149                date.getHours(),
150                date.getMinutes(),
151                date.getSeconds(),
152                (((int) (date.getTime() % 1000)) + 1000) % 1000
153            );
154        }
155    
156        //-----------------------------------------------------------------------
157        /**
158         * Constructs a TimeOfDay from the specified millis of day using the
159         * ISO chronology.
160         * <p>
161         * The millisOfDay value may exceed the number of millis in one day,
162         * but additional days will be ignored.
163         * This method uses the UTC time zone internally.
164         *
165         * @param millisOfDay  the number of milliseconds into a day to convert
166         */
167        public static TimeOfDay fromMillisOfDay(long millisOfDay) {
168            return fromMillisOfDay(millisOfDay, null);
169        }
170    
171        /**
172         * Constructs a TimeOfDay from the specified millis of day using the
173         * specified chronology.
174         * <p>
175         * The millisOfDay value may exceed the number of millis in one day,
176         * but additional days will be ignored.
177         * This method uses the UTC time zone internally.
178         *
179         * @param millisOfDay  the number of milliseconds into a day to convert
180         * @param chrono  the chronology, null means ISO chronology
181         */
182        public static TimeOfDay fromMillisOfDay(long millisOfDay, Chronology chrono) {
183            chrono = DateTimeUtils.getChronology(chrono);
184            chrono = chrono.withUTC();
185            return new TimeOfDay(millisOfDay, chrono);
186        }
187    
188        // Constructors
189        //-----------------------------------------------------------------------
190        /**
191         * Constructs a TimeOfDay with the current time, using ISOChronology in
192         * the default zone to extract the fields.
193         * <p>
194         * The constructor uses the default time zone, resulting in the local time
195         * being initialised. Once the constructor is complete, all further calculations
196         * are performed without reference to a timezone (by switching to UTC).
197         */
198        public TimeOfDay() {
199            super();
200        }
201    
202        /**
203         * Constructs a TimeOfDay with the current time, using ISOChronology in
204         * the specified zone to extract the fields.
205         * <p>
206         * The constructor uses the specified time zone to obtain the current time.
207         * Once the constructor is complete, all further calculations
208         * are performed without reference to a timezone (by switching to UTC).
209         * 
210         * @param zone  the zone to use, null means default zone
211         * @since 1.1
212         */
213        public TimeOfDay(DateTimeZone zone) {
214            super(ISOChronology.getInstance(zone));
215        }
216    
217        /**
218         * Constructs a TimeOfDay with the current time, using the specified chronology
219         * and zone to extract the fields.
220         * <p>
221         * The constructor uses the time zone of the chronology specified.
222         * Once the constructor is complete, all further calculations are performed
223         * without reference to a timezone (by switching to UTC).
224         *
225         * @param chronology  the chronology, null means ISOChronology in the default zone
226         */
227        public TimeOfDay(Chronology chronology) {
228            super(chronology);
229        }
230    
231        /**
232         * Constructs a TimeOfDay extracting the partial fields from the specified
233         * milliseconds using the ISOChronology in the default zone.
234         * <p>
235         * The constructor uses the default time zone, resulting in the local time
236         * being initialised. Once the constructor is complete, all further calculations
237         * are performed without reference to a timezone (by switching to UTC).
238         *
239         * @param instant  the milliseconds from 1970-01-01T00:00:00Z
240         */
241        public TimeOfDay(long instant) {
242            super(instant);
243        }
244    
245        /**
246         * Constructs a TimeOfDay extracting the partial fields from the specified
247         * milliseconds using the chronology provided.
248         * <p>
249         * The constructor uses the time zone of the chronology specified.
250         * Once the constructor is complete, all further calculations are performed
251         * without reference to a timezone (by switching to UTC).
252         *
253         * @param instant  the milliseconds from 1970-01-01T00:00:00Z
254         * @param chronology  the chronology, null means ISOChronology in the default zone
255         */
256        public TimeOfDay(long instant, Chronology chronology) {
257            super(instant, chronology);
258        }
259    
260        /**
261         * Constructs a TimeOfDay from an Object that represents a time.
262         * <p>
263         * The recognised object types are defined in
264         * {@link org.joda.time.convert.ConverterManager ConverterManager} and
265         * include ReadableInstant, String, Calendar and Date.
266         * The String formats are described by {@link ISODateTimeFormat#timeParser()}.
267         * <p>
268         * The chronology used will be derived from the object, defaulting to ISO.
269         * <p>
270         * NOTE: Prior to v1.3 the string format was described by
271         * {@link ISODateTimeFormat#dateTimeParser()}. Dates are now rejected.
272         *
273         * @param instant  the datetime object, null means now
274         * @throws IllegalArgumentException if the instant is invalid
275         */
276        public TimeOfDay(Object instant) {
277            super(instant, null, ISODateTimeFormat.timeParser());
278        }
279    
280        /**
281         * Constructs a TimeOfDay from an Object that represents a time, using the
282         * specified chronology.
283         * <p>
284         * The recognised object types are defined in
285         * {@link org.joda.time.convert.ConverterManager ConverterManager} and
286         * include ReadableInstant, String, Calendar and Date.
287         * The String formats are described by {@link ISODateTimeFormat#timeParser()}.
288         * <p>
289         * The constructor uses the time zone of the chronology specified.
290         * Once the constructor is complete, all further calculations are performed
291         * without reference to a timezone (by switching to UTC).
292         * The specified chronology overrides that of the object.
293         * <p>
294         * NOTE: Prior to v1.3 the string format was described by
295         * {@link ISODateTimeFormat#dateTimeParser()}. Dates are now rejected.
296         *
297         * @param instant  the datetime object, null means now
298         * @param chronology  the chronology, null means ISO default
299         * @throws IllegalArgumentException if the instant is invalid
300         */
301        public TimeOfDay(Object instant, Chronology chronology) {
302            super(instant, DateTimeUtils.getChronology(chronology), ISODateTimeFormat.timeParser());
303        }
304    
305        /**
306         * Constructs a TimeOfDay with specified hour and minute and zero seconds and milliseconds
307         * using <code>ISOChronology</code> in the default zone.
308         * <p>
309         * The constructor uses the no time zone initialising the fields as provided.
310         * Once the constructor is complete, all further calculations
311         * are performed without reference to a timezone (by switching to UTC).
312         *
313         * @param hourOfDay  the hour of the day
314         * @param minuteOfHour  the minute of the hour
315         */
316        public TimeOfDay(int hourOfDay, int minuteOfHour) {
317            this(hourOfDay, minuteOfHour, 0, 0, null);
318        }
319    
320        /**
321         * Constructs a TimeOfDay with specified hour and minute and zero seconds and milliseconds.
322         * <p>
323         * The constructor uses the time zone of the chronology specified.
324         * Once the constructor is complete, all further calculations are performed
325         * without reference to a timezone (by switching to UTC).
326         *
327         * @param hourOfDay  the hour of the day
328         * @param minuteOfHour  the minute of the hour
329         * @param chronology  the chronology, null means ISOChronology in the default zone
330         */
331        public TimeOfDay(int hourOfDay, int minuteOfHour, Chronology chronology) {
332            this(hourOfDay, minuteOfHour, 0, 0, chronology);
333        }
334    
335        /**
336         * Constructs a TimeOfDay with specified time field values and zero milliseconds
337         * using <code>ISOChronology</code> in the default zone.
338         * <p>
339         * The constructor uses the no time zone initialising the fields as provided.
340         * Once the constructor is complete, all further calculations
341         * are performed without reference to a timezone (by switching to UTC).
342         *
343         * @param hourOfDay  the hour of the day
344         * @param minuteOfHour  the minute of the hour
345         * @param secondOfMinute  the second of the minute
346         */
347        public TimeOfDay(int hourOfDay, int minuteOfHour, int secondOfMinute) {
348            this(hourOfDay, minuteOfHour, secondOfMinute, 0, null);
349        }
350    
351        /**
352         * Constructs a TimeOfDay with specified time field values and zero milliseconds.
353         * <p>
354         * The constructor uses the time zone of the chronology specified.
355         * Once the constructor is complete, all further calculations are performed
356         * without reference to a timezone (by switching to UTC).
357         *
358         * @param hourOfDay  the hour of the day
359         * @param minuteOfHour  the minute of the hour
360         * @param secondOfMinute  the second of the minute
361         * @param chronology  the chronology, null means ISOChronology in the default zone
362         */
363        public TimeOfDay(int hourOfDay, int minuteOfHour, int secondOfMinute, Chronology chronology) {
364            this(hourOfDay, minuteOfHour, secondOfMinute, 0, chronology);
365        }
366    
367        /**
368         * Constructs a TimeOfDay with specified time field values using
369         * <code>ISOChronology</code> in the default zone.
370         * <p>
371         * The constructor uses the no time zone initialising the fields as provided.
372         * Once the constructor is complete, all further calculations
373         * are performed without reference to a timezone (by switching to UTC).
374         *
375         * @param hourOfDay  the hour of the day
376         * @param minuteOfHour  the minute of the hour
377         * @param secondOfMinute  the second of the minute
378         * @param millisOfSecond  the millisecond of the second
379         */
380        public TimeOfDay(int hourOfDay, int minuteOfHour, int secondOfMinute, int millisOfSecond) {
381            this(hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond, null);
382        }
383    
384        /**
385         * Constructs a TimeOfDay with specified time field values and chronology.
386         * <p>
387         * The constructor uses the time zone of the chronology specified.
388         * Once the constructor is complete, all further calculations are performed
389         * without reference to a timezone (by switching to UTC).
390         *
391         * @param hourOfDay  the hour of the day
392         * @param minuteOfHour  the minute of the hour
393         * @param secondOfMinute  the second of the minute
394         * @param millisOfSecond  the millisecond of the second
395         * @param chronology  the chronology, null means ISOChronology in the default zone
396         */
397        public TimeOfDay(int hourOfDay, int minuteOfHour,
398                int secondOfMinute, int millisOfSecond, Chronology chronology) {
399            super(new int[] {hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond}, chronology);
400        }
401    
402        /**
403         * Constructs a TimeOfDay with chronology from this instance and new values.
404         *
405         * @param partial  the partial to base this new instance on
406         * @param values  the new set of values
407         */
408        TimeOfDay(TimeOfDay partial, int[] values) {
409            super(partial, values);
410        }
411    
412        /**
413         * Constructs a TimeOfDay with values from this instance and a new chronology.
414         *
415         * @param partial  the partial to base this new instance on
416         * @param chrono  the new chronology
417         */
418        TimeOfDay(TimeOfDay partial, Chronology chrono) {
419            super(partial, chrono);
420        }
421    
422        //-----------------------------------------------------------------------
423        /**
424         * Gets the number of fields in this partial.
425         * 
426         * @return the field count
427         */
428        public int size() {
429            return 4;
430        }
431    
432        /**
433         * Gets the field for a specific index in the chronology specified.
434         * <p>
435         * This method must not use any instance variables.
436         * 
437         * @param index  the index to retrieve
438         * @param chrono  the chronology to use
439         * @return the field
440         */
441        protected DateTimeField getField(int index, Chronology chrono) {
442            switch (index) {
443                case HOUR_OF_DAY:
444                    return chrono.hourOfDay();
445                case MINUTE_OF_HOUR:
446                    return chrono.minuteOfHour();
447                case SECOND_OF_MINUTE:
448                    return chrono.secondOfMinute();
449                case MILLIS_OF_SECOND:
450                    return chrono.millisOfSecond();
451                default:
452                    throw new IndexOutOfBoundsException("Invalid index: " + index);
453            }
454        }
455    
456        /**
457         * Gets the field type at the specified index.
458         *
459         * @param index  the index to retrieve
460         * @return the field at the specified index
461         * @throws IndexOutOfBoundsException if the index is invalid
462         */
463        public DateTimeFieldType getFieldType(int index) {
464            return FIELD_TYPES[index];
465        }
466    
467        /**
468         * Gets an array of the field type of each of the fields that this partial supports.
469         * <p>
470         * The fields are returned largest to smallest, Hour, Minute, Second, Millis.
471         *
472         * @return the array of field types (cloned), largest to smallest
473         */
474        public DateTimeFieldType[] getFieldTypes() {
475            return (DateTimeFieldType[]) FIELD_TYPES.clone();
476        }
477    
478        //-----------------------------------------------------------------------
479        /**
480         * Returns a copy of this time with the specified chronology.
481         * This instance is immutable and unaffected by this method call.
482         * <p>
483         * This method retains the values of the fields, thus the result will
484         * typically refer to a different instant.
485         * <p>
486         * The time zone of the specified chronology is ignored, as TimeOfDay
487         * operates without a time zone.
488         *
489         * @param newChronology  the new chronology, null means ISO
490         * @return a copy of this datetime with a different chronology
491         * @throws IllegalArgumentException if the values are invalid for the new chronology
492         */
493        public TimeOfDay withChronologyRetainFields(Chronology newChronology) {
494            newChronology = DateTimeUtils.getChronology(newChronology);
495            newChronology = newChronology.withUTC();
496            if (newChronology == getChronology()) {
497                return this;
498            } else {
499                TimeOfDay newTimeOfDay = new TimeOfDay(this, newChronology);
500                newChronology.validate(newTimeOfDay, getValues());
501                return newTimeOfDay;
502            }
503        }
504    
505        /**
506         * Returns a copy of this time with the specified field set to a new value.
507         * <p>
508         * For example, if the field type is <code>minuteOfHour</code> then the day
509         * would be changed in the returned instance.
510         * <p>
511         * These three lines are equivalent:
512         * <pre>
513         * TimeOfDay updated = tod.withField(DateTimeFieldType.minuteOfHour(), 6);
514         * TimeOfDay updated = tod.minuteOfHour().setCopy(6);
515         * TimeOfDay updated = tod.property(DateTimeFieldType.minuteOfHour()).setCopy(6);
516         * </pre>
517         *
518         * @param fieldType  the field type to set, not null
519         * @param value  the value to set
520         * @return a copy of this instance with the field set
521         * @throws IllegalArgumentException if the value is null or invalid
522         */
523        public TimeOfDay withField(DateTimeFieldType fieldType, int value) {
524            int index = indexOfSupported(fieldType);
525            if (value == getValue(index)) {
526                return this;
527            }
528            int[] newValues = getValues();
529            newValues = getField(index).set(this, index, newValues, value);
530            return new TimeOfDay(this, newValues);
531        }
532    
533        /**
534         * Returns a copy of this time with the value of the specified field increased,
535         * wrapping to what would be a new day if required.
536         * <p>
537         * If the addition is zero, then <code>this</code> is returned.
538         * <p>
539         * These three lines are equivalent:
540         * <pre>
541         * TimeOfDay added = tod.withFieldAdded(DurationFieldType.minutes(), 6);
542         * TimeOfDay added = tod.plusMinutes(6);
543         * TimeOfDay added = tod.minuteOfHour().addToCopy(6);
544         * </pre>
545         * 
546         * @param fieldType  the field type to add to, not null
547         * @param amount  the amount to add
548         * @return a copy of this instance with the field updated
549         * @throws IllegalArgumentException if the value is null or invalid
550         * @throws ArithmeticException if the new datetime exceeds the capacity
551         */
552        public TimeOfDay withFieldAdded(DurationFieldType fieldType, int amount) {
553            int index = indexOfSupported(fieldType);
554            if (amount == 0) {
555                return this;
556            }
557            int[] newValues = getValues();
558            newValues = getField(index).addWrapPartial(this, index, newValues, amount);
559            return new TimeOfDay(this, newValues);
560        }
561    
562        /**
563         * Returns a copy of this time with the specified period added,
564         * wrapping to what would be a new day if required.
565         * <p>
566         * If the addition is zero, then <code>this</code> is returned.
567         * Fields in the period that aren't present in the partial are ignored.
568         * <p>
569         * This method is typically used to add multiple copies of complex
570         * period instances. Adding one field is best achieved using methods
571         * like {@link #withFieldAdded(DurationFieldType, int)}
572         * or {@link #plusHours(int)}.
573         * 
574         * @param period  the period to add to this one, null means zero
575         * @param scalar  the amount of times to add, such as -1 to subtract once
576         * @return a copy of this instance with the period added
577         * @throws ArithmeticException if the new datetime exceeds the capacity
578         */
579        public TimeOfDay withPeriodAdded(ReadablePeriod period, int scalar) {
580            if (period == null || scalar == 0) {
581                return this;
582            }
583            int[] newValues = getValues();
584            for (int i = 0; i < period.size(); i++) {
585                DurationFieldType fieldType = period.getFieldType(i);
586                int index = indexOf(fieldType);
587                if (index >= 0) {
588                    newValues = getField(index).addWrapPartial(this, index, newValues,
589                            FieldUtils.safeMultiply(period.getValue(i), scalar));
590                }
591            }
592            return new TimeOfDay(this, newValues);
593        }
594    
595        //-----------------------------------------------------------------------
596        /**
597         * Returns a copy of this time with the specified period added,
598         * wrapping to what would be a new day if required.
599         * <p>
600         * If the amount is zero or null, then <code>this</code> is returned.
601         * <p>
602         * This method is typically used to add complex period instances.
603         * Adding one field is best achieved using methods
604         * like {@link #plusHours(int)}.
605         * 
606         * @param period  the duration to add to this one, null means zero
607         * @return a copy of this instance with the period added
608         * @throws ArithmeticException if the new datetime exceeds the capacity of a long
609         */
610        public TimeOfDay plus(ReadablePeriod period) {
611            return withPeriodAdded(period, 1);
612        }
613    
614        //-----------------------------------------------------------------------
615        /**
616         * Returns a copy of this time plus the specified number of hours.
617         * <p>
618         * This time instance is immutable and unaffected by this method call.
619         * <p>
620         * The following three lines are identical in effect:
621         * <pre>
622         * TimeOfDay added = dt.plusHours(6);
623         * TimeOfDay added = dt.plus(Period.hours(6));
624         * TimeOfDay added = dt.withFieldAdded(DurationFieldType.hours(), 6);
625         * </pre>
626         *
627         * @param hours  the amount of hours to add, may be negative
628         * @return the new time plus the increased hours
629         * @since 1.1
630         */
631        public TimeOfDay plusHours(int hours) {
632            return withFieldAdded(DurationFieldType.hours(), hours);
633        }
634    
635        /**
636         * Returns a copy of this time plus the specified number of minutes.
637         * <p>
638         * This time instance is immutable and unaffected by this method call.
639         * <p>
640         * The following three lines are identical in effect:
641         * <pre>
642         * TimeOfDay added = dt.plusMinutes(6);
643         * TimeOfDay added = dt.plus(Period.minutes(6));
644         * TimeOfDay added = dt.withFieldAdded(DurationFieldType.minutes(), 6);
645         * </pre>
646         *
647         * @param minutes  the amount of minutes to add, may be negative
648         * @return the new time plus the increased minutes
649         * @since 1.1
650         */
651        public TimeOfDay plusMinutes(int minutes) {
652            return withFieldAdded(DurationFieldType.minutes(), minutes);
653        }
654    
655        /**
656         * Returns a copy of this time plus the specified number of seconds.
657         * <p>
658         * This time instance is immutable and unaffected by this method call.
659         * <p>
660         * The following three lines are identical in effect:
661         * <pre>
662         * TimeOfDay added = dt.plusSeconds(6);
663         * TimeOfDay added = dt.plus(Period.seconds(6));
664         * TimeOfDay added = dt.withFieldAdded(DurationFieldType.seconds(), 6);
665         * </pre>
666         *
667         * @param seconds  the amount of seconds to add, may be negative
668         * @return the new time plus the increased seconds
669         * @since 1.1
670         */
671        public TimeOfDay plusSeconds(int seconds) {
672            return withFieldAdded(DurationFieldType.seconds(), seconds);
673        }
674    
675        /**
676         * Returns a copy of this time plus the specified number of millis.
677         * <p>
678         * This time instance is immutable and unaffected by this method call.
679         * <p>
680         * The following three lines are identical in effect:
681         * <pre>
682         * TimeOfDay added = dt.plusMillis(6);
683         * TimeOfDay added = dt.plus(Period.millis(6));
684         * TimeOfDay added = dt.withFieldAdded(DurationFieldType.millis(), 6);
685         * </pre>
686         *
687         * @param millis  the amount of millis to add, may be negative
688         * @return the new time plus the increased millis
689         * @since 1.1
690         */
691        public TimeOfDay plusMillis(int millis) {
692            return withFieldAdded(DurationFieldType.millis(), millis);
693        }
694    
695        //-----------------------------------------------------------------------
696        /**
697         * Returns a copy of this time with the specified period taken away,
698         * wrapping to what would be a new day if required.
699         * <p>
700         * If the amount is zero or null, then <code>this</code> is returned.
701         * <p>
702         * This method is typically used to subtract complex period instances.
703         * Subtracting one field is best achieved using methods
704         * like {@link #minusHours(int)}.
705         * 
706         * @param period  the period to reduce this instant by
707         * @return a copy of this instance with the period taken away
708         * @throws ArithmeticException if the new time exceeds capacity
709         */
710        public TimeOfDay minus(ReadablePeriod period) {
711            return withPeriodAdded(period, -1);
712        }
713    
714        //-----------------------------------------------------------------------
715        /**
716         * Returns a copy of this time minus the specified number of hours.
717         * <p>
718         * This time instance is immutable and unaffected by this method call.
719         * <p>
720         * The following three lines are identical in effect:
721         * <pre>
722         * TimeOfDay subtracted = dt.minusHours(6);
723         * TimeOfDay subtracted = dt.minus(Period.hours(6));
724         * TimeOfDay subtracted = dt.withFieldAdded(DurationFieldType.hours(), -6);
725         * </pre>
726         *
727         * @param hours  the amount of hours to subtract, may be negative
728         * @return the new time minus the increased hours
729         * @since 1.1
730         */
731        public TimeOfDay minusHours(int hours) {
732            return withFieldAdded(DurationFieldType.hours(), FieldUtils.safeNegate(hours));
733        }
734    
735        /**
736         * Returns a copy of this time minus the specified number of minutes.
737         * <p>
738         * This time instance is immutable and unaffected by this method call.
739         * <p>
740         * The following three lines are identical in effect:
741         * <pre>
742         * TimeOfDay subtracted = dt.minusMinutes(6);
743         * TimeOfDay subtracted = dt.minus(Period.minutes(6));
744         * TimeOfDay subtracted = dt.withFieldAdded(DurationFieldType.minutes(), -6);
745         * </pre>
746         *
747         * @param minutes  the amount of minutes to subtract, may be negative
748         * @return the new time minus the increased minutes
749         * @since 1.1
750         */
751        public TimeOfDay minusMinutes(int minutes) {
752            return withFieldAdded(DurationFieldType.minutes(), FieldUtils.safeNegate(minutes));
753        }
754    
755        /**
756         * Returns a copy of this time minus the specified number of seconds.
757         * <p>
758         * This time instance is immutable and unaffected by this method call.
759         * <p>
760         * The following three lines are identical in effect:
761         * <pre>
762         * TimeOfDay subtracted = dt.minusSeconds(6);
763         * TimeOfDay subtracted = dt.minus(Period.seconds(6));
764         * TimeOfDay subtracted = dt.withFieldAdded(DurationFieldType.seconds(), -6);
765         * </pre>
766         *
767         * @param seconds  the amount of seconds to subtract, may be negative
768         * @return the new time minus the increased seconds
769         * @since 1.1
770         */
771        public TimeOfDay minusSeconds(int seconds) {
772            return withFieldAdded(DurationFieldType.seconds(), FieldUtils.safeNegate(seconds));
773        }
774    
775        /**
776         * Returns a copy of this time minus the specified number of millis.
777         * <p>
778         * This time instance is immutable and unaffected by this method call.
779         * <p>
780         * The following three lines are identical in effect:
781         * <pre>
782         * TimeOfDay subtracted = dt.minusMillis(6);
783         * TimeOfDay subtracted = dt.minus(Period.millis(6));
784         * TimeOfDay subtracted = dt.withFieldAdded(DurationFieldType.millis(), -6);
785         * </pre>
786         *
787         * @param millis  the amount of millis to subtract, may be negative
788         * @return the new time minus the increased millis
789         * @since 1.1
790         */
791        public TimeOfDay minusMillis(int millis) {
792            return withFieldAdded(DurationFieldType.millis(), FieldUtils.safeNegate(millis));
793        }
794    
795        //-----------------------------------------------------------------------
796        /**
797         * Gets the property object for the specified type, which contains
798         * many useful methods.
799         *
800         * @param type  the field type to get the property for
801         * @return the property object
802         * @throws IllegalArgumentException if the field is null or unsupported
803         */
804        public Property property(DateTimeFieldType type) {
805            return new Property(this, indexOfSupported(type));
806        }
807    
808        //-----------------------------------------------------------------------
809        /**
810         * Converts this object to a LocalTime with the same time and chronology.
811         *
812         * @return a LocalTime with the same time and chronology
813         * @since 1.3
814         */
815        public LocalTime toLocalTime() {
816            return new LocalTime(getHourOfDay(), getMinuteOfHour(),
817                    getSecondOfMinute(), getMillisOfSecond(), getChronology());
818        }
819    
820        //-----------------------------------------------------------------------
821        /**
822         * Converts this partial to a full datetime using the default time zone
823         * setting the time fields from this instance and the date fields from
824         * the current time.
825         *
826         * @return this date as a datetime with the time as the current time
827         */
828        public DateTime toDateTimeToday() {
829            return toDateTimeToday(null);
830        }
831    
832        /**
833         * Converts this partial to a full datetime using the specified time zone
834         * setting the time fields from this instance and the date fields from
835         * the current time.
836         * <p>
837         * This method uses the chronology from this instance plus the time zone
838         * specified.
839         *
840         * @param zone  the zone to use, null means default
841         * @return this date as a datetime with the time as the current time
842         */
843        public DateTime toDateTimeToday(DateTimeZone zone) {
844            Chronology chrono = getChronology().withZone(zone);
845            long instantMillis = DateTimeUtils.currentTimeMillis();
846            long resolved = chrono.set(this, instantMillis);
847            return new DateTime(resolved, chrono);
848        }
849    
850        //-----------------------------------------------------------------------
851        /**
852         * Get the hour of day (0-23) field value.
853         *
854         * @return the hour of day
855         */
856        public int getHourOfDay() {
857            return getValue(HOUR_OF_DAY);
858        }
859    
860        /**
861         * Get the minute of hour field value.
862         *
863         * @return the minute of hour
864         */
865        public int getMinuteOfHour() {
866            return getValue(MINUTE_OF_HOUR);
867        }
868    
869        /**
870         * Get the second of minute field value.
871         *
872         * @return the second of minute
873         */
874        public int getSecondOfMinute() {
875            return getValue(SECOND_OF_MINUTE);
876        }
877    
878        /**
879         * Get the millis of second field value.
880         *
881         * @return the millis of second
882         */
883        public int getMillisOfSecond() {
884            return getValue(MILLIS_OF_SECOND);
885        }
886    
887        //-----------------------------------------------------------------------
888        /**
889         * Returns a copy of this time with the hour of day field updated.
890         * <p>
891         * TimeOfDay is immutable, so there are no set methods.
892         * Instead, this method returns a new instance with the value of
893         * hour of day changed.
894         *
895         * @param hour  the hour of day to set
896         * @return a copy of this object with the field set
897         * @throws IllegalArgumentException if the value is invalid
898         * @since 1.3
899         */
900        public TimeOfDay withHourOfDay(int hour) {
901            int[] newValues = getValues();
902            newValues = getChronology().hourOfDay().set(this, HOUR_OF_DAY, newValues, hour);
903            return new TimeOfDay(this, newValues);
904        }
905    
906        /**
907         * Returns a copy of this time with the minute of hour field updated.
908         * <p>
909         * TimeOfDay is immutable, so there are no set methods.
910         * Instead, this method returns a new instance with the value of
911         * minute of hour changed.
912         *
913         * @param minute  the minute of hour to set
914         * @return a copy of this object with the field set
915         * @throws IllegalArgumentException if the value is invalid
916         * @since 1.3
917         */
918        public TimeOfDay withMinuteOfHour(int minute) {
919            int[] newValues = getValues();
920            newValues = getChronology().minuteOfHour().set(this, MINUTE_OF_HOUR, newValues, minute);
921            return new TimeOfDay(this, newValues);
922        }
923    
924        /**
925         * Returns a copy of this time with the second of minute field updated.
926         * <p>
927         * TimeOfDay is immutable, so there are no set methods.
928         * Instead, this method returns a new instance with the value of
929         * second of minute changed.
930         *
931         * @param second  the second of minute to set
932         * @return a copy of this object with the field set
933         * @throws IllegalArgumentException if the value is invalid
934         * @since 1.3
935         */
936        public TimeOfDay withSecondOfMinute(int second) {
937            int[] newValues = getValues();
938            newValues = getChronology().secondOfMinute().set(this, SECOND_OF_MINUTE, newValues, second);
939            return new TimeOfDay(this, newValues);
940        }
941    
942        /**
943         * Returns a copy of this time with the millis of second field updated.
944         * <p>
945         * TimeOfDay is immutable, so there are no set methods.
946         * Instead, this method returns a new instance with the value of
947         * millis of second changed.
948         *
949         * @param millis  the millis of second to set
950         * @return a copy of this object with the field set
951         * @throws IllegalArgumentException if the value is invalid
952         * @since 1.3
953         */
954        public TimeOfDay withMillisOfSecond(int millis) {
955            int[] newValues = getValues();
956            newValues = getChronology().millisOfSecond().set(this, MILLIS_OF_SECOND, newValues, millis);
957            return new TimeOfDay(this, newValues);
958        }
959    
960        //-----------------------------------------------------------------------
961        /**
962         * Get the hour of day field property which provides access to advanced functionality.
963         * 
964         * @return the hour of day property
965         */
966        public Property hourOfDay() {
967            return new Property(this, HOUR_OF_DAY);
968        }
969    
970        /**
971         * Get the minute of hour field property which provides access to advanced functionality.
972         * 
973         * @return the minute of hour property
974         */
975        public Property minuteOfHour() {
976            return new Property(this, MINUTE_OF_HOUR);
977        }
978    
979        /**
980         * Get the second of minute field property which provides access to advanced functionality.
981         * 
982         * @return the second of minute property
983         */
984        public Property secondOfMinute() {
985            return new Property(this, SECOND_OF_MINUTE);
986        }
987    
988        /**
989         * Get the millis of second property which provides access to advanced functionality.
990         * 
991         * @return the millis of second property
992         */
993        public Property millisOfSecond() {
994            return new Property(this, MILLIS_OF_SECOND);
995        }
996    
997        //-----------------------------------------------------------------------
998        /**
999         * Output the time in the ISO8601 format THH:mm:ss.SSS.
1000         * 
1001         * @return ISO8601 formatted string
1002         */
1003        public String toString() {
1004            return ISODateTimeFormat.tTime().print(this);
1005        }
1006    
1007        //-----------------------------------------------------------------------
1008        /**
1009         * The property class for <code>TimeOfDay</code>.
1010         * <p>
1011         * This class binds a <code>TimeOfDay</code> to a <code>DateTimeField</code>.
1012         * 
1013         * @author Stephen Colebourne
1014         * @since 1.0
1015         * @deprecated Use LocalTime which has a much better internal implementation
1016         */
1017        @Deprecated
1018        public static class Property extends AbstractPartialFieldProperty implements Serializable {
1019    
1020            /** Serialization version */
1021            private static final long serialVersionUID = 5598459141741063833L;
1022    
1023            /** The partial */
1024            private final TimeOfDay iTimeOfDay;
1025            /** The field index */
1026            private final int iFieldIndex;
1027    
1028            /**
1029             * Constructs a property.
1030             * 
1031             * @param partial  the partial instance
1032             * @param fieldIndex  the index in the partial
1033             */
1034            Property(TimeOfDay partial, int fieldIndex) {
1035                super();
1036                iTimeOfDay = partial;
1037                iFieldIndex = fieldIndex;
1038            }
1039    
1040            /**
1041             * Gets the field that this property uses.
1042             * 
1043             * @return the field
1044             */
1045            public DateTimeField getField() {
1046                return iTimeOfDay.getField(iFieldIndex);
1047            }
1048    
1049            /**
1050             * Gets the partial that this property belongs to.
1051             * 
1052             * @return the partial
1053             */
1054            protected ReadablePartial getReadablePartial() {
1055                return iTimeOfDay;
1056            }
1057    
1058            /**
1059             * Gets the partial that this property belongs to.
1060             * 
1061             * @return the partial
1062             */
1063            public TimeOfDay getTimeOfDay() {
1064                return iTimeOfDay;
1065            }
1066    
1067            /**
1068             * Gets the value of this field.
1069             * 
1070             * @return the field value
1071             */
1072            public int get() {
1073                return iTimeOfDay.getValue(iFieldIndex);
1074            }
1075    
1076            //-----------------------------------------------------------------------
1077            /**
1078             * Adds to the value of this field in a copy of this TimeOfDay,
1079             * wrapping to what would be the next day if necessary.
1080             * <p>
1081             * The value will be added to this field. If the value is too large to be
1082             * added solely to this field then it will affect larger fields.
1083             * Smaller fields are unaffected.
1084             * <p>
1085             * If the result would be too large, beyond 23:59:59:999, then the
1086             * calculation wraps to 00:00:00.000. For the alternate strict behaviour
1087             * with no wrapping see {@link #addNoWrapToCopy(int)}.
1088             * <p>
1089             * The TimeOfDay attached to this property is unchanged by this call.
1090             * Instead, a new instance is returned.
1091             * 
1092             * @param valueToAdd  the value to add to the field in the copy
1093             * @return a copy of the TimeOfDay with the field value changed
1094             * @throws IllegalArgumentException if the value isn't valid
1095             */
1096            public TimeOfDay addToCopy(int valueToAdd) {
1097                int[] newValues = iTimeOfDay.getValues();
1098                newValues = getField().addWrapPartial(iTimeOfDay, iFieldIndex, newValues, valueToAdd);
1099                return new TimeOfDay(iTimeOfDay, newValues);
1100            }
1101    
1102            /**
1103             * Adds to the value of this field in a copy of this TimeOfDay,
1104             * throwing an Exception if the bounds are exceeded.
1105             * <p>
1106             * The value will be added to this field. If the value is too large to be
1107             * added solely to this field then it will affect larger fields.
1108             * Smaller fields are unaffected.
1109             * <p>
1110             * If the result would be too large (beyond 23:59:59:999) or too
1111             * small (less than 00:00:00.000) then an Execption is thrown.
1112             * For the alternate behaviour which wraps to the next 'day',
1113             * see {@link #addToCopy(int)}.
1114             * <p>
1115             * The TimeOfDay attached to this property is unchanged by this call.
1116             * Instead, a new instance is returned.
1117             * 
1118             * @param valueToAdd  the value to add to the field in the copy
1119             * @return a copy of the TimeOfDay with the field value changed
1120             * @throws IllegalArgumentException if the value isn't valid
1121             */
1122            public TimeOfDay addNoWrapToCopy(int valueToAdd) {
1123                int[] newValues = iTimeOfDay.getValues();
1124                newValues = getField().add(iTimeOfDay, iFieldIndex, newValues, valueToAdd);
1125                return new TimeOfDay(iTimeOfDay, newValues);
1126            }
1127    
1128            /**
1129             * Adds to the value of this field in a copy of this TimeOfDay wrapping
1130             * within this field if the maximum value is reached.
1131             * <p>
1132             * The value will be added to this field. If the value is too large to be
1133             * added solely to this field then it wraps within this field.
1134             * Other fields are unaffected.
1135             * <p>
1136             * For example,
1137             * <code>12:59:37</code> addWrapField one minute returns <code>12:00:37</code>.
1138             * <p>
1139             * The TimeOfDay attached to this property is unchanged by this call.
1140             * Instead, a new instance is returned.
1141             * 
1142             * @param valueToAdd  the value to add to the field in the copy
1143             * @return a copy of the TimeOfDay with the field value changed
1144             * @throws IllegalArgumentException if the value isn't valid
1145             */
1146            public TimeOfDay addWrapFieldToCopy(int valueToAdd) {
1147                int[] newValues = iTimeOfDay.getValues();
1148                newValues = getField().addWrapField(iTimeOfDay, iFieldIndex, newValues, valueToAdd);
1149                return new TimeOfDay(iTimeOfDay, newValues);
1150            }
1151    
1152            //-----------------------------------------------------------------------
1153            /**
1154             * Sets this field in a copy of the TimeOfDay.
1155             * <p>
1156             * The TimeOfDay attached to this property is unchanged by this call.
1157             * Instead, a new instance is returned.
1158             * 
1159             * @param value  the value to set the field in the copy to
1160             * @return a copy of the TimeOfDay with the field value changed
1161             * @throws IllegalArgumentException if the value isn't valid
1162             */
1163            public TimeOfDay setCopy(int value) {
1164                int[] newValues = iTimeOfDay.getValues();
1165                newValues = getField().set(iTimeOfDay, iFieldIndex, newValues, value);
1166                return new TimeOfDay(iTimeOfDay, newValues);
1167            }
1168    
1169            /**
1170             * Sets this field in a copy of the TimeOfDay to a parsed text value.
1171             * <p>
1172             * The TimeOfDay attached to this property is unchanged by this call.
1173             * Instead, a new instance is returned.
1174             * 
1175             * @param text  the text value to set
1176             * @param locale  optional locale to use for selecting a text symbol
1177             * @return a copy of the TimeOfDay with the field value changed
1178             * @throws IllegalArgumentException if the text value isn't valid
1179             */
1180            public TimeOfDay setCopy(String text, Locale locale) {
1181                int[] newValues = iTimeOfDay.getValues();
1182                newValues = getField().set(iTimeOfDay, iFieldIndex, newValues, text, locale);
1183                return new TimeOfDay(iTimeOfDay, newValues);
1184            }
1185    
1186            /**
1187             * Sets this field in a copy of the TimeOfDay to a parsed text value.
1188             * <p>
1189             * The TimeOfDay attached to this property is unchanged by this call.
1190             * Instead, a new instance is returned.
1191             * 
1192             * @param text  the text value to set
1193             * @return a copy of the TimeOfDay with the field value changed
1194             * @throws IllegalArgumentException if the text value isn't valid
1195             */
1196            public TimeOfDay setCopy(String text) {
1197                return setCopy(text, null);
1198            }
1199    
1200            //-----------------------------------------------------------------------
1201            /**
1202             * Returns a new TimeOfDay with this field set to the maximum value
1203             * for this field.
1204             * <p>
1205             * The TimeOfDay attached to this property is unchanged by this call.
1206             *
1207             * @return a copy of the TimeOfDay with this field set to its maximum
1208             * @since 1.2
1209             */
1210            public TimeOfDay withMaximumValue() {
1211                return setCopy(getMaximumValue());
1212            }
1213    
1214            /**
1215             * Returns a new TimeOfDay with this field set to the minimum value
1216             * for this field.
1217             * <p>
1218             * The TimeOfDay attached to this property is unchanged by this call.
1219             *
1220             * @return a copy of the TimeOfDay with this field set to its minimum
1221             * @since 1.2
1222             */
1223            public TimeOfDay withMinimumValue() {
1224                return setCopy(getMinimumValue());
1225            }
1226        }
1227    
1228    }