001    /*
002     *  Copyright 2001-2005 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    
020    import org.joda.time.base.BasePeriod;
021    import org.joda.time.field.FieldUtils;
022    import org.joda.time.format.ISOPeriodFormat;
023    
024    /**
025     * Standard mutable time period implementation.
026     * <p>
027     * A time period is divided into a number of fields, such as hours and seconds.
028     * Which fields are supported is defined by the PeriodType class.
029     * The default is the standard period type, which supports years, months, weeks, days,
030     * hours, minutes, seconds and millis.
031     * <p>
032     * When this time period is added to an instant, the effect is of adding each field in turn.
033     * As a result, this takes into account daylight savings time.
034     * Adding a time period of 1 day to the day before daylight savings starts will only add
035     * 23 hours rather than 24 to ensure that the time remains the same.
036     * If this is not the behaviour you want, then see {@link Duration}.
037     * <p>
038     * The definition of a period also affects the equals method. A period of 1
039     * day is not equal to a period of 24 hours, nor 1 hour equal to 60 minutes.
040     * This is because periods represent an abstracted definition of a time period
041     * (eg. a day may not actually be 24 hours, it might be 23 or 25 at daylight
042     * savings boundary). To compare the actual duration of two periods, convert
043     * both to durations using toDuration, an operation that emphasises that the
044     * result may differ according to the date you choose.
045     * <p>
046     * MutablePeriod is mutable and not thread-safe, unless concurrent threads
047     * are not invoking mutator methods.
048     *
049     * @author Brian S O'Neill
050     * @author Stephen Colebourne
051     * @since 1.0
052     * @see Period
053     */
054    public class MutablePeriod
055            extends BasePeriod
056            implements ReadWritablePeriod, Cloneable, Serializable {
057    
058        /** Serialization version */
059        private static final long serialVersionUID = 3436451121567212165L;
060    
061        /**
062         * Creates a zero-length period using the standard period type.
063         */
064        public MutablePeriod() {
065            super(0L, null, null);
066        }
067    
068        /**
069         * Creates a zero-length period using the specified period type.
070         *
071         * @param type  which set of fields this period supports
072         */
073        public MutablePeriod(PeriodType type) {
074            super(0L, type, null);
075        }
076    
077        /**
078         * Create a period from a set of field values using the standard set of fields.
079         *
080         * @param hours  amount of hours in this period
081         * @param minutes  amount of minutes in this period
082         * @param seconds  amount of seconds in this period
083         * @param millis  amount of milliseconds in this period
084         */
085        public MutablePeriod(int hours, int minutes, int seconds, int millis) {
086            super(0, 0, 0, 0, hours, minutes, seconds, millis, PeriodType.standard());
087        }
088    
089        /**
090         * Create a period from a set of field values using the standard set of fields.
091         *
092         * @param years  amount of years in this period
093         * @param months  amount of months in this period
094         * @param weeks  amount of weeks in this period
095         * @param days  amount of days in this period
096         * @param hours  amount of hours in this period
097         * @param minutes  amount of minutes in this period
098         * @param seconds  amount of seconds in this period
099         * @param millis  amount of milliseconds in this period
100         */
101        public MutablePeriod(int years, int months, int weeks, int days,
102                      int hours, int minutes, int seconds, int millis) {
103            super(years, months, weeks, days, hours, minutes, seconds, millis, PeriodType.standard());
104        }
105    
106        /**
107         * Create a period from a set of field values.
108         *
109         * @param years  amount of years in this period, which must be zero if unsupported
110         * @param months  amount of months in this period, which must be zero if unsupported
111         * @param weeks  amount of weeks in this period, which must be zero if unsupported
112         * @param days  amount of days in this period, which must be zero if unsupported
113         * @param hours  amount of hours in this period, which must be zero if unsupported
114         * @param minutes  amount of minutes in this period, which must be zero if unsupported
115         * @param seconds  amount of seconds in this period, which must be zero if unsupported
116         * @param millis  amount of milliseconds in this period, which must be zero if unsupported
117         * @param type  which set of fields this period supports, null means AllType
118         * @throws IllegalArgumentException if an unsupported field's value is non-zero
119         */
120        public MutablePeriod(int years, int months, int weeks, int days,
121                        int hours, int minutes, int seconds, int millis, PeriodType type) {
122            super(years, months, weeks, days, hours, minutes, seconds, millis, type);
123        }
124    
125        /**
126         * Creates a period from the given millisecond duration using the standard
127         * set of fields.
128         * <p>
129         * Only precise fields in the period type will be used.
130         * For the standard period type this is the time fields only.
131         * Thus the year, month, week and day fields will not be populated.
132         * <p>
133         * If the duration is small, less than one day, then this method will perform
134         * as you might expect and split the fields evenly.
135         * <p>
136         * If the duration is larger than one day then all the remaining duration will
137         * be stored in the largest available precise field, hours in this case.
138         * <p>
139         * For example, a duration equal to (365 + 60 + 5) days will be converted to
140         * ((365 + 60 + 5) * 24) hours by this constructor.
141         * <p>
142         * For more control over the conversion process, you have two options:
143         * <ul>
144         * <li>convert the duration to an {@link Interval}, and from there obtain the period
145         * <li>specify a period type that contains precise definitions of the day and larger
146         * fields, such as the UTC or precise types.
147         * </ul>
148         *
149         * @param duration  the duration, in milliseconds
150         */
151        public MutablePeriod(long duration) {
152            super(duration, null, null);
153        }
154    
155        /**
156         * Creates a period from the given millisecond duration.
157         * <p>
158         * Only precise fields in the period type will be used.
159         * Imprecise fields will not be populated.
160         * <p>
161         * If the duration is small then this method will perform
162         * as you might expect and split the fields evenly.
163         * <p>
164         * If the duration is large then all the remaining duration will
165         * be stored in the largest available precise field.
166         * For details as to which fields are precise, review the period type javadoc.
167         *
168         * @param duration  the duration, in milliseconds
169         * @param type  which set of fields this period supports, null means standard
170         */
171        public MutablePeriod(long duration, PeriodType type) {
172            super(duration, type, null);
173        }
174    
175        /**
176         * Creates a period from the given millisecond duration using the standard
177         * set of fields.
178         * <p>
179         * Only precise fields in the period type will be used.
180         * Imprecise fields will not be populated.
181         * <p>
182         * If the duration is small then this method will perform
183         * as you might expect and split the fields evenly.
184         * <p>
185         * If the duration is large then all the remaining duration will
186         * be stored in the largest available precise field.
187         * For details as to which fields are precise, review the period type javadoc.
188         *
189         * @param duration  the duration, in milliseconds
190         * @param chronology  the chronology to use to split the duration, null means ISO default
191         */
192        public MutablePeriod(long duration, Chronology chronology) {
193            super(duration, null, chronology);
194        }
195    
196        /**
197         * Creates a period from the given millisecond duration.
198         * <p>
199         * Only precise fields in the period type will be used.
200         * Imprecise fields will not be populated.
201         * <p>
202         * If the duration is small then this method will perform
203         * as you might expect and split the fields evenly.
204         * <p>
205         * If the duration is large then all the remaining duration will
206         * be stored in the largest available precise field.
207         * For details as to which fields are precise, review the period type javadoc.
208         *
209         * @param duration  the duration, in milliseconds
210         * @param type  which set of fields this period supports, null means standard
211         * @param chronology  the chronology to use to split the duration, null means ISO default
212         */
213        public MutablePeriod(long duration, PeriodType type, Chronology chronology) {
214            super(duration, type, chronology);
215        }
216    
217        /**
218         * Creates a period from the given interval endpoints using the standard
219         * set of fields.
220         *
221         * @param startInstant  interval start, in milliseconds
222         * @param endInstant  interval end, in milliseconds
223         */
224        public MutablePeriod(long startInstant, long endInstant) {
225            super(startInstant, endInstant, null, null);
226        }
227    
228        /**
229         * Creates a period from the given interval endpoints.
230         *
231         * @param startInstant  interval start, in milliseconds
232         * @param endInstant  interval end, in milliseconds
233         * @param type  which set of fields this period supports, null means standard
234         */
235        public MutablePeriod(long startInstant, long endInstant, PeriodType type) {
236            super(startInstant, endInstant, type, null);
237        }
238    
239        /**
240         * Creates a period from the given interval endpoints using the standard
241         * set of fields.
242         *
243         * @param startInstant  interval start, in milliseconds
244         * @param endInstant  interval end, in milliseconds
245         * @param chrono  the chronology to use, null means ISO in default zone
246         */
247        public MutablePeriod(long startInstant, long endInstant, Chronology chrono) {
248            super(startInstant, endInstant, null, chrono);
249        }
250    
251        /**
252         * Creates a period from the given interval endpoints.
253         *
254         * @param startInstant  interval start, in milliseconds
255         * @param endInstant  interval end, in milliseconds
256         * @param type  which set of fields this period supports, null means standard
257         * @param chrono  the chronology to use, null means ISO in default zone
258         */
259        public MutablePeriod(long startInstant, long endInstant, PeriodType type, Chronology chrono) {
260            super(startInstant, endInstant, type, chrono);
261        }
262    
263        /**
264         * Creates a period from the given interval endpoints using the standard
265         * set of fields.
266         * <p>
267         * The chronology of the start instant is used, unless that is null when the
268         * chronology of the end instant is used instead.
269         *
270         * @param startInstant  interval start, null means now
271         * @param endInstant  interval end, null means now
272         */
273        public MutablePeriod(ReadableInstant startInstant, ReadableInstant endInstant) {
274            super(startInstant, endInstant, null);
275        }
276    
277        /**
278         * Creates a period from the given interval endpoints.
279         * <p>
280         * The chronology of the start instant is used, unless that is null when the
281         * chronology of the end instant is used instead.
282         *
283         * @param startInstant  interval start, null means now
284         * @param endInstant  interval end, null means now
285         * @param type  which set of fields this period supports, null means AllType
286         */
287        public MutablePeriod(ReadableInstant startInstant, ReadableInstant endInstant, PeriodType type) {
288            super(startInstant, endInstant, type);
289        }
290    
291        /**
292         * Creates a period from the given start point and the duration.
293         *
294         * @param startInstant  the interval start, null means now
295         * @param duration  the duration of the interval, null means zero-length
296         */
297        public MutablePeriod(ReadableInstant startInstant, ReadableDuration duration) {
298            super(startInstant, duration, null);
299        }
300    
301        /**
302         * Creates a period from the given start point and the duration.
303         *
304         * @param startInstant  the interval start, null means now
305         * @param duration  the duration of the interval, null means zero-length
306         * @param type  which set of fields this period supports, null means standard
307         */
308        public MutablePeriod(ReadableInstant startInstant, ReadableDuration duration, PeriodType type) {
309            super(startInstant, duration, type);
310        }
311    
312        /**
313         * Creates a period from the given duration and end point.
314         *
315         * @param duration  the duration of the interval, null means zero-length
316         * @param endInstant  the interval end, null means now
317         */
318        public MutablePeriod(ReadableDuration duration, ReadableInstant endInstant) {
319            super(duration, endInstant, null);
320        }
321    
322        /**
323         * Creates a period from the given duration and end point.
324         *
325         * @param duration  the duration of the interval, null means zero-length
326         * @param endInstant  the interval end, null means now
327         * @param type  which set of fields this period supports, null means standard
328         */
329        public MutablePeriod(ReadableDuration duration, ReadableInstant endInstant, PeriodType type) {
330            super(duration, endInstant, type);
331        }
332    
333        /**
334         * Creates a period by converting or copying from another object.
335         * <p>
336         * The recognised object types are defined in
337         * {@link org.joda.time.convert.ConverterManager ConverterManager} and
338         * include ReadablePeriod, ReadableInterval and String.
339         * The String formats are described by {@link ISOPeriodFormat#standard()}.
340         *
341         * @param period  period to convert
342         * @throws IllegalArgumentException if period is invalid
343         * @throws UnsupportedOperationException if an unsupported field's value is non-zero
344         */
345        public MutablePeriod(Object period) {
346            super(period, null, null);
347        }
348    
349        /**
350         * Creates a period by converting or copying from another object.
351         * <p>
352         * The recognised object types are defined in
353         * {@link org.joda.time.convert.ConverterManager ConverterManager} and
354         * include ReadablePeriod, ReadableInterval and String.
355         * The String formats are described by {@link ISOPeriodFormat#standard()}.
356         *
357         * @param period  period to convert
358         * @param type  which set of fields this period supports, null means use converter
359         * @throws IllegalArgumentException if period is invalid
360         * @throws UnsupportedOperationException if an unsupported field's value is non-zero
361         */
362        public MutablePeriod(Object period, PeriodType type) {
363            super(period, type, null);
364        }
365    
366        /**
367         * Creates a period by converting or copying from another object.
368         * <p>
369         * The recognised object types are defined in
370         * {@link org.joda.time.convert.ConverterManager ConverterManager} and
371         * include ReadablePeriod, ReadableInterval and String.
372         * The String formats are described by {@link ISOPeriodFormat#standard()}.
373         *
374         * @param period  period to convert
375         * @param chrono  the chronology to use, null means ISO in default zone
376         * @throws IllegalArgumentException if period is invalid
377         * @throws UnsupportedOperationException if an unsupported field's value is non-zero
378         */
379        public MutablePeriod(Object period, Chronology chrono) {
380            super(period, null, chrono);
381        }
382    
383        /**
384         * Creates a period by converting or copying from another object.
385         * <p>
386         * The recognised object types are defined in
387         * {@link org.joda.time.convert.ConverterManager ConverterManager} and
388         * include ReadablePeriod, ReadableInterval and String.
389         * The String formats are described by {@link ISOPeriodFormat#standard()}.
390         *
391         * @param period  period to convert
392         * @param type  which set of fields this period supports, null means use converter
393         * @param chrono  the chronology to use, null means ISO in default zone
394         * @throws IllegalArgumentException if period is invalid
395         * @throws UnsupportedOperationException if an unsupported field's value is non-zero
396         */
397        public MutablePeriod(Object period, PeriodType type, Chronology chrono) {
398            super(period, type, chrono);
399        }
400    
401        //-----------------------------------------------------------------------
402        /**
403         * Clears the period, setting all values back to zero.
404         */
405        public void clear() {
406            super.setValues(new int[size()]);
407        }
408    
409        /**
410         * Sets the value of one of the fields by index.
411         *
412         * @param index  the field index
413         * @param value  the new value for the field
414         * @throws IndexOutOfBoundsException if the index is invalid
415         */
416        public void setValue(int index, int value) {
417            super.setValue(index, value);
418        }
419    
420        /**
421         * Sets the value of one of the fields.
422         * <p>
423         * The field type specified must be one of those that is supported by the period.
424         *
425         * @param field  a DurationFieldType instance that is supported by this period, not null
426         * @param value  the new value for the field
427         * @throws IllegalArgumentException if the field is null or not supported
428         */
429        public void set(DurationFieldType field, int value) {
430            super.setField(field, value);
431        }
432    
433        /**
434         * Sets all the fields in one go from another ReadablePeriod.
435         * 
436         * @param period  the period to set, null means zero length period
437         * @throws IllegalArgumentException if an unsupported field's value is non-zero
438         */
439        public void setPeriod(ReadablePeriod period) {
440            super.setPeriod(period);
441        }
442    
443        /**
444         * Sets all the fields in one go.
445         * 
446         * @param years  amount of years in this period, which must be zero if unsupported
447         * @param months  amount of months in this period, which must be zero if unsupported
448         * @param weeks  amount of weeks in this period, which must be zero if unsupported
449         * @param days  amount of days in this period, which must be zero if unsupported
450         * @param hours  amount of hours in this period, which must be zero if unsupported
451         * @param minutes  amount of minutes in this period, which must be zero if unsupported
452         * @param seconds  amount of seconds in this period, which must be zero if unsupported
453         * @param millis  amount of milliseconds in this period, which must be zero if unsupported
454         * @throws IllegalArgumentException if an unsupported field's value is non-zero
455         */
456        public void setPeriod(int years, int months, int weeks, int days,
457                              int hours, int minutes, int seconds, int millis) {
458            super.setPeriod(years, months, weeks, days, hours, minutes, seconds, millis);
459        }
460    
461        /**
462         * Sets all the fields in one go from an interval using the ISO chronology
463         * and dividing the fields using the period type.
464         * 
465         * @param interval  the interval to set, null means zero length
466         * @throws ArithmeticException if the set exceeds the capacity of the period
467         */
468        public void setPeriod(ReadableInterval interval) {
469            if (interval == null) {
470                setPeriod(0L);
471            } else {
472                Chronology chrono = DateTimeUtils.getChronology(interval.getChronology());
473                setPeriod(interval.getStartMillis(), interval.getEndMillis(), chrono);
474            }
475        }
476    
477        /**
478         * Sets all the fields in one go from two instants representing an interval.
479         * <p>
480         * The chronology of the start instant is used, unless that is null when the
481         * chronology of the end instant is used instead.
482         * 
483         * @param start  the start instant, null means now
484         * @param end  the end instant, null means now
485         * @throws ArithmeticException if the set exceeds the capacity of the period
486         */
487        public void setPeriod(ReadableInstant start, ReadableInstant end) {
488            if (start == end) {
489                setPeriod(0L);
490            } else {
491                long startMillis = DateTimeUtils.getInstantMillis(start);
492                long endMillis = DateTimeUtils.getInstantMillis(end);
493                Chronology chrono = DateTimeUtils.getIntervalChronology(start, end);
494                setPeriod(startMillis, endMillis, chrono);
495            }
496        }
497    
498        /**
499         * Sets all the fields in one go from a millisecond interval using ISOChronology
500         * and dividing the fields using the period type.
501         * 
502         * @param startInstant  interval start, in milliseconds
503         * @param endInstant  interval end, in milliseconds
504         * @throws ArithmeticException if the set exceeds the capacity of the period
505         */
506        public void setPeriod(long startInstant, long endInstant) {
507            setPeriod(startInstant, endInstant, null);
508        }
509    
510        /**
511         * Sets all the fields in one go from a millisecond interval.
512         * 
513         * @param startInstant  interval start, in milliseconds
514         * @param endInstant  interval end, in milliseconds
515         * @param chrono  the chronology to use, not null
516         * @throws ArithmeticException if the set exceeds the capacity of the period
517         */
518        public void setPeriod(long startInstant, long endInstant, Chronology chrono) {
519            chrono = DateTimeUtils.getChronology(chrono);
520            setValues(chrono.get(this, startInstant, endInstant));
521        }
522    
523        /**
524         * Sets all the fields in one go from a duration dividing the
525         * fields using the period type.
526         * <p>
527         * When dividing the duration, only precise fields in the period type will be used.
528         * For large durations, all the remaining duration will be stored in the largest
529         * available precise field.
530         * 
531         * @param duration  the duration to set, null means zero length
532         * @throws ArithmeticException if the set exceeds the capacity of the period
533         */
534        public void setPeriod(ReadableDuration duration) {
535            setPeriod(duration, null);
536        }
537    
538        /**
539         * Sets all the fields in one go from a duration dividing the
540         * fields using the period type.
541         * <p>
542         * When dividing the duration, only precise fields in the period type will be used.
543         * For large durations, all the remaining duration will be stored in the largest
544         * available precise field.
545         * 
546         * @param duration  the duration to set, null means zero length
547         * @param chrono  the chronology to use, null means ISO default
548         * @throws ArithmeticException if the set exceeds the capacity of the period
549         */
550        public void setPeriod(ReadableDuration duration, Chronology chrono) {
551            long durationMillis = DateTimeUtils.getDurationMillis(duration);
552            setPeriod(durationMillis, chrono);
553        }
554    
555        /**
556         * Sets all the fields in one go from a millisecond duration dividing the
557         * fields using the period type.
558         * <p>
559         * When dividing the duration, only precise fields in the period type will be used.
560         * For large durations, all the remaining duration will be stored in the largest
561         * available precise field.
562         * 
563         * @param duration  the duration, in milliseconds
564         * @throws ArithmeticException if the set exceeds the capacity of the period
565         */
566        public void setPeriod(long duration) {
567            setPeriod(duration, null);
568        }
569    
570        /**
571         * Sets all the fields in one go from a millisecond duration.
572         * <p>
573         * When dividing the duration, only precise fields in the period type will be used.
574         * For large durations, all the remaining duration will be stored in the largest
575         * available precise field.
576         * 
577         * @param duration  the duration, in milliseconds
578         * @param chrono  the chronology to use, not null
579         * @throws ArithmeticException if the set exceeds the capacity of the period
580         */
581        public void setPeriod(long duration, Chronology chrono) {
582            chrono = DateTimeUtils.getChronology(chrono);
583            setValues(chrono.get(this, duration));
584        }
585    
586        //-----------------------------------------------------------------------
587        /**
588         * Adds to the value of one of the fields.
589         * <p>
590         * The field type specified must be one of those that is supported by the period.
591         *
592         * @param field  a DurationFieldType instance that is supported by this period, not null
593         * @param value  the value to add to the field
594         * @throws IllegalArgumentException if the field is null or not supported
595         */
596        public void add(DurationFieldType field, int value) {
597            super.addField(field, value);
598        }
599    
600        /**
601         * Adds a period to this one by adding each field in turn.
602         * 
603         * @param period  the period to add, null means add nothing
604         * @throws IllegalArgumentException if the period being added contains a field
605         * not supported by this period
606         * @throws ArithmeticException if the addition exceeds the capacity of the period
607         */
608        public void add(ReadablePeriod period) {
609            super.addPeriod(period);
610        }
611    
612        /**
613         * Adds to each field of this period.
614         * 
615         * @param years  amount of years to add to this period, which must be zero if unsupported
616         * @param months  amount of months to add to this period, which must be zero if unsupported
617         * @param weeks  amount of weeks to add to this period, which must be zero if unsupported
618         * @param days  amount of days to add to this period, which must be zero if unsupported
619         * @param hours  amount of hours to add to this period, which must be zero if unsupported
620         * @param minutes  amount of minutes to add to this period, which must be zero if unsupported
621         * @param seconds  amount of seconds to add to this period, which must be zero if unsupported
622         * @param millis  amount of milliseconds to add to this period, which must be zero if unsupported
623         * @throws IllegalArgumentException if the period being added contains a field
624         * not supported by this period
625         * @throws ArithmeticException if the addition exceeds the capacity of the period
626         */
627        public void add(int years, int months, int weeks, int days,
628                           int hours, int minutes, int seconds, int millis) {
629            setPeriod(
630                FieldUtils.safeAdd(getYears(), years),
631                FieldUtils.safeAdd(getMonths(), months),
632                FieldUtils.safeAdd(getWeeks(), weeks),
633                FieldUtils.safeAdd(getDays(), days),
634                FieldUtils.safeAdd(getHours(), hours),
635                FieldUtils.safeAdd(getMinutes(), minutes),
636                FieldUtils.safeAdd(getSeconds(), seconds),
637                FieldUtils.safeAdd(getMillis(), millis)
638            );
639        }
640    
641        /**
642         * Adds an interval to this one by dividing the interval into
643         * fields and calling {@link #add(ReadablePeriod)}.
644         * 
645         * @param interval  the interval to add, null means add nothing
646         * @throws ArithmeticException if the addition exceeds the capacity of the period
647         */
648        public void add(ReadableInterval interval) {
649            if (interval != null) {
650                add(interval.toPeriod(getPeriodType()));
651            }
652        }
653    
654        /**
655         * Adds a duration to this one by dividing the duration into
656         * fields and calling {@link #add(ReadablePeriod)}.
657         * 
658         * @param duration  the duration to add, null means add nothing
659         * @throws ArithmeticException if the addition exceeds the capacity of the period
660         */
661        public void add(ReadableDuration duration) {
662            if (duration != null) {
663                add(new Period(duration.getMillis(), getPeriodType()));
664            }
665        }
666    
667        /**
668         * Adds a millisecond duration to this one by dividing the duration into
669         * fields and calling {@link #add(ReadablePeriod)}.
670         * <p>
671         * When dividing the duration, only precise fields in the period type will be used.
672         * For large durations, all the remaining duration will be stored in the largest
673         * available precise field.
674         * 
675         * @param duration  the duration, in milliseconds
676         * @throws ArithmeticException if the addition exceeds the capacity of the period
677         */
678        public void add(long duration) {
679            add(new Period(duration, getPeriodType()));
680        }
681    
682        /**
683         * Adds a millisecond duration to this one by dividing the duration into
684         * fields and calling {@link #add(ReadablePeriod)}.
685         * <p>
686         * When dividing the duration, only precise fields in the period type will be used.
687         * For large durations, all the remaining duration will be stored in the largest
688         * available precise field.
689         * 
690         * @param duration  the duration, in milliseconds
691         * @param chrono  the chronology to use, null means ISO default
692         * @throws ArithmeticException if the addition exceeds the capacity of the period
693         */
694        public void add(long duration, Chronology chrono) {
695            add(new Period(duration, getPeriodType(), chrono));
696        }
697    
698        //-----------------------------------------------------------------------
699        /**
700         * Merges all the fields from the specified period into this one.
701         * <p>
702         * Fields that are not present in the specified period are left unaltered.
703         * 
704         * @param period  the period to set, null ignored
705         * @throws IllegalArgumentException if an unsupported field's value is non-zero
706         */
707        public void mergePeriod(ReadablePeriod period) {
708            super.mergePeriod(period);
709        }
710    
711        //-----------------------------------------------------------------------
712        /**
713         * Gets the years field part of the period.
714         * 
715         * @return the number of years in the period, zero if unsupported
716         */
717        public int getYears() {
718            return getPeriodType().getIndexedField(this, PeriodType.YEAR_INDEX);
719        }
720    
721        /**
722         * Gets the months field part of the period.
723         * 
724         * @return the number of months in the period, zero if unsupported
725         */
726        public int getMonths() {
727            return getPeriodType().getIndexedField(this, PeriodType.MONTH_INDEX);
728        }
729    
730        /**
731         * Gets the weeks field part of the period.
732         * 
733         * @return the number of weeks in the period, zero if unsupported
734         */
735        public int getWeeks() {
736            return getPeriodType().getIndexedField(this, PeriodType.WEEK_INDEX);
737        }
738    
739        /**
740         * Gets the days field part of the period.
741         * 
742         * @return the number of days in the period, zero if unsupported
743         */
744        public int getDays() {
745            return getPeriodType().getIndexedField(this, PeriodType.DAY_INDEX);
746        }
747    
748        //-----------------------------------------------------------------------
749        /**
750         * Gets the hours field part of the period.
751         * 
752         * @return the number of hours in the period, zero if unsupported
753         */
754        public int getHours() {
755            return getPeriodType().getIndexedField(this, PeriodType.HOUR_INDEX);
756        }
757    
758        /**
759         * Gets the minutes field part of the period.
760         * 
761         * @return the number of minutes in the period, zero if unsupported
762         */
763        public int getMinutes() {
764            return getPeriodType().getIndexedField(this, PeriodType.MINUTE_INDEX);
765        }
766    
767        /**
768         * Gets the seconds field part of the period.
769         * 
770         * @return the number of seconds in the period, zero if unsupported
771         */
772        public int getSeconds() {
773            return getPeriodType().getIndexedField(this, PeriodType.SECOND_INDEX);
774        }
775    
776        /**
777         * Gets the millis field part of the period.
778         * 
779         * @return the number of millis in the period, zero if unsupported
780         */
781        public int getMillis() {
782            return getPeriodType().getIndexedField(this, PeriodType.MILLI_INDEX);
783        }
784    
785        //-----------------------------------------------------------------------
786        /**
787         * Sets the number of years of the period.
788         * 
789         * @param years  the number of years
790         * @throws IllegalArgumentException if field is not supported and the value is non-zero
791         */
792        public void setYears(int years) {
793            super.setField(DurationFieldType.years(), years);
794        }
795    
796        /**
797         * Adds the specified years to the number of years in the period.
798         * 
799         * @param years  the number of years
800         * @throws IllegalArgumentException if field is not supported and the value is non-zero
801         * @throws ArithmeticException if the addition exceeds the capacity of the period
802         */
803        public void addYears(int years) {
804            super.addField(DurationFieldType.years(), years);
805        }
806    
807        //-----------------------------------------------------------------------
808        /**
809         * Sets the number of months of the period.
810         * 
811         * @param months  the number of months
812         * @throws IllegalArgumentException if field is not supported and the value is non-zero
813         */
814        public void setMonths(int months) {
815            super.setField(DurationFieldType.months(), months);
816        }
817    
818        /**
819         * Adds the specified months to the number of months in the period.
820         * 
821         * @param months  the number of months
822         * @throws IllegalArgumentException if field is not supported and the value is non-zero
823         * @throws ArithmeticException if the addition exceeds the capacity of the period
824         */
825        public void addMonths(int months) {
826            super.addField(DurationFieldType.months(), months);
827        }
828    
829        //-----------------------------------------------------------------------
830        /**
831         * Sets the number of weeks of the period.
832         * 
833         * @param weeks  the number of weeks
834         * @throws IllegalArgumentException if field is not supported and the value is non-zero
835         */
836        public void setWeeks(int weeks) {
837            super.setField(DurationFieldType.weeks(), weeks);
838        }
839    
840        /**
841         * Adds the specified weeks to the number of weeks in the period.
842         * 
843         * @param weeks  the number of weeks
844         * @throws IllegalArgumentException if field is not supported and the value is non-zero
845         * @throws ArithmeticException if the addition exceeds the capacity of the period
846         */
847        public void addWeeks(int weeks) {
848            super.addField(DurationFieldType.weeks(), weeks);
849        }
850    
851        //-----------------------------------------------------------------------
852        /**
853         * Sets the number of days of the period.
854         * 
855         * @param days  the number of days
856         * @throws IllegalArgumentException if field is not supported and the value is non-zero
857         */
858        public void setDays(int days) {
859            super.setField(DurationFieldType.days(), days);
860        }
861    
862        /**
863         * Adds the specified days to the number of days in the period.
864         * 
865         * @param days  the number of days
866         * @throws IllegalArgumentException if field is not supported and the value is non-zero
867         * @throws ArithmeticException if the addition exceeds the capacity of the period
868         */
869        public void addDays(int days) {
870            super.addField(DurationFieldType.days(), days);
871        }
872    
873        //-----------------------------------------------------------------------
874        /**
875         * Sets the number of hours of the period.
876         * 
877         * @param hours  the number of hours
878         * @throws IllegalArgumentException if field is not supported and the value is non-zero
879         */
880        public void setHours(int hours) {
881            super.setField(DurationFieldType.hours(), hours);
882        }
883    
884        /**
885         * Adds the specified hours to the number of hours in the period.
886         * 
887         * @param hours  the number of hours
888         * @throws IllegalArgumentException if field is not supported and the value is non-zero
889         * @throws ArithmeticException if the addition exceeds the capacity of the period
890         */
891        public void addHours(int hours) {
892            super.addField(DurationFieldType.hours(), hours);
893        }
894    
895        //-----------------------------------------------------------------------
896        /**
897         * Sets the number of minutes of the period.
898         * 
899         * @param minutes  the number of minutes
900         * @throws IllegalArgumentException if field is not supported and the value is non-zero
901         */
902        public void setMinutes(int minutes) {
903            super.setField(DurationFieldType.minutes(), minutes);
904        }
905    
906        /**
907         * Adds the specified minutes to the number of minutes in the period.
908         * 
909         * @param minutes  the number of minutes
910         * @throws IllegalArgumentException if field is not supported and the value is non-zero
911         * @throws ArithmeticException if the addition exceeds the capacity of the period
912         */
913        public void addMinutes(int minutes) {
914            super.addField(DurationFieldType.minutes(), minutes);
915        }
916    
917        //-----------------------------------------------------------------------
918        /**
919         * Sets the number of seconds of the period.
920         * 
921         * @param seconds  the number of seconds
922         * @throws IllegalArgumentException if field is not supported and the value is non-zero
923         */
924        public void setSeconds(int seconds) {
925            super.setField(DurationFieldType.seconds(), seconds);
926        }
927    
928        /**
929         * Adds the specified seconds to the number of seconds in the period.
930         * 
931         * @param seconds  the number of seconds
932         * @throws IllegalArgumentException if field is not supported and the value is non-zero
933         * @throws ArithmeticException if the addition exceeds the capacity of the period
934         */
935        public void addSeconds(int seconds) {
936            super.addField(DurationFieldType.seconds(), seconds);
937        }
938    
939        //-----------------------------------------------------------------------
940        /**
941         * Sets the number of millis of the period.
942         * 
943         * @param millis  the number of millis
944         * @throws IllegalArgumentException if field is not supported and the value is non-zero
945         */
946        public void setMillis(int millis) {
947            super.setField(DurationFieldType.millis(), millis);
948        }
949    
950        /**
951         * Adds the specified millis to the number of millis in the period.
952         * 
953         * @param millis  the number of millis
954         * @throws IllegalArgumentException if field is not supported and the value is non-zero
955         * @throws ArithmeticException if the addition exceeds the capacity of the period
956         */
957        public void addMillis(int millis) {
958            super.addField(DurationFieldType.millis(), millis);
959        }
960    
961        // Misc
962        //-----------------------------------------------------------------------
963        /**
964         * Clone this object without having to cast the returned object.
965         *
966         * @return a clone of the this object.
967         */
968        public MutablePeriod copy() {
969            return (MutablePeriod) clone();
970        }
971    
972        /**
973         * Clone this object.
974         *
975         * @return a clone of this object.
976         */
977        public Object clone() {
978            try {
979                return super.clone();
980            } catch (CloneNotSupportedException ex) {
981                throw new InternalError("Clone error");
982            }
983        }
984    
985    }