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