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 }