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