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     */
016    package org.joda.time;
017    
018    import java.io.Serializable;
019    
020    import org.joda.convert.FromString;
021    import org.joda.time.base.BasePeriod;
022    import org.joda.time.chrono.ISOChronology;
023    import org.joda.time.field.FieldUtils;
024    import org.joda.time.format.ISOPeriodFormat;
025    import 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     */
057    public 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    }