View Javadoc

1   /*
2    *  Copyright 2001-2011 Stephen Colebourne
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  package org.joda.time;
17  
18  import java.io.Serializable;
19  
20  import org.joda.convert.FromString;
21  import org.joda.time.base.BasePeriod;
22  import org.joda.time.field.FieldUtils;
23  import org.joda.time.format.ISOPeriodFormat;
24  import org.joda.time.format.PeriodFormatter;
25  
26  /**
27   * Standard mutable time period implementation.
28   * <p>
29   * A time period is divided into a number of fields, such as hours and seconds.
30   * Which fields are supported is defined by the PeriodType class.
31   * The default is the standard period type, which supports years, months, weeks, days,
32   * hours, minutes, seconds and millis.
33   * <p>
34   * When this time period is added to an instant, the effect is of adding each field in turn.
35   * As a result, this takes into account daylight savings time.
36   * Adding a time period of 1 day to the day before daylight savings starts will only add
37   * 23 hours rather than 24 to ensure that the time remains the same.
38   * If this is not the behaviour you want, then see {@link Duration}.
39   * <p>
40   * The definition of a period also affects the equals method. A period of 1
41   * day is not equal to a period of 24 hours, nor 1 hour equal to 60 minutes.
42   * This is because periods represent an abstracted definition of a time period
43   * (eg. a day may not actually be 24 hours, it might be 23 or 25 at daylight
44   * savings boundary). To compare the actual duration of two periods, convert
45   * both to durations using toDuration, an operation that emphasises that the
46   * result may differ according to the date you choose.
47   * <p>
48   * MutablePeriod is mutable and not thread-safe, unless concurrent threads
49   * are not invoking mutator methods.
50   *
51   * @author Brian S O'Neill
52   * @author Stephen Colebourne
53   * @since 1.0
54   * @see Period
55   */
56  public class MutablePeriod
57          extends BasePeriod
58          implements ReadWritablePeriod, Cloneable, Serializable {
59  
60      /** Serialization version */
61      private static final long serialVersionUID = 3436451121567212165L;
62  
63      //-----------------------------------------------------------------------
64      /**
65       * Parses a {@code MutablePeriod} from the specified string.
66       * <p>
67       * This uses {@link ISOPeriodFormat#standard()}.
68       * 
69       * @param str  the string to parse, not null
70       * @since 2.0
71       */
72      @FromString
73      public static MutablePeriod parse(String str) {
74          return parse(str, ISOPeriodFormat.standard());
75      }
76  
77      /**
78       * Parses a {@code MutablePeriod} from the specified string using a formatter.
79       * 
80       * @param str  the string to parse, not null
81       * @param formatter  the formatter to use, not null
82       * @since 2.0
83       */
84      public static MutablePeriod parse(String str, PeriodFormatter formatter) {
85          return formatter.parsePeriod(str).toMutablePeriod();
86      }
87  
88      //-----------------------------------------------------------------------
89      /**
90       * Creates a zero-length period using the standard period type.
91       */
92      public MutablePeriod() {
93          super(0L, null, null);
94      }
95  
96      /**
97       * Creates a zero-length period using the specified period type.
98       *
99       * @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 }