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 */
016package org.joda.time;
017
018import java.io.Serializable;
019
020import org.joda.convert.FromString;
021import org.joda.time.base.BasePeriod;
022import org.joda.time.field.FieldUtils;
023import org.joda.time.format.ISOPeriodFormat;
024import 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 */
056public 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}