001/*
002 *  Copyright 2001-2010 Stephen Colebourne
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.joda.time;
017
018import java.io.Serializable;
019
020import org.joda.convert.FromString;
021import org.joda.time.base.BasePeriod;
022import org.joda.time.chrono.ISOChronology;
023import org.joda.time.field.FieldUtils;
024import org.joda.time.format.ISOPeriodFormat;
025import org.joda.time.format.PeriodFormatter;
026
027/**
028 * An immutable time period specifying a set of duration field values.
029 * <p>
030 * A time period is divided into a number of fields, such as hours and seconds.
031 * Which fields are supported is defined by the PeriodType class.
032 * The default is the standard period type, which supports years, months, weeks, days,
033 * hours, minutes, seconds and millis.
034 * <p>
035 * When this time period is added to an instant, the effect is of adding each field in turn.
036 * As a result, this takes into account daylight savings time.
037 * Adding a time period of 1 day to the day before daylight savings starts will only add
038 * 23 hours rather than 24 to ensure that the time remains the same.
039 * If this is not the behaviour you want, then see {@link Duration}.
040 * <p>
041 * The definition of a period also affects the equals method. A period of 1
042 * day is not equal to a period of 24 hours, nor 1 hour equal to 60 minutes.
043 * This is because periods represent an abstracted definition of a time period
044 * (eg. a day may not actually be 24 hours, it might be 23 or 25 at daylight
045 * savings boundary). To compare the actual duration of two periods, convert
046 * both to durations using toDuration, an operation that emphasises that the
047 * result may differ according to the date you choose.
048 * <p>
049 * Period is thread-safe and immutable, provided that the PeriodType is as well.
050 * All standard PeriodType classes supplied are thread-safe and immutable.
051 *
052 * @author Brian S O'Neill
053 * @author Stephen Colebourne
054 * @since 1.0
055 * @see MutablePeriod
056 */
057public final class Period
058        extends BasePeriod
059        implements ReadablePeriod, Serializable {
060
061    /**
062     * A period of zero length and standard period type.
063     * @since 1.4
064     */
065    public static final Period ZERO = new Period();
066
067    /** Serialization version */
068    private static final long serialVersionUID = 741052353876488155L;
069
070    //-----------------------------------------------------------------------
071    /**
072     * Parses a {@code Period} from the specified string.
073     * <p>
074     * This uses {@link ISOPeriodFormat#standard()}.
075     * 
076     * @param str  the string to parse, not null
077     * @since 2.0
078     */
079    @FromString
080    public static Period parse(String str) {
081        return parse(str, ISOPeriodFormat.standard());
082    }
083
084    /**
085     * Parses a {@code Period} from the specified string using a formatter.
086     * 
087     * @param str  the string to parse, not null
088     * @param formatter  the formatter to use, not null
089     * @since 2.0
090     */
091    public static Period parse(String str, PeriodFormatter formatter) {
092        return formatter.parsePeriod(str);
093    }
094
095    //-----------------------------------------------------------------------
096    /**
097     * Create a period with a specified number of years.
098     * <p>
099     * 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}