View Javadoc

1   /*
2    *  Copyright 2001-2010 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.chrono.ISOChronology;
23  import org.joda.time.field.FieldUtils;
24  import org.joda.time.format.ISOPeriodFormat;
25  import org.joda.time.format.PeriodFormatter;
26  
27  /**
28   * An immutable time period specifying a set of duration field values.
29   * <p>
30   * A time period is divided into a number of fields, such as hours and seconds.
31   * Which fields are supported is defined by the PeriodType class.
32   * The default is the standard period type, which supports years, months, weeks, days,
33   * hours, minutes, seconds and millis.
34   * <p>
35   * When this time period is added to an instant, the effect is of adding each field in turn.
36   * As a result, this takes into account daylight savings time.
37   * Adding a time period of 1 day to the day before daylight savings starts will only add
38   * 23 hours rather than 24 to ensure that the time remains the same.
39   * If this is not the behaviour you want, then see {@link Duration}.
40   * <p>
41   * The definition of a period also affects the equals method. A period of 1
42   * day is not equal to a period of 24 hours, nor 1 hour equal to 60 minutes.
43   * This is because periods represent an abstracted definition of a time period
44   * (eg. a day may not actually be 24 hours, it might be 23 or 25 at daylight
45   * savings boundary). To compare the actual duration of two periods, convert
46   * both to durations using toDuration, an operation that emphasises that the
47   * result may differ according to the date you choose.
48   * <p>
49   * Period is thread-safe and immutable, provided that the PeriodType is as well.
50   * All standard PeriodType classes supplied are thread-safe and immutable.
51   *
52   * @author Brian S O'Neill
53   * @author Stephen Colebourne
54   * @since 1.0
55   * @see MutablePeriod
56   */
57  public final class Period
58          extends BasePeriod
59          implements ReadablePeriod, Serializable {
60  
61      /**
62       * A period of zero length and standard period type.
63       * @since 1.4
64       */
65      public static final Period ZERO = new Period();
66  
67      /** Serialization version */
68      private static final long serialVersionUID = 741052353876488155L;
69  
70      //-----------------------------------------------------------------------
71      /**
72       * Parses a {@code Period} from the specified string.
73       * <p>
74       * This uses {@link ISOPeriodFormat#standard()}.
75       * 
76       * @param str  the string to parse, not null
77       * @since 2.0
78       */
79      @FromString
80      public static Period parse(String str) {
81          return parse(str, ISOPeriodFormat.standard());
82      }
83  
84      /**
85       * Parses a {@code Period} from the specified string using a formatter.
86       * 
87       * @param str  the string to parse, not null
88       * @param formatter  the formatter to use, not null
89       * @since 2.0
90       */
91      public static Period parse(String str, PeriodFormatter formatter) {
92          return formatter.parsePeriod(str);
93      }
94  
95      //-----------------------------------------------------------------------
96      /**
97       * Create a period with a specified number of years.
98       * <p>
99       * The standard period type is used, thus you can add other fields such
100      * as months or days using the <code>withXxx()</code> methods.
101      * For example, <code>Period.years(2).withMonths(6);</code>
102      * <p>
103      * If you want a year-based period that cannot have other fields added,
104      * then you should consider using {@link Years}.
105      *
106      * @param years  the amount of years in this period
107      * @return the period
108      */
109     public static Period years(int years) {
110         return new Period(new int[] {years, 0, 0, 0, 0, 0, 0, 0, 0}, PeriodType.standard());
111     }
112 
113     /**
114      * Create a period with a specified number of months.
115      * <p>
116      * The standard period type is used, thus you can add other fields such
117      * as years or days using the <code>withXxx()</code> methods.
118      * For example, <code>Period.months(2).withDays(6);</code>
119      * <p>
120      * If you want a month-based period that cannot have other fields added,
121      * then you should consider using {@link Months}.
122      *
123      * @param months  the amount of months in this period
124      * @return the period
125      */
126     public static Period months(int months) {
127         return new Period(new int[] {0, months, 0, 0, 0, 0, 0, 0}, PeriodType.standard());
128     }
129 
130     /**
131      * Create a period with a specified number of weeks.
132      * <p>
133      * The standard period type is used, thus you can add other fields such
134      * as months or days using the <code>withXxx()</code> methods.
135      * For example, <code>Period.weeks(2).withDays(6);</code>
136      * <p>
137      * If you want a week-based period that cannot have other fields added,
138      * then you should consider using {@link Weeks}.
139      *
140      * @param weeks  the amount of weeks in this period
141      * @return the period
142      */
143     public static Period weeks(int weeks) {
144         return new Period(new int[] {0, 0, weeks, 0, 0, 0, 0, 0}, PeriodType.standard());
145     }
146 
147     /**
148      * Create a period with a specified number of days.
149      * <p>
150      * The standard period type is used, thus you can add other fields such
151      * as months or weeks using the <code>withXxx()</code> methods.
152      * For example, <code>Period.days(2).withHours(6);</code>
153      * <p>
154      * If you want a day-based period that cannot have other fields added,
155      * then you should consider using {@link Days}.
156      *
157      * @param days  the amount of days in this period
158      * @return the period
159      */
160     public static Period days(int days) {
161         return new Period(new int[] {0, 0, 0, days, 0, 0, 0, 0}, PeriodType.standard());
162     }
163 
164     /**
165      * Create a period with a specified number of hours.
166      * <p>
167      * The standard period type is used, thus you can add other fields such
168      * as months or days using the <code>withXxx()</code> methods.
169      * For example, <code>Period.hours(2).withMinutes(30);</code>
170      * <p>
171      * If you want a hour-based period that cannot have other fields added,
172      * then you should consider using {@link Hours}.
173      *
174      * @param hours  the amount of hours in this period
175      * @return the period
176      */
177     public static Period hours(int hours) {
178         return new Period(new int[] {0, 0, 0, 0, hours, 0, 0, 0}, PeriodType.standard());
179     }
180 
181     /**
182      * Create a period with a specified number of minutes.
183      * <p>
184      * The standard period type is used, thus you can add other fields such
185      * as days or hours using the <code>withXxx()</code> methods.
186      * For example, <code>Period.minutes(2).withSeconds(30);</code>
187      * <p>
188      * If you want a minute-based period that cannot have other fields added,
189      * then you should consider using {@link Minutes}.
190      *
191      * @param minutes  the amount of minutes in this period
192      * @return the period
193      */
194     public static Period minutes(int minutes) {
195         return new Period(new int[] {0, 0, 0, 0, 0, minutes, 0, 0}, PeriodType.standard());
196     }
197 
198     /**
199      * Create a period with a specified number of seconds.
200      * <p>
201      * The standard period type is used, thus you can add other fields such
202      * as days or hours using the <code>withXxx()</code> methods.
203      * For example, <code>Period.seconds(2).withMillis(30);</code>
204      * <p>
205      * If you want a second-based period that cannot have other fields added,
206      * then you should consider using {@link Seconds}.
207      *
208      * @param seconds  the amount of seconds in this period
209      * @return the period
210      */
211     public static Period seconds(int seconds) {
212         return new Period(new int[] {0, 0, 0, 0, 0, 0, seconds, 0}, PeriodType.standard());
213     }
214 
215     /**
216      * Create a period with a specified number of millis.
217      * <p>
218      * The standard period type is used, thus you can add other fields such
219      * as days or hours using the <code>withXxx()</code> methods.
220      * For example, <code>Period.millis(20).withSeconds(30);</code>
221      *
222      * @param millis  the amount of millis in this period
223      * @return the period
224      */
225     public static Period millis(int millis) {
226         return new Period(new int[] {0, 0, 0, 0, 0, 0, 0, millis}, PeriodType.standard());
227     }
228 
229     //-----------------------------------------------------------------------
230     /**
231      * Creates a period from two partially specified times, calculating
232      * by field difference.
233      * <p>
234      * The two partials must contain the same fields, thus you can specify
235      * two <code>LocalDate</code> objects, or two <code>LocalTime</code> objects,
236      * but not one of each. Also, the partial may not contain overlapping
237      * fields, such as dayOfWeek and dayOfMonth.
238      * <p>
239      * Calculation by field difference works by extracting the difference
240      * one field at a time and not wrapping into other fields.
241      * Thus 2005-06-09/2007-04-12 will yield P1Y-2M3D.
242      * <p>
243      * For example, you have an event that always runs from the 27th of
244      * each month to the 2nd of the next month. If you calculate this
245      * period using a standard constructor, then you will get between
246      * P3D and P6D depending on the month. If you use this method, then
247      * you will get P1M-25D. This field-difference based period can
248      * be successfully applied to each month of the year to obtain the
249      * correct end date for a given start date.
250      *
251      * @param start  the start of the period, must not be null
252      * @param end  the end of the period, must not be null
253      * @throws IllegalArgumentException if the partials are null or invalid
254      * @since 1.1
255      */
256     public static Period fieldDifference(ReadablePartial start, ReadablePartial end) {
257         if (start == null || end == null) {
258             throw new IllegalArgumentException("ReadablePartial objects must not be null");
259         }
260         if (start.size() != end.size()) {
261             throw new IllegalArgumentException("ReadablePartial objects must have the same set of fields");
262         }
263         DurationFieldType[] types = new DurationFieldType[start.size()];
264         int[] values = new int[start.size()];
265         for (int i = 0, isize = start.size(); i < isize; i++) {
266             if (start.getFieldType(i) != end.getFieldType(i)) {
267                 throw new IllegalArgumentException("ReadablePartial objects must have the same set of fields");
268             }
269             types[i] = start.getFieldType(i).getDurationType();
270             if (i > 0 && types[i - 1] == types[i]) {
271                 throw new IllegalArgumentException("ReadablePartial objects must not have overlapping fields");
272             }
273             values[i] = end.getValue(i) - start.getValue(i);
274         }
275         return new Period(values, PeriodType.forFields(types));
276     }
277 
278     //-----------------------------------------------------------------------
279     /**
280      * Creates a new empty period with the standard set of fields.
281      * <p>
282      * One way to initialise a period is as follows:
283      * <pre>
284      * Period = new Period().withYears(6).withMonths(3).withSeconds(23);
285      * </pre>
286      * Bear in mind that this creates four period instances in total, three of
287      * which are immediately discarded.
288      * The alterative is more efficient, but less readable:
289      * <pre>
290      * Period = new Period(6, 3, 0, 0, 0, 0, 23, 0);
291      * </pre>
292      * The following is also slightly less wasteful:
293      * <pre>
294      * Period = Period.years(6).withMonths(3).withSeconds(23);
295      * </pre>
296      */
297     public Period() {
298         super(0L, null, null);
299     }
300 
301     /**
302      * Create a period from a set of field values using the standard set of fields.
303      * Note that the parameters specify the time fields hours, minutes,
304      * seconds and millis, not the date fields.
305      *
306      * @param hours  amount of hours in this period
307      * @param minutes  amount of minutes in this period
308      * @param seconds  amount of seconds in this period
309      * @param millis  amount of milliseconds in this period
310      */
311     public Period(int hours, int minutes, int seconds, int millis) {
312         super(0, 0, 0, 0, hours, minutes, seconds, millis, PeriodType.standard());
313     }
314 
315     /**
316      * Create a period from a set of field values using the standard set of fields.
317      *
318      * @param years  amount of years in this period
319      * @param months  amount of months in this period
320      * @param weeks  amount of weeks in this period
321      * @param days  amount of days in this period
322      * @param hours  amount of hours in this period
323      * @param minutes  amount of minutes in this period
324      * @param seconds  amount of seconds in this period
325      * @param millis  amount of milliseconds in this period
326      */
327     public Period(int years, int months, int weeks, int days,
328                   int hours, int minutes, int seconds, int millis) {
329         super(years, months, weeks, days, hours, minutes, seconds, millis, PeriodType.standard());
330     }
331 
332     /**
333      * Create a period from a set of field values.
334      * <p>
335      * There is usually little need to use this constructor.
336      * The period type is used primarily to define how to split an interval into a period.
337      * As this constructor already is split, the period type does no real work.
338      *
339      * @param years  amount of years in this period, which must be zero if unsupported
340      * @param months  amount of months in this period, which must be zero if unsupported
341      * @param weeks  amount of weeks in this period, which must be zero if unsupported
342      * @param days  amount of days in this period, which must be zero if unsupported
343      * @param hours  amount of hours in this period, which must be zero if unsupported
344      * @param minutes  amount of minutes in this period, which must be zero if unsupported
345      * @param seconds  amount of seconds in this period, which must be zero if unsupported
346      * @param millis  amount of milliseconds in this period, which must be zero if unsupported
347      * @param type  which set of fields this period supports, null means AllType
348      * @throws IllegalArgumentException if an unsupported field's value is non-zero
349      */
350     public Period(int years, int months, int weeks, int days,
351                     int hours, int minutes, int seconds, int millis, PeriodType type) {
352         super(years, months, weeks, days, hours, minutes, seconds, millis, type);
353     }
354 
355     /**
356      * Creates a period from the given millisecond duration using the standard
357      * set of fields.
358      * <p>
359      * Only precise fields in the period type will be used.
360      * For the standard period type this is the time fields only.
361      * Thus the year, month, week and day fields will not be populated.
362      * <p>
363      * If the duration is small, less than one day, then this method will perform
364      * as you might expect and split the fields evenly.
365      * <p>
366      * If the duration is larger than one day then all the remaining duration will
367      * be stored in the largest available precise field, hours in this case.
368      * <p>
369      * For example, a duration equal to (365 + 60 + 5) days will be converted to
370      * ((365 + 60 + 5) * 24) hours by this constructor.
371      * <p>
372      * For more control over the conversion process, you have two options:
373      * <ul>
374      * <li>convert the duration to an {@link Interval}, and from there obtain the period
375      * <li>specify a period type that contains precise definitions of the day and larger
376      * fields, such as UTC
377      * </ul>
378      *
379      * @param duration  the duration, in milliseconds
380      */
381     public Period(long duration) {
382         super(duration);
383     }
384 
385     /**
386      * Creates a period from the given millisecond duration.
387      * <p>
388      * Only precise fields in the period type will be used.
389      * Imprecise fields will not be populated.
390      * <p>
391      * If the duration is small then this method will perform
392      * as you might expect and split the fields evenly.
393      * <p>
394      * If the duration is large then all the remaining duration will
395      * be stored in the largest available precise field.
396      * For details as to which fields are precise, review the period type javadoc.
397      *
398      * @param duration  the duration, in milliseconds
399      * @param type  which set of fields this period supports, null means standard
400      */
401     public Period(long duration, PeriodType type) {
402         super(duration, type, null);
403     }
404 
405     /**
406      * Creates a period from the given millisecond duration using the standard
407      * set of fields.
408      * <p>
409      * Only precise fields in the period type will be used.
410      * Imprecise fields will not be populated.
411      * <p>
412      * If the duration is small then this method will perform
413      * as you might expect and split the fields evenly.
414      * <p>
415      * If the duration is large then all the remaining duration will
416      * be stored in the largest available precise field.
417      * For details as to which fields are precise, review the period type javadoc.
418      *
419      * @param duration  the duration, in milliseconds
420      * @param chronology  the chronology to use to split the duration, null means ISO default
421      */
422     public Period(long duration, Chronology chronology) {
423         super(duration, null, chronology);
424     }
425 
426     /**
427      * Creates a period from the given millisecond duration.
428      * <p>
429      * Only precise fields in the period type will be used.
430      * Imprecise fields will not be populated.
431      * <p>
432      * If the duration is small then this method will perform
433      * as you might expect and split the fields evenly.
434      * <p>
435      * If the duration is large then all the remaining duration will
436      * be stored in the largest available precise field.
437      * For details as to which fields are precise, review the period type javadoc.
438      *
439      * @param duration  the duration, in milliseconds
440      * @param type  which set of fields this period supports, null means standard
441      * @param chronology  the chronology to use to split the duration, null means ISO default
442      */
443     public Period(long duration, PeriodType type, Chronology chronology) {
444         super(duration, type, chronology);
445     }
446 
447     /**
448      * Creates a period from the given interval endpoints using the standard
449      * set of fields.
450      *
451      * @param startInstant  interval start, in milliseconds
452      * @param endInstant  interval end, in milliseconds
453      */
454     public Period(long startInstant, long endInstant) {
455         super(startInstant, endInstant, null, null);
456     }
457 
458     /**
459      * Creates a period from the given interval endpoints.
460      *
461      * @param startInstant  interval start, in milliseconds
462      * @param endInstant  interval end, in milliseconds
463      * @param type  which set of fields this period supports, null means standard
464      */
465     public Period(long startInstant, long endInstant, PeriodType type) {
466         super(startInstant, endInstant, type, null);
467     }
468 
469     /**
470      * Creates a period from the given interval endpoints using the standard
471      * set of fields.
472      *
473      * @param startInstant  interval start, in milliseconds
474      * @param endInstant  interval end, in milliseconds
475      * @param chrono  the chronology to use, null means ISO in default zone
476      */
477     public Period(long startInstant, long endInstant, Chronology chrono) {
478         super(startInstant, endInstant, null, chrono);
479     }
480 
481     /**
482      * Creates a period from the given interval endpoints.
483      *
484      * @param startInstant  interval start, in milliseconds
485      * @param endInstant  interval end, in milliseconds
486      * @param type  which set of fields this period supports, null means standard
487      * @param chrono  the chronology to use, null means ISO in default zone
488      */
489     public Period(long startInstant, long endInstant, PeriodType type, Chronology chrono) {
490         super(startInstant, endInstant, type, chrono);
491     }
492 
493     /**
494      * Creates a period from the given interval endpoints using the standard
495      * set of fields.
496      *
497      * @param startInstant  interval start, null means now
498      * @param endInstant  interval end, null means now
499      */
500     public Period(ReadableInstant startInstant, ReadableInstant endInstant) {
501         super(startInstant, endInstant, null);
502     }
503 
504     /**
505      * Creates a period from the given interval endpoints.
506      *
507      * @param startInstant  interval start, null means now
508      * @param endInstant  interval end, null means now
509      * @param type  which set of fields this period supports, null means standard
510      */
511     public Period(ReadableInstant startInstant, ReadableInstant endInstant, PeriodType type) {
512         super(startInstant, endInstant, type);
513     }
514 
515     /**
516      * Creates a period from two partially specified times.
517      * <p>
518      * The two partials must contain the same fields, thus you can specify
519      * two <code>LocalDate</code> objects, or two <code>LocalTime</code> objects,
520      * but not one of each.
521      * As these are Partial objects, time zones have no effect on the result.
522      * <p>
523      * The two partials must also both be contiguous - see
524      * {@link DateTimeUtils#isContiguous(ReadablePartial)} for a definition.
525      * Both <code>LocalDate</code> and <code>LocalTime</code> are contiguous.
526      * <p>
527      * An alternative way of constructing a Period from two Partials
528      * is {@link #fieldDifference(ReadablePartial, ReadablePartial)}.
529      * That method handles all kinds of partials.
530      *
531      * @param start  the start of the period, must not be null
532      * @param end  the end of the period, must not be null
533      * @throws IllegalArgumentException if the partials are null or invalid
534      * @since 1.1
535      */
536     public Period(ReadablePartial start, ReadablePartial end) {
537         super(start, end, null);
538     }
539 
540     /**
541      * Creates a period from two partially specified times.
542      * <p>
543      * The two partials must contain the same fields, thus you can specify
544      * two <code>LocalDate</code> objects, or two <code>LocalTime</code> objects,
545      * but not one of each.
546      * As these are Partial objects, time zones have no effect on the result.
547      * <p>
548      * The two partials must also both be contiguous - see
549      * {@link DateTimeUtils#isContiguous(ReadablePartial)} for a definition.
550      * Both <code>LocalDate</code> and <code>LocalTime</code> are contiguous.
551      * <p>
552      * An alternative way of constructing a Period from two Partials
553      * is {@link #fieldDifference(ReadablePartial, ReadablePartial)}.
554      * That method handles all kinds of partials.
555      *
556      * @param start  the start of the period, must not be null
557      * @param end  the end of the period, must not be null
558      * @param type  which set of fields this period supports, null means standard
559      * @throws IllegalArgumentException if the partials are null or invalid
560      * @since 1.1
561      */
562     public Period(ReadablePartial start, ReadablePartial end, PeriodType type) {
563         super(start, end, type);
564     }
565 
566     /**
567      * Creates a period from the given start point and the duration.
568      *
569      * @param startInstant  the interval start, null means now
570      * @param duration  the duration of the interval, null means zero-length
571      */
572     public Period(ReadableInstant startInstant, ReadableDuration duration) {
573         super(startInstant, duration, null);
574     }
575 
576     /**
577      * Creates a period from the given start point and the duration.
578      *
579      * @param startInstant  the interval start, null means now
580      * @param duration  the duration of the interval, null means zero-length
581      * @param type  which set of fields this period supports, null means standard
582      */
583     public Period(ReadableInstant startInstant, ReadableDuration duration, PeriodType type) {
584         super(startInstant, duration, type);
585     }
586 
587     /**
588      * Creates a period from the given duration and end point.
589      *
590      * @param duration  the duration of the interval, null means zero-length
591      * @param endInstant  the interval end, null means now
592      */
593     public Period(ReadableDuration duration, ReadableInstant endInstant) {
594         super(duration, endInstant, null);
595     }
596 
597     /**
598      * Creates a period from the given duration and end point.
599      *
600      * @param duration  the duration of the interval, null means zero-length
601      * @param endInstant  the interval end, null means now
602      * @param type  which set of fields this period supports, null means standard
603      */
604     public Period(ReadableDuration duration, ReadableInstant endInstant, PeriodType type) {
605         super(duration, endInstant, type);
606     }
607 
608     /**
609      * Creates a period by converting or copying from another object.
610      * <p>
611      * The recognised object types are defined in
612      * {@link org.joda.time.convert.ConverterManager ConverterManager} and
613      * include ReadablePeriod, ReadableInterval and String.
614      * The String formats are described by {@link ISOPeriodFormat#standard()}.
615      *
616      * @param period  period to convert
617      * @throws IllegalArgumentException if period is invalid
618      * @throws UnsupportedOperationException if an unsupported field's value is non-zero
619      */
620     public Period(Object period) {
621         super(period, null, null);
622     }
623 
624     /**
625      * Creates a period by converting or copying from another object.
626      * <p>
627      * The recognised object types are defined in
628      * {@link org.joda.time.convert.ConverterManager ConverterManager} and
629      * include ReadablePeriod, ReadableInterval and String.
630      * The String formats are described by {@link ISOPeriodFormat#standard()}.
631      *
632      * @param period  period to convert
633      * @param type  which set of fields this period supports, null means use converter
634      * @throws IllegalArgumentException if period is invalid
635      * @throws UnsupportedOperationException if an unsupported field's value is non-zero
636      */
637     public Period(Object period, PeriodType type) {
638         super(period, type, null);
639     }
640 
641     /**
642      * Creates a period by converting or copying from another object.
643      * <p>
644      * The recognised object types are defined in
645      * {@link org.joda.time.convert.ConverterManager ConverterManager} and
646      * include ReadablePeriod, ReadableInterval and String.
647      * The String formats are described by {@link ISOPeriodFormat#standard()}.
648      *
649      * @param period  period to convert
650      * @param chrono  the chronology to use, null means ISO in default zone
651      * @throws IllegalArgumentException if period is invalid
652      * @throws UnsupportedOperationException if an unsupported field's value is non-zero
653      */
654     public Period(Object period, Chronology chrono) {
655         super(period, null, chrono);
656     }
657 
658     /**
659      * Creates a period by converting or copying from another object.
660      * <p>
661      * The recognised object types are defined in
662      * {@link org.joda.time.convert.ConverterManager ConverterManager} and
663      * include ReadablePeriod, ReadableInterval and String.
664      * The String formats are described by {@link ISOPeriodFormat#standard()}.
665      *
666      * @param period  period to convert
667      * @param type  which set of fields this period supports, null means use converter
668      * @param chrono  the chronology to use, null means ISO in default zone
669      * @throws IllegalArgumentException if period is invalid
670      * @throws UnsupportedOperationException if an unsupported field's value is non-zero
671      */
672     public Period(Object period, PeriodType type, Chronology chrono) {
673         super(period, type, chrono);
674     }
675 
676     /**
677      * Constructor used when we trust ourselves.
678      *
679      * @param values  the values to use, not null, not cloned
680      * @param type  which set of fields this period supports, not null
681      */
682     private Period(int[] values, PeriodType type) {
683         super(values, type);
684     }
685 
686     //-----------------------------------------------------------------------
687     /**
688      * Get this period as an immutable <code>Period</code> object
689      * by returning <code>this</code>.
690      * 
691      * @return <code>this</code>
692      */
693     public Period toPeriod() {
694         return this;
695     }
696 
697     //-----------------------------------------------------------------------
698     /**
699      * Gets the years field part of the period.
700      * 
701      * @return the number of years in the period, zero if unsupported
702      */
703     public int getYears() {
704         return getPeriodType().getIndexedField(this, PeriodType.YEAR_INDEX);
705     }
706 
707     /**
708      * Gets the months field part of the period.
709      * 
710      * @return the number of months in the period, zero if unsupported
711      */
712     public int getMonths() {
713         return getPeriodType().getIndexedField(this, PeriodType.MONTH_INDEX);
714     }
715 
716     /**
717      * Gets the weeks field part of the period.
718      * 
719      * @return the number of weeks in the period, zero if unsupported
720      */
721     public int getWeeks() {
722         return getPeriodType().getIndexedField(this, PeriodType.WEEK_INDEX);
723     }
724 
725     /**
726      * Gets the days field part of the period.
727      * 
728      * @return the number of days in the period, zero if unsupported
729      */
730     public int getDays() {
731         return getPeriodType().getIndexedField(this, PeriodType.DAY_INDEX);
732     }
733 
734     //-----------------------------------------------------------------------
735     /**
736      * Gets the hours field part of the period.
737      * 
738      * @return the number of hours in the period, zero if unsupported
739      */
740     public int getHours() {
741         return getPeriodType().getIndexedField(this, PeriodType.HOUR_INDEX);
742     }
743 
744     /**
745      * Gets the minutes field part of the period.
746      * 
747      * @return the number of minutes in the period, zero if unsupported
748      */
749     public int getMinutes() {
750         return getPeriodType().getIndexedField(this, PeriodType.MINUTE_INDEX);
751     }
752 
753     /**
754      * Gets the seconds field part of the period.
755      * 
756      * @return the number of seconds in the period, zero if unsupported
757      */
758     public int getSeconds() {
759         return getPeriodType().getIndexedField(this, PeriodType.SECOND_INDEX);
760     }
761 
762     /**
763      * Gets the millis field part of the period.
764      * 
765      * @return the number of millis in the period, zero if unsupported
766      */
767     public int getMillis() {
768         return getPeriodType().getIndexedField(this, PeriodType.MILLI_INDEX);
769     }
770 
771     //-----------------------------------------------------------------------
772     /**
773      * Creates a new Period instance with the same field values but
774      * different PeriodType.
775      * <p>
776      * This period instance is immutable and unaffected by this method call.
777      * 
778      * @param type  the period type to use, null means standard
779      * @return the new period instance
780      * @throws IllegalArgumentException if the new period won't accept all of the current fields
781      */
782     public Period withPeriodType(PeriodType type) {
783         type = DateTimeUtils.getPeriodType(type);
784         if (type.equals(getPeriodType())) {
785             return this;
786         }
787         return new Period(this, type);
788     }
789 
790     /**
791      * Creates a new Period instance with the fields from the specified period
792      * copied on top of those from this period.
793      * <p>
794      * This period instance is immutable and unaffected by this method call.
795      * 
796      * @param period  the period to copy from, null ignored
797      * @return the new period instance
798      * @throws IllegalArgumentException if a field type is unsupported
799      */
800     public Period withFields(ReadablePeriod period) {
801         if (period == null) {
802             return this;
803         }
804         int[] newValues = getValues();  // cloned
805         newValues = super.mergePeriodInto(newValues, period);
806         return new Period(newValues, getPeriodType());
807     }
808 
809     //-----------------------------------------------------------------------
810     /**
811      * Creates a new Period instance with the specified field set to a new value.
812      * <p>
813      * This period instance is immutable and unaffected by this method call.
814      * 
815      * @param field  the field to set, not null
816      * @param value  the value to set to
817      * @return the new period instance
818      * @throws IllegalArgumentException if the field type is null or unsupported
819      */
820     public Period withField(DurationFieldType field, int value) {
821         if (field == null) {
822             throw new IllegalArgumentException("Field must not be null");
823         }
824         int[] newValues = getValues();  // cloned
825         super.setFieldInto(newValues, field, value);
826         return new Period(newValues, getPeriodType());
827     }
828 
829     /**
830      * Creates a new Period instance with the valueToAdd added to the specified field.
831      * <p>
832      * This period instance is immutable and unaffected by this method call.
833      * 
834      * @param field  the field to set, not null
835      * @param value  the value to add
836      * @return the new period instance
837      * @throws IllegalArgumentException if the field type is null or unsupported
838      */
839     public Period withFieldAdded(DurationFieldType field, int value) {
840         if (field == null) {
841             throw new IllegalArgumentException("Field must not be null");
842         }
843         if (value == 0) {
844             return this;
845         }
846         int[] newValues = getValues();  // cloned
847         super.addFieldInto(newValues, field, value);
848         return new Period(newValues, getPeriodType());
849     }
850 
851     //-----------------------------------------------------------------------
852     /**
853      * Returns a new period with the specified number of years.
854      * <p>
855      * This period instance is immutable and unaffected by this method call.
856      *
857      * @param years  the amount of years to add, may be negative
858      * @return the new period with the increased years
859      * @throws UnsupportedOperationException if the field is not supported
860      */
861     public Period withYears(int years) {
862         int[] values = getValues();  // cloned
863         getPeriodType().setIndexedField(this, PeriodType.YEAR_INDEX, values, years);
864         return new Period(values, getPeriodType());
865     }
866 
867     /**
868      * Returns a new period with the specified number of months.
869      * <p>
870      * This period instance is immutable and unaffected by this method call.
871      *
872      * @param months  the amount of months to add, may be negative
873      * @return the new period with the increased months
874      * @throws UnsupportedOperationException if the field is not supported
875      */
876     public Period withMonths(int months) {
877         int[] values = getValues();  // cloned
878         getPeriodType().setIndexedField(this, PeriodType.MONTH_INDEX, values, months);
879         return new Period(values, getPeriodType());
880     }
881 
882     /**
883      * Returns a new period with the specified number of weeks.
884      * <p>
885      * This period instance is immutable and unaffected by this method call.
886      *
887      * @param weeks  the amount of weeks to add, may be negative
888      * @return the new period with the increased weeks
889      * @throws UnsupportedOperationException if the field is not supported
890      */
891     public Period withWeeks(int weeks) {
892         int[] values = getValues();  // cloned
893         getPeriodType().setIndexedField(this, PeriodType.WEEK_INDEX, values, weeks);
894         return new Period(values, getPeriodType());
895     }
896 
897     /**
898      * Returns a new period with the specified number of days.
899      * <p>
900      * This period instance is immutable and unaffected by this method call.
901      *
902      * @param days  the amount of days to add, may be negative
903      * @return the new period with the increased days
904      * @throws UnsupportedOperationException if the field is not supported
905      */
906     public Period withDays(int days) {
907         int[] values = getValues();  // cloned
908         getPeriodType().setIndexedField(this, PeriodType.DAY_INDEX, values, days);
909         return new Period(values, getPeriodType());
910     }
911 
912     /**
913      * Returns a new period with the specified number of hours.
914      * <p>
915      * This period instance is immutable and unaffected by this method call.
916      *
917      * @param hours  the amount of hours to add, may be negative
918      * @return the new period with the increased hours
919      * @throws UnsupportedOperationException if the field is not supported
920      */
921     public Period withHours(int hours) {
922         int[] values = getValues();  // cloned
923         getPeriodType().setIndexedField(this, PeriodType.HOUR_INDEX, values, hours);
924         return new Period(values, getPeriodType());
925     }
926 
927     /**
928      * Returns a new period with the specified number of minutes.
929      * <p>
930      * This period instance is immutable and unaffected by this method call.
931      *
932      * @param minutes  the amount of minutes to add, may be negative
933      * @return the new period with the increased minutes
934      * @throws UnsupportedOperationException if the field is not supported
935      */
936     public Period withMinutes(int minutes) {
937         int[] values = getValues();  // cloned
938         getPeriodType().setIndexedField(this, PeriodType.MINUTE_INDEX, values, minutes);
939         return new Period(values, getPeriodType());
940     }
941 
942     /**
943      * Returns a new period with the specified number of seconds.
944      * <p>
945      * This period instance is immutable and unaffected by this method call.
946      *
947      * @param seconds  the amount of seconds to add, may be negative
948      * @return the new period with the increased seconds
949      * @throws UnsupportedOperationException if the field is not supported
950      */
951     public Period withSeconds(int seconds) {
952         int[] values = getValues();  // cloned
953         getPeriodType().setIndexedField(this, PeriodType.SECOND_INDEX, values, seconds);
954         return new Period(values, getPeriodType());
955     }
956 
957     /**
958      * Returns a new period with the specified number of millis.
959      * <p>
960      * This period instance is immutable and unaffected by this method call.
961      *
962      * @param millis  the amount of millis to add, may be negative
963      * @return the new period with the increased millis
964      * @throws UnsupportedOperationException if the field is not supported
965      */
966     public Period withMillis(int millis) {
967         int[] values = getValues();  // cloned
968         getPeriodType().setIndexedField(this, PeriodType.MILLI_INDEX, values, millis);
969         return new Period(values, getPeriodType());
970     }
971 
972     //-----------------------------------------------------------------------
973     /**
974      * Returns a new period with the specified period added.
975      * <p>
976      * Each field of the period is added separately. Thus a period of
977      * 2 hours 30 minutes plus 3 hours 40 minutes will produce a result
978      * of 5 hours 70 minutes - see {@link #normalizedStandard()}.
979      * <p>
980      * If the period being added contains a non-zero amount for a field that
981      * is not supported in this period then an exception is thrown.
982      * <p>
983      * This period instance is immutable and unaffected by this method call.
984      *
985      * @param period  the period to add, null adds zero and returns this
986      * @return the new updated period
987      * @throws UnsupportedOperationException if any field is not supported
988      * @since 1.5
989      */
990     public Period plus(ReadablePeriod period) {
991         if (period == null) {
992             return this;
993         }
994         int[] values = getValues();  // cloned
995         getPeriodType().addIndexedField(this, PeriodType.YEAR_INDEX, values, period.get(DurationFieldType.YEARS_TYPE));
996         getPeriodType().addIndexedField(this, PeriodType.MONTH_INDEX, values, period.get(DurationFieldType.MONTHS_TYPE));
997         getPeriodType().addIndexedField(this, PeriodType.WEEK_INDEX, values, period.get(DurationFieldType.WEEKS_TYPE));
998         getPeriodType().addIndexedField(this, PeriodType.DAY_INDEX, values, period.get(DurationFieldType.DAYS_TYPE));
999         getPeriodType().addIndexedField(this, PeriodType.HOUR_INDEX, values, period.get(DurationFieldType.HOURS_TYPE));
1000         getPeriodType().addIndexedField(this, PeriodType.MINUTE_INDEX, values, period.get(DurationFieldType.MINUTES_TYPE));
1001         getPeriodType().addIndexedField(this, PeriodType.SECOND_INDEX, values, period.get(DurationFieldType.SECONDS_TYPE));
1002         getPeriodType().addIndexedField(this, PeriodType.MILLI_INDEX, values, period.get(DurationFieldType.MILLIS_TYPE));
1003         return new Period(values, getPeriodType());
1004     }
1005 
1006     //-----------------------------------------------------------------------
1007     /**
1008      * Returns a new period with the specified number of years added.
1009      * <p>
1010      * This period instance is immutable and unaffected by this method call.
1011      *
1012      * @param years  the amount of years to add, may be negative
1013      * @return the new period with the increased years
1014      * @throws UnsupportedOperationException if the field is not supported
1015      */
1016     public Period plusYears(int years) {
1017         if (years == 0) {
1018             return this;
1019         }
1020         int[] values = getValues();  // cloned
1021         getPeriodType().addIndexedField(this, PeriodType.YEAR_INDEX, values, years);
1022         return new Period(values, getPeriodType());
1023     }
1024 
1025     /**
1026      * Returns a new period plus the specified number of months added.
1027      * <p>
1028      * This period instance is immutable and unaffected by this method call.
1029      *
1030      * @param months  the amount of months to add, may be negative
1031      * @return the new period plus the increased months
1032      * @throws UnsupportedOperationException if the field is not supported
1033      */
1034     public Period plusMonths(int months) {
1035         if (months == 0) {
1036             return this;
1037         }
1038         int[] values = getValues();  // cloned
1039         getPeriodType().addIndexedField(this, PeriodType.MONTH_INDEX, values, months);
1040         return new Period(values, getPeriodType());
1041     }
1042 
1043     /**
1044      * Returns a new period plus the specified number of weeks added.
1045      * <p>
1046      * This period instance is immutable and unaffected by this method call.
1047      *
1048      * @param weeks  the amount of weeks to add, may be negative
1049      * @return the new period plus the increased weeks
1050      * @throws UnsupportedOperationException if the field is not supported
1051      */
1052     public Period plusWeeks(int weeks) {
1053         if (weeks == 0) {
1054             return this;
1055         }
1056         int[] values = getValues();  // cloned
1057         getPeriodType().addIndexedField(this, PeriodType.WEEK_INDEX, values, weeks);
1058         return new Period(values, getPeriodType());
1059     }
1060 
1061     /**
1062      * Returns a new period plus the specified number of days added.
1063      * <p>
1064      * This period instance is immutable and unaffected by this method call.
1065      *
1066      * @param days  the amount of days to add, may be negative
1067      * @return the new period plus the increased days
1068      * @throws UnsupportedOperationException if the field is not supported
1069      */
1070     public Period plusDays(int days) {
1071         if (days == 0) {
1072             return this;
1073         }
1074         int[] values = getValues();  // cloned
1075         getPeriodType().addIndexedField(this, PeriodType.DAY_INDEX, values, days);
1076         return new Period(values, getPeriodType());
1077     }
1078 
1079     /**
1080      * Returns a new period plus the specified number of hours added.
1081      * <p>
1082      * This period instance is immutable and unaffected by this method call.
1083      *
1084      * @param hours  the amount of hours to add, may be negative
1085      * @return the new period plus the increased hours
1086      * @throws UnsupportedOperationException if the field is not supported
1087      */
1088     public Period plusHours(int hours) {
1089         if (hours == 0) {
1090             return this;
1091         }
1092         int[] values = getValues();  // cloned
1093         getPeriodType().addIndexedField(this, PeriodType.HOUR_INDEX, values, hours);
1094         return new Period(values, getPeriodType());
1095     }
1096 
1097     /**
1098      * Returns a new period plus the specified number of minutes added.
1099      * <p>
1100      * This period instance is immutable and unaffected by this method call.
1101      *
1102      * @param minutes  the amount of minutes to add, may be negative
1103      * @return the new period plus the increased minutes
1104      * @throws UnsupportedOperationException if the field is not supported
1105      */
1106     public Period plusMinutes(int minutes) {
1107         if (minutes == 0) {
1108             return this;
1109         }
1110         int[] values = getValues();  // cloned
1111         getPeriodType().addIndexedField(this, PeriodType.MINUTE_INDEX, values, minutes);
1112         return new Period(values, getPeriodType());
1113     }
1114 
1115     /**
1116      * Returns a new period plus the specified number of seconds added.
1117      * <p>
1118      * This period instance is immutable and unaffected by this method call.
1119      *
1120      * @param seconds  the amount of seconds to add, may be negative
1121      * @return the new period plus the increased seconds
1122      * @throws UnsupportedOperationException if the field is not supported
1123      */
1124     public Period plusSeconds(int seconds) {
1125         if (seconds == 0) {
1126             return this;
1127         }
1128         int[] values = getValues();  // cloned
1129         getPeriodType().addIndexedField(this, PeriodType.SECOND_INDEX, values, seconds);
1130         return new Period(values, getPeriodType());
1131     }
1132 
1133     /**
1134      * Returns a new period plus the specified number of millis added.
1135      * <p>
1136      * This period instance is immutable and unaffected by this method call.
1137      *
1138      * @param millis  the amount of millis to add, may be negative
1139      * @return the new period plus the increased millis
1140      * @throws UnsupportedOperationException if the field is not supported
1141      */
1142     public Period plusMillis(int millis) {
1143         if (millis == 0) {
1144             return this;
1145         }
1146         int[] values = getValues();  // cloned
1147         getPeriodType().addIndexedField(this, PeriodType.MILLI_INDEX, values, millis);
1148         return new Period(values, getPeriodType());
1149     }
1150 
1151     //-----------------------------------------------------------------------
1152     /**
1153      * Returns a new period with the specified period subtracted.
1154      * <p>
1155      * Each field of the period is subtracted separately. Thus a period of
1156      * 3 hours 30 minutes minus 2 hours 40 minutes will produce a result
1157      * of 1 hour and -10 minutes - see {@link #normalizedStandard()}.
1158      * <p>
1159      * If the period being added contains a non-zero amount for a field that
1160      * is not supported in this period then an exception is thrown.
1161      * <p>
1162      * This period instance is immutable and unaffected by this method call.
1163      *
1164      * @param period  the period to add, null adds zero and returns this
1165      * @return the new updated period
1166      * @throws UnsupportedOperationException if any field is not supported
1167      * @since 1.5
1168      */
1169     public Period minus(ReadablePeriod period) {
1170         if (period == null) {
1171             return this;
1172         }
1173         int[] values = getValues();  // cloned
1174         getPeriodType().addIndexedField(this, PeriodType.YEAR_INDEX, values, -period.get(DurationFieldType.YEARS_TYPE));
1175         getPeriodType().addIndexedField(this, PeriodType.MONTH_INDEX, values, -period.get(DurationFieldType.MONTHS_TYPE));
1176         getPeriodType().addIndexedField(this, PeriodType.WEEK_INDEX, values, -period.get(DurationFieldType.WEEKS_TYPE));
1177         getPeriodType().addIndexedField(this, PeriodType.DAY_INDEX, values, -period.get(DurationFieldType.DAYS_TYPE));
1178         getPeriodType().addIndexedField(this, PeriodType.HOUR_INDEX, values, -period.get(DurationFieldType.HOURS_TYPE));
1179         getPeriodType().addIndexedField(this, PeriodType.MINUTE_INDEX, values, -period.get(DurationFieldType.MINUTES_TYPE));
1180         getPeriodType().addIndexedField(this, PeriodType.SECOND_INDEX, values, -period.get(DurationFieldType.SECONDS_TYPE));
1181         getPeriodType().addIndexedField(this, PeriodType.MILLI_INDEX, values, -period.get(DurationFieldType.MILLIS_TYPE));
1182         return new Period(values, getPeriodType());
1183     }
1184 
1185     //-----------------------------------------------------------------------
1186     /**
1187      * Returns a new period with the specified number of years taken away.
1188      * <p>
1189      * This period instance is immutable and unaffected by this method call.
1190      *
1191      * @param years  the amount of years to take away, may be negative
1192      * @return the new period with the increased years
1193      * @throws UnsupportedOperationException if the field is not supported
1194      */
1195     public Period minusYears(int years) {
1196         return plusYears(-years);
1197     }
1198 
1199     /**
1200      * Returns a new period minus the specified number of months taken away.
1201      * <p>
1202      * This period instance is immutable and unaffected by this method call.
1203      *
1204      * @param months  the amount of months to take away, may be negative
1205      * @return the new period minus the increased months
1206      * @throws UnsupportedOperationException if the field is not supported
1207      */
1208     public Period minusMonths(int months) {
1209         return plusMonths(-months);
1210     }
1211 
1212     /**
1213      * Returns a new period minus the specified number of weeks taken away.
1214      * <p>
1215      * This period instance is immutable and unaffected by this method call.
1216      *
1217      * @param weeks  the amount of weeks to take away, may be negative
1218      * @return the new period minus the increased weeks
1219      * @throws UnsupportedOperationException if the field is not supported
1220      */
1221     public Period minusWeeks(int weeks) {
1222         return plusWeeks(-weeks);
1223     }
1224 
1225     /**
1226      * Returns a new period minus the specified number of days taken away.
1227      * <p>
1228      * This period instance is immutable and unaffected by this method call.
1229      *
1230      * @param days  the amount of days to take away, may be negative
1231      * @return the new period minus the increased days
1232      * @throws UnsupportedOperationException if the field is not supported
1233      */
1234     public Period minusDays(int days) {
1235         return plusDays(-days);
1236     }
1237 
1238     /**
1239      * Returns a new period minus the specified number of hours taken away.
1240      * <p>
1241      * This period instance is immutable and unaffected by this method call.
1242      *
1243      * @param hours  the amount of hours to take away, may be negative
1244      * @return the new period minus the increased hours
1245      * @throws UnsupportedOperationException if the field is not supported
1246      */
1247     public Period minusHours(int hours) {
1248         return plusHours(-hours);
1249     }
1250 
1251     /**
1252      * Returns a new period minus the specified number of minutes taken away.
1253      * <p>
1254      * This period instance is immutable and unaffected by this method call.
1255      *
1256      * @param minutes  the amount of minutes to take away, may be negative
1257      * @return the new period minus the increased minutes
1258      * @throws UnsupportedOperationException if the field is not supported
1259      */
1260     public Period minusMinutes(int minutes) {
1261         return plusMinutes(-minutes);
1262     }
1263 
1264     /**
1265      * Returns a new period minus the specified number of seconds taken away.
1266      * <p>
1267      * This period instance is immutable and unaffected by this method call.
1268      *
1269      * @param seconds  the amount of seconds to take away, may be negative
1270      * @return the new period minus the increased seconds
1271      * @throws UnsupportedOperationException if the field is not supported
1272      */
1273     public Period minusSeconds(int seconds) {
1274         return plusSeconds(-seconds);
1275     }
1276 
1277     /**
1278      * Returns a new period minus the specified number of millis taken away.
1279      * <p>
1280      * This period instance is immutable and unaffected by this method call.
1281      *
1282      * @param millis  the amount of millis to take away, may be negative
1283      * @return the new period minus the increased millis
1284      * @throws UnsupportedOperationException if the field is not supported
1285      */
1286     public Period minusMillis(int millis) {
1287         return plusMillis(-millis);
1288     }
1289 
1290     //-----------------------------------------------------------------------
1291     /**
1292      * Returns a new instance with each element in this period multiplied
1293      * by the specified scalar.
1294      *
1295      * @param scalar  the scalar to multiply by, not null
1296      * @return a {@code Period} based on this period with the amounts multiplied by the scalar, never null
1297      * @throws ArithmeticException if the capacity of any field is exceeded
1298      * @since 2.1
1299      */
1300     public Period multipliedBy(int scalar) {
1301         if (this == ZERO || scalar == 1) {
1302             return this;
1303         }
1304         int[] values = getValues();  // cloned
1305         for (int i = 0; i < values.length; i++) {
1306             values[i] = FieldUtils.safeMultiply(values[i], scalar);
1307         }
1308         return new Period(values, getPeriodType());
1309     }
1310 
1311     /**
1312      * Returns a new instance with each amount in this period negated.
1313      *
1314      * @return a {@code Period} based on this period with the amounts negated, never null
1315      * @throws ArithmeticException if any field has the minimum value
1316      * @since 2.1
1317      */
1318     public Period negated() {
1319         return multipliedBy(-1);
1320     }
1321 
1322     //-----------------------------------------------------------------------
1323     /**
1324      * Converts this period to a period in weeks assuming a
1325      * 7 day week, 24 hour day, 60 minute hour and 60 second minute.
1326      * <p>
1327      * This method allows you to convert between different types of period.
1328      * However to achieve this it makes the assumption that all
1329      * weeks are 7 days, all days are 24 hours, all hours are 60 minutes and
1330      * all minutes are 60 seconds. This is not true when daylight savings time
1331      * is considered, and may also not be true for some unusual chronologies.
1332      * However, it is included as it is a useful operation for many
1333      * applications and business rules.
1334      * <p>
1335      * If the period contains years or months, an exception will be thrown.
1336      * 
1337      * @return a period representing the number of standard weeks in this period
1338      * @throws UnsupportedOperationException if the period contains years or months
1339      * @throws ArithmeticException if the number of weeks is too large to be represented
1340      * @since 1.5
1341      */
1342     public Weeks toStandardWeeks() {
1343         checkYearsAndMonths("Weeks");
1344         long millis = getMillis();  // assign to a long
1345         millis += ((long) getSeconds()) * DateTimeConstants.MILLIS_PER_SECOND;
1346         millis += ((long) getMinutes()) * DateTimeConstants.MILLIS_PER_MINUTE;
1347         millis += ((long) getHours()) * DateTimeConstants.MILLIS_PER_HOUR;
1348         millis += ((long) getDays()) * DateTimeConstants.MILLIS_PER_DAY;
1349         long weeks = ((long) getWeeks()) + millis / DateTimeConstants.MILLIS_PER_WEEK;
1350         return Weeks.weeks(FieldUtils.safeToInt(weeks));
1351     }
1352 
1353     /**
1354      * Converts this period to a period in days assuming a
1355      * 7 day week, 24 hour day, 60 minute hour and 60 second minute.
1356      * <p>
1357      * This method allows you to convert between different types of period.
1358      * However to achieve this it makes the assumption that all
1359      * weeks are 7 days, all days are 24 hours, all hours are 60 minutes and
1360      * all minutes are 60 seconds. This is not true when daylight savings time
1361      * is considered, and may also not be true for some unusual chronologies.
1362      * However, it is included as it is a useful operation for many
1363      * applications and business rules.
1364      * <p>
1365      * If the period contains years or months, an exception will be thrown.
1366      * 
1367      * @return a period representing the number of standard days in this period
1368      * @throws UnsupportedOperationException if the period contains years or months
1369      * @throws ArithmeticException if the number of days is too large to be represented
1370      * @since 1.5
1371      */
1372     public Days toStandardDays() {
1373         checkYearsAndMonths("Days");
1374         long millis = getMillis();  // assign to a long
1375         millis += ((long) getSeconds()) * DateTimeConstants.MILLIS_PER_SECOND;
1376         millis += ((long) getMinutes()) * DateTimeConstants.MILLIS_PER_MINUTE;
1377         millis += ((long) getHours()) * DateTimeConstants.MILLIS_PER_HOUR;
1378         long days = millis / DateTimeConstants.MILLIS_PER_DAY;
1379         days = FieldUtils.safeAdd(days, getDays());
1380         days = FieldUtils.safeAdd(days, ((long) getWeeks()) * ((long) DateTimeConstants.DAYS_PER_WEEK));
1381         return Days.days(FieldUtils.safeToInt(days));
1382     }
1383 
1384     /**
1385      * Converts this period to a period in hours assuming a
1386      * 7 day week, 24 hour day, 60 minute hour and 60 second minute.
1387      * <p>
1388      * This method allows you to convert between different types of period.
1389      * However to achieve this it makes the assumption that all
1390      * weeks are 7 days, all days are 24 hours, all hours are 60 minutes and
1391      * all minutes are 60 seconds. This is not true when daylight savings time
1392      * is considered, and may also not be true for some unusual chronologies.
1393      * However, it is included as it is a useful operation for many
1394      * applications and business rules.
1395      * <p>
1396      * If the period contains years or months, an exception will be thrown.
1397      * 
1398      * @return a period representing the number of standard hours in this period
1399      * @throws UnsupportedOperationException if the period contains years or months
1400      * @throws ArithmeticException if the number of hours is too large to be represented
1401      * @since 1.5
1402      */
1403     public Hours toStandardHours() {
1404         checkYearsAndMonths("Hours");
1405         long millis = getMillis();  // assign to a long
1406         millis += ((long) getSeconds()) * DateTimeConstants.MILLIS_PER_SECOND;
1407         millis += ((long) getMinutes()) * DateTimeConstants.MILLIS_PER_MINUTE;
1408         long hours = millis / DateTimeConstants.MILLIS_PER_HOUR;
1409         hours = FieldUtils.safeAdd(hours, getHours());
1410         hours = FieldUtils.safeAdd(hours, ((long) getDays()) * ((long) DateTimeConstants.HOURS_PER_DAY));
1411         hours = FieldUtils.safeAdd(hours, ((long) getWeeks()) * ((long) DateTimeConstants.HOURS_PER_WEEK));
1412         return Hours.hours(FieldUtils.safeToInt(hours));
1413     }
1414 
1415     /**
1416      * Converts this period to a period in minutes assuming a
1417      * 7 day week, 24 hour day, 60 minute hour and 60 second minute.
1418      * <p>
1419      * This method allows you to convert between different types of period.
1420      * However to achieve this it makes the assumption that all
1421      * weeks are 7 days, all days are 24 hours, all hours are 60 minutes and
1422      * all minutes are 60 seconds. This is not true when daylight savings time
1423      * is considered, and may also not be true for some unusual chronologies.
1424      * However, it is included as it is a useful operation for many
1425      * applications and business rules.
1426      * <p>
1427      * If the period contains years or months, an exception will be thrown.
1428      * 
1429      * @return a period representing the number of standard minutes in this period
1430      * @throws UnsupportedOperationException if the period contains years or months
1431      * @throws ArithmeticException if the number of minutes is too large to be represented
1432      * @since 1.5
1433      */
1434     public Minutes toStandardMinutes() {
1435         checkYearsAndMonths("Minutes");
1436         long millis = getMillis();  // assign to a long
1437         millis += ((long) getSeconds()) * DateTimeConstants.MILLIS_PER_SECOND;
1438         long minutes = millis / DateTimeConstants.MILLIS_PER_MINUTE;
1439         minutes = FieldUtils.safeAdd(minutes, getMinutes());
1440         minutes = FieldUtils.safeAdd(minutes, ((long) getHours()) * ((long) DateTimeConstants.MINUTES_PER_HOUR));
1441         minutes = FieldUtils.safeAdd(minutes, ((long) getDays()) * ((long) DateTimeConstants.MINUTES_PER_DAY));
1442         minutes = FieldUtils.safeAdd(minutes, ((long) getWeeks()) * ((long) DateTimeConstants.MINUTES_PER_WEEK));
1443         return Minutes.minutes(FieldUtils.safeToInt(minutes));
1444     }
1445 
1446     /**
1447      * Converts this period to a period in seconds assuming a
1448      * 7 day week, 24 hour day, 60 minute hour and 60 second minute.
1449      * <p>
1450      * This method allows you to convert between different types of period.
1451      * However to achieve this it makes the assumption that all
1452      * weeks are 7 days, all days are 24 hours, all hours are 60 minutes and
1453      * all minutes are 60 seconds. This is not true when daylight savings time
1454      * is considered, and may also not be true for some unusual chronologies.
1455      * However, it is included as it is a useful operation for many
1456      * applications and business rules.
1457      * <p>
1458      * If the period contains years or months, an exception will be thrown.
1459      * 
1460      * @return a period representing the number of standard seconds in this period
1461      * @throws UnsupportedOperationException if the period contains years or months
1462      * @throws ArithmeticException if the number of seconds is too large to be represented
1463      * @since 1.5
1464      */
1465     public Seconds toStandardSeconds() {
1466         checkYearsAndMonths("Seconds");
1467         long seconds = getMillis() / DateTimeConstants.MILLIS_PER_SECOND;
1468         seconds = FieldUtils.safeAdd(seconds, getSeconds());
1469         seconds = FieldUtils.safeAdd(seconds, ((long) getMinutes()) * ((long) DateTimeConstants.SECONDS_PER_MINUTE));
1470         seconds = FieldUtils.safeAdd(seconds, ((long) getHours()) * ((long) DateTimeConstants.SECONDS_PER_HOUR));
1471         seconds = FieldUtils.safeAdd(seconds, ((long) getDays()) * ((long) DateTimeConstants.SECONDS_PER_DAY));
1472         seconds = FieldUtils.safeAdd(seconds, ((long) getWeeks()) * ((long) DateTimeConstants.SECONDS_PER_WEEK));
1473         return Seconds.seconds(FieldUtils.safeToInt(seconds));
1474     }
1475 
1476     //-----------------------------------------------------------------------
1477     /**
1478      * Converts this period to a duration assuming a
1479      * 7 day week, 24 hour day, 60 minute hour and 60 second minute.
1480      * <p>
1481      * This method allows you to convert from a period to a duration.
1482      * However to achieve this it makes the assumption that all
1483      * weeks are 7 days, all days are 24 hours, all hours are 60 minutes and
1484      * all minutes are 60 seconds. This is not true when daylight savings time
1485      * is considered, and may also not be true for some unusual chronologies.
1486      * However, it is included as it is a useful operation for many
1487      * applications and business rules.
1488      * <p>
1489      * If the period contains years or months, an exception will be thrown.
1490      * 
1491      * @return a duration equivalent to this period
1492      * @throws UnsupportedOperationException if the period contains years or months
1493      * @since 1.5
1494      */
1495     public Duration toStandardDuration() {
1496         checkYearsAndMonths("Duration");
1497         long millis = getMillis();  // no overflow can happen, even with Integer.MAX_VALUEs
1498         millis += (((long) getSeconds()) * ((long) DateTimeConstants.MILLIS_PER_SECOND));
1499         millis += (((long) getMinutes()) * ((long) DateTimeConstants.MILLIS_PER_MINUTE));
1500         millis += (((long) getHours()) * ((long) DateTimeConstants.MILLIS_PER_HOUR));
1501         millis += (((long) getDays()) * ((long) DateTimeConstants.MILLIS_PER_DAY));
1502         millis += (((long) getWeeks()) * ((long) DateTimeConstants.MILLIS_PER_WEEK));
1503         return new Duration(millis);
1504     }
1505 
1506     /**
1507      * Check that there are no years or months in the period.
1508      * 
1509      * @param destintionType  the destination type, not null
1510      * @throws UnsupportedOperationException if the period contains years or months
1511      */
1512     private void checkYearsAndMonths(String destintionType) {
1513         if (getMonths() != 0) {
1514             throw new UnsupportedOperationException("Cannot convert to " + destintionType + " as this period contains months and months vary in length");
1515         }
1516         if (getYears() != 0) {
1517             throw new UnsupportedOperationException("Cannot convert to " + destintionType + " as this period contains years and years vary in length");
1518         }
1519     }
1520 
1521     //-----------------------------------------------------------------------
1522     /**
1523      * Normalizes this period using standard rules, assuming a 12 month year,
1524      * 7 day week, 24 hour day, 60 minute hour and 60 second minute.
1525      * <p>
1526      * This method allows you to normalize a period.
1527      * However to achieve this it makes the assumption that all years are
1528      * 12 months, all weeks are 7 days, all days are 24 hours,
1529      * all hours are 60 minutes and all minutes are 60 seconds. This is not
1530      * true when daylight savings time is considered, and may also not be true
1531      * for some chronologies. However, it is included as it is a useful operation
1532      * for many applications and business rules.
1533      * <p>
1534      * If the period contains years or months, then the months will be
1535      * normalized to be between 0 and 11. The days field and below will be
1536      * normalized as necessary, however this will not overflow into the months
1537      * field. Thus a period of 1 year 15 months will normalize to 2 years 3 months.
1538      * But a period of 1 month 40 days will remain as 1 month 40 days.
1539      * <p>
1540      * The result will always have a <code>PeriodType</code> of standard, thus
1541      * days will be grouped into weeks.
1542      * 
1543      * @return a normalized period equivalent to this period
1544      * @throws ArithmeticException if any field is too large to be represented
1545      * @since 1.5
1546      */
1547     public Period normalizedStandard() {
1548         return normalizedStandard(PeriodType.standard());
1549     }
1550 
1551     //-----------------------------------------------------------------------
1552     /**
1553      * Normalizes this period using standard rules, assuming a 12 month year,
1554      * 7 day week, 24 hour day, 60 minute hour and 60 second minute,
1555      * providing control over how the result is split into fields.
1556      * <p>
1557      * This method allows you to normalize a period.
1558      * However to achieve this it makes the assumption that all years are
1559      * 12 months, all weeks are 7 days, all days are 24 hours,
1560      * all hours are 60 minutes and all minutes are 60 seconds. This is not
1561      * true when daylight savings time is considered, and may also not be true
1562      * for some chronologies. However, it is included as it is a useful operation
1563      * for many applications and business rules.
1564      * <p>
1565      * If the period contains years or months, then the months will be
1566      * normalized to be between 0 and 11. The days field and below will be
1567      * normalized as necessary, however this will not overflow into the months
1568      * field. Thus a period of 1 year 15 months will normalize to 2 years 3 months.
1569      * But a period of 1 month 40 days will remain as 1 month 40 days.
1570      * <p>
1571      * The PeriodType parameter controls how the result is created. It allows
1572      * you to omit certain fields from the result if desired. For example,
1573      * you may not want the result to include weeks, in which case you pass
1574      * in <code>PeriodType.yearMonthDayTime()</code>.
1575      * 
1576      * @param type  the period type of the new period, null means standard type
1577      * @return a normalized period equivalent to this period
1578      * @throws ArithmeticException if any field is too large to be represented
1579      * @throws UnsupportedOperationException if this period contains non-zero
1580      *  years or months but the specified period type does not support them
1581      * @since 1.5
1582      */
1583     public Period normalizedStandard(PeriodType type) {
1584         long millis = getMillis();  // no overflow can happen, even with Integer.MAX_VALUEs
1585         millis += (((long) getSeconds()) * ((long) DateTimeConstants.MILLIS_PER_SECOND));
1586         millis += (((long) getMinutes()) * ((long) DateTimeConstants.MILLIS_PER_MINUTE));
1587         millis += (((long) getHours()) * ((long) DateTimeConstants.MILLIS_PER_HOUR));
1588         millis += (((long) getDays()) * ((long) DateTimeConstants.MILLIS_PER_DAY));
1589         millis += (((long) getWeeks()) * ((long) DateTimeConstants.MILLIS_PER_WEEK));
1590         Period result = new Period(millis, DateTimeUtils.getPeriodType(type), ISOChronology.getInstanceUTC());
1591         int years = getYears();
1592         int months = getMonths();
1593         if (years != 0 || months != 0) {
1594             years = FieldUtils.safeAdd(years, months / 12);
1595             months = months % 12;
1596             if (years != 0) {
1597                 result = result.withYears(years);
1598             }
1599             if (months != 0) {
1600                 result = result.withMonths(months);
1601             }
1602         }
1603         return result;
1604     }
1605 
1606 }