1 | /* |
2 | * Copyright 2001-2005 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.time.base.BasePeriod; |
21 | import org.joda.time.field.FieldUtils; |
22 | import org.joda.time.format.ISOPeriodFormat; |
23 | |
24 | /** |
25 | * Standard mutable time period implementation. |
26 | * <p> |
27 | * A time period is divided into a number of fields, such as hours and seconds. |
28 | * Which fields are supported is defined by the PeriodType class. |
29 | * The default is the standard period type, which supports years, months, weeks, days, |
30 | * hours, minutes, seconds and millis. |
31 | * <p> |
32 | * When this time period is added to an instant, the effect is of adding each field in turn. |
33 | * As a result, this takes into account daylight savings time. |
34 | * Adding a time period of 1 day to the day before daylight savings starts will only add |
35 | * 23 hours rather than 24 to ensure that the time remains the same. |
36 | * If this is not the behaviour you want, then see {@link Duration}. |
37 | * <p> |
38 | * The definition of a period also affects the equals method. A period of 1 |
39 | * day is not equal to a period of 24 hours, nor 1 hour equal to 60 minutes. |
40 | * This is because periods represent an abstracted definition of a time period |
41 | * (eg. a day may not actually be 24 hours, it might be 23 or 25 at daylight |
42 | * savings boundary). To compare the actual duration of two periods, convert |
43 | * both to durations using toDuration, an operation that emphasises that the |
44 | * result may differ according to the date you choose. |
45 | * <p> |
46 | * MutablePeriod is mutable and not thread-safe, unless concurrent threads |
47 | * are not invoking mutator methods. |
48 | * |
49 | * @author Brian S O'Neill |
50 | * @author Stephen Colebourne |
51 | * @since 1.0 |
52 | * @see Period |
53 | */ |
54 | public class MutablePeriod |
55 | extends BasePeriod |
56 | implements ReadWritablePeriod, Cloneable, Serializable { |
57 | |
58 | /** Serialization version */ |
59 | private static final long serialVersionUID = 3436451121567212165L; |
60 | |
61 | /** |
62 | * Creates a zero-length period using the standard period type. |
63 | */ |
64 | public MutablePeriod() { |
65 | super(0L, null, null); |
66 | } |
67 | |
68 | /** |
69 | * Creates a zero-length period using the specified period type. |
70 | * |
71 | * @param type which set of fields this period supports |
72 | */ |
73 | public MutablePeriod(PeriodType type) { |
74 | super(0L, type, null); |
75 | } |
76 | |
77 | /** |
78 | * Create a period from a set of field values using the standard set of fields. |
79 | * |
80 | * @param hours amount of hours in this period |
81 | * @param minutes amount of minutes in this period |
82 | * @param seconds amount of seconds in this period |
83 | * @param millis amount of milliseconds in this period |
84 | */ |
85 | public MutablePeriod(int hours, int minutes, int seconds, int millis) { |
86 | super(0, 0, 0, 0, hours, minutes, seconds, millis, PeriodType.standard()); |
87 | } |
88 | |
89 | /** |
90 | * Create a period from a set of field values using the standard set of fields. |
91 | * |
92 | * @param years amount of years in this period |
93 | * @param months amount of months in this period |
94 | * @param weeks amount of weeks in this period |
95 | * @param days amount of days in this period |
96 | * @param hours amount of hours in this period |
97 | * @param minutes amount of minutes in this period |
98 | * @param seconds amount of seconds in this period |
99 | * @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 | } |