1/*2 * Copyright 2001-2010 Stephen Colebourne3 *4 * Licensed under the Apache License, Version 2.0 (the "License");5 * you may not use this file except in compliance with the License.6 * You may obtain a copy of the License at7 *8 * http://www.apache.org/licenses/LICENSE-2.09 *10 * Unless required by applicable law or agreed to in writing, software11 * distributed under the License is distributed on an "AS IS" BASIS,12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13 * See the License for the specific language governing permissions and14 * limitations under the License.15 */16package org.joda.time;
1718import java.io.Serializable;
1920import org.joda.convert.FromString;
21import org.joda.time.base.BasePeriod;
22import org.joda.time.chrono.ISOChronology;
23import org.joda.time.field.FieldUtils;
24import org.joda.time.format.ISOPeriodFormat;
25import org.joda.time.format.PeriodFormatter;
2627/**28 * An immutable time period specifying a set of duration field values.29 * <p>30 * A time period is divided into a number of fields, such as hours and seconds.31 * Which fields are supported is defined by the PeriodType class.32 * The default is the standard period type, which supports years, months, weeks, days,33 * hours, minutes, seconds and millis.34 * <p>35 * When this time period is added to an instant, the effect is of adding each field in turn.36 * As a result, this takes into account daylight savings time.37 * Adding a time period of 1 day to the day before daylight savings starts will only add38 * 23 hours rather than 24 to ensure that the time remains the same.39 * If this is not the behaviour you want, then see {@link Duration}.40 * <p>41 * The definition of a period also affects the equals method. A period of 142 * day is not equal to a period of 24 hours, nor 1 hour equal to 60 minutes.43 * This is because periods represent an abstracted definition of a time period44 * (eg. a day may not actually be 24 hours, it might be 23 or 25 at daylight45 * savings boundary). To compare the actual duration of two periods, convert46 * both to durations using toDuration, an operation that emphasises that the47 * result may differ according to the date you choose.48 * <p>49 * Period is thread-safe and immutable, provided that the PeriodType is as well.50 * All standard PeriodType classes supplied are thread-safe and immutable.51 *52 * @author Brian S O'Neill53 * @author Stephen Colebourne54 * @since 1.055 * @see MutablePeriod56 */57publicfinalclassPeriod58extendsBasePeriod59implements ReadablePeriod, Serializable {
6061/**62 * A period of zero length and standard period type.63 * @since 1.464 */65publicstaticfinalPeriod ZERO = newPeriod();
6667/** Serialization version */68privatestaticfinallong serialVersionUID = 741052353876488155L;
6970//-----------------------------------------------------------------------71/**72 * Parses a {@code Period} from the specified string.73 * <p>74 * This uses {@link ISOPeriodFormat#standard()}.75 * 76 * @param str the string to parse, not null77 * @since 2.078 */79 @FromString
80publicstaticPeriod parse(String str) {
81return parse(str, ISOPeriodFormat.standard());
82 }
8384/**85 * Parses a {@code Period} from the specified string using a formatter.86 * 87 * @param str the string to parse, not null88 * @param formatter the formatter to use, not null89 * @since 2.090 */91publicstaticPeriod parse(String str, PeriodFormatter formatter) {
92return formatter.parsePeriod(str);
93 }
9495//-----------------------------------------------------------------------96/**97 * Create a period with a specified number of years.98 * <p>99 * The standard period type is used, thus you can add other fields such100 * 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 period107 * @return the period108 */109publicstaticPeriod years(int years) {
110returnnewPeriod(newint[] {years, 0, 0, 0, 0, 0, 0, 0, 0}, PeriodType.standard());
111 }
112113/**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 such117 * 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 period124 * @return the period125 */126publicstaticPeriod months(int months) {
127returnnewPeriod(newint[] {0, months, 0, 0, 0, 0, 0, 0}, PeriodType.standard());
128 }
129130/**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 such134 * 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 period141 * @return the period142 */143publicstaticPeriod weeks(int weeks) {
144returnnewPeriod(newint[] {0, 0, weeks, 0, 0, 0, 0, 0}, PeriodType.standard());
145 }
146147/**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 such151 * 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 period158 * @return the period159 */160publicstaticPeriod days(int days) {
161returnnewPeriod(newint[] {0, 0, 0, days, 0, 0, 0, 0}, PeriodType.standard());
162 }
163164/**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 such168 * 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 period175 * @return the period176 */177publicstaticPeriod hours(int hours) {
178returnnewPeriod(newint[] {0, 0, 0, 0, hours, 0, 0, 0}, PeriodType.standard());
179 }
180181/**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 such185 * 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 period192 * @return the period193 */194publicstaticPeriod minutes(int minutes) {
195returnnewPeriod(newint[] {0, 0, 0, 0, 0, minutes, 0, 0}, PeriodType.standard());
196 }
197198/**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 such202 * 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 period209 * @return the period210 */211publicstaticPeriod seconds(int seconds) {
212returnnewPeriod(newint[] {0, 0, 0, 0, 0, 0, seconds, 0}, PeriodType.standard());
213 }
214215/**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 such219 * 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 period223 * @return the period224 */225publicstaticPeriod millis(int millis) {
226returnnewPeriod(newint[] {0, 0, 0, 0, 0, 0, 0, millis}, PeriodType.standard());
227 }
228229//-----------------------------------------------------------------------230/**231 * Creates a period from two partially specified times, calculating232 * by field difference.233 * <p>234 * The two partials must contain the same fields, thus you can specify235 * two <code>LocalDate</code> objects, or two <code>LocalTime</code> objects,236 * but not one of each. Also, the partial may not contain overlapping237 * fields, such as dayOfWeek and dayOfMonth.238 * <p>239 * Calculation by field difference works by extracting the difference240 * 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 of244 * each month to the 2nd of the next month. If you calculate this245 * period using a standard constructor, then you will get between246 * P3D and P6D depending on the month. If you use this method, then247 * you will get P1M-25D. This field-difference based period can248 * be successfully applied to each month of the year to obtain the249 * correct end date for a given start date.250 *251 * @param start the start of the period, must not be null252 * @param end the end of the period, must not be null253 * @throws IllegalArgumentException if the partials are null or invalid254 * @since 1.1255 */256publicstaticPeriod fieldDifference(ReadablePartial start, ReadablePartial end) {
257if (start == null || end == null) {
258thrownew IllegalArgumentException("ReadablePartial objects must not be null");
259 }
260if (start.size() != end.size()) {
261thrownew IllegalArgumentException("ReadablePartial objects must have the same set of fields");
262 }
263DurationFieldType[] types = newDurationFieldType[start.size()];
264int[] values = newint[start.size()];
265for (int i = 0, isize = start.size(); i < isize; i++) {
266if (start.getFieldType(i) != end.getFieldType(i)) {
267thrownew IllegalArgumentException("ReadablePartial objects must have the same set of fields");
268 }
269 types[i] = start.getFieldType(i).getDurationType();
270if (i > 0 && types[i - 1] == types[i]) {
271thrownew IllegalArgumentException("ReadablePartial objects must not have overlapping fields");
272 }
273 values[i] = end.getValue(i) - start.getValue(i);
274 }
275returnnewPeriod(values, PeriodType.forFields(types));
276 }
277278//-----------------------------------------------------------------------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 of287 * 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 */297publicPeriod() {
298super(0L, null, null);
299 }
300301/**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 period307 * @param minutes amount of minutes in this period308 * @param seconds amount of seconds in this period309 * @param millis amount of milliseconds in this period310 */311publicPeriod(int hours, int minutes, int seconds, int millis) {
312super(0, 0, 0, 0, hours, minutes, seconds, millis, PeriodType.standard());
313 }
314315/**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 period319 * @param months amount of months in this period320 * @param weeks amount of weeks in this period321 * @param days amount of days in this period322 * @param hours amount of hours in this period323 * @param minutes amount of minutes in this period324 * @param seconds amount of seconds in this period325 * @param millis amount of milliseconds in this period326 */327publicPeriod(int years, int months, int weeks, int days,
328int hours, int minutes, int seconds, int millis) {
329super(years, months, weeks, days, hours, minutes, seconds, millis, PeriodType.standard());
330 }
331332/**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 unsupported340 * @param months amount of months in this period, which must be zero if unsupported341 * @param weeks amount of weeks in this period, which must be zero if unsupported342 * @param days amount of days in this period, which must be zero if unsupported343 * @param hours amount of hours in this period, which must be zero if unsupported344 * @param minutes amount of minutes in this period, which must be zero if unsupported345 * @param seconds amount of seconds in this period, which must be zero if unsupported346 * @param millis amount of milliseconds in this period, which must be zero if unsupported347 * @param type which set of fields this period supports, null means AllType348 * @throws IllegalArgumentException if an unsupported field's value is non-zero349 */350publicPeriod(int years, int months, int weeks, int days,
351int hours, int minutes, int seconds, int millis, PeriodType type) {
352super(years, months, weeks, days, hours, minutes, seconds, millis, type);
353 }
354355/**356 * Creates a period from the given millisecond duration using the standard357 * 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 perform364 * 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 will367 * 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 to370 * ((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 period375 * <li>specify a period type that contains precise definitions of the day and larger376 * fields, such as UTC377 * </ul>378 *379 * @param duration the duration, in milliseconds380 */381publicPeriod(long duration) {
382super(duration);
383 }
384385/**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 perform392 * as you might expect and split the fields evenly.393 * <p>394 * If the duration is large then all the remaining duration will395 * 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 milliseconds399 * @param type which set of fields this period supports, null means standard400 */401publicPeriod(long duration, PeriodType type) {
402super(duration, type, null);
403 }
404405/**406 * Creates a period from the given millisecond duration using the standard407 * 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 perform413 * as you might expect and split the fields evenly.414 * <p>415 * If the duration is large then all the remaining duration will416 * 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 milliseconds420 * @param chronology the chronology to use to split the duration, null means ISO default421 */422publicPeriod(long duration, Chronology chronology) {
423super(duration, null, chronology);
424 }
425426/**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 perform433 * as you might expect and split the fields evenly.434 * <p>435 * If the duration is large then all the remaining duration will436 * 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 milliseconds440 * @param type which set of fields this period supports, null means standard441 * @param chronology the chronology to use to split the duration, null means ISO default442 */443publicPeriod(long duration, PeriodType type, Chronology chronology) {
444super(duration, type, chronology);
445 }
446447/**448 * Creates a period from the given interval endpoints using the standard449 * set of fields.450 *451 * @param startInstant interval start, in milliseconds452 * @param endInstant interval end, in milliseconds453 */454publicPeriod(long startInstant, long endInstant) {
455super(startInstant, endInstant, null, null);
456 }
457458/**459 * Creates a period from the given interval endpoints.460 *461 * @param startInstant interval start, in milliseconds462 * @param endInstant interval end, in milliseconds463 * @param type which set of fields this period supports, null means standard464 */465publicPeriod(long startInstant, long endInstant, PeriodType type) {
466super(startInstant, endInstant, type, null);
467 }
468469/**470 * Creates a period from the given interval endpoints using the standard471 * set of fields.472 *473 * @param startInstant interval start, in milliseconds474 * @param endInstant interval end, in milliseconds475 * @param chrono the chronology to use, null means ISO in default zone476 */477publicPeriod(long startInstant, long endInstant, Chronology chrono) {
478super(startInstant, endInstant, null, chrono);
479 }
480481/**482 * Creates a period from the given interval endpoints.483 *484 * @param startInstant interval start, in milliseconds485 * @param endInstant interval end, in milliseconds486 * @param type which set of fields this period supports, null means standard487 * @param chrono the chronology to use, null means ISO in default zone488 */489publicPeriod(long startInstant, long endInstant, PeriodType type, Chronology chrono) {
490super(startInstant, endInstant, type, chrono);
491 }
492493/**494 * Creates a period from the given interval endpoints using the standard495 * set of fields.496 *497 * @param startInstant interval start, null means now498 * @param endInstant interval end, null means now499 */500publicPeriod(ReadableInstant startInstant, ReadableInstant endInstant) {
501super(startInstant, endInstant, null);
502 }
503504/**505 * Creates a period from the given interval endpoints.506 *507 * @param startInstant interval start, null means now508 * @param endInstant interval end, null means now509 * @param type which set of fields this period supports, null means standard510 */511publicPeriod(ReadableInstant startInstant, ReadableInstant endInstant, PeriodType type) {
512super(startInstant, endInstant, type);
513 }
514515/**516 * Creates a period from two partially specified times.517 * <p>518 * The two partials must contain the same fields, thus you can specify519 * 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 - see524 * {@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 Partials528 * 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 null532 * @param end the end of the period, must not be null533 * @throws IllegalArgumentException if the partials are null or invalid534 * @since 1.1535 */536publicPeriod(ReadablePartial start, ReadablePartial end) {
537super(start, end, null);
538 }
539540/**541 * Creates a period from two partially specified times.542 * <p>543 * The two partials must contain the same fields, thus you can specify544 * 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 - see549 * {@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 Partials553 * 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 null557 * @param end the end of the period, must not be null558 * @param type which set of fields this period supports, null means standard559 * @throws IllegalArgumentException if the partials are null or invalid560 * @since 1.1561 */562publicPeriod(ReadablePartial start, ReadablePartial end, PeriodType type) {
563super(start, end, type);
564 }
565566/**567 * Creates a period from the given start point and the duration.568 *569 * @param startInstant the interval start, null means now570 * @param duration the duration of the interval, null means zero-length571 */572publicPeriod(ReadableInstant startInstant, ReadableDuration duration) {
573super(startInstant, duration, null);
574 }
575576/**577 * Creates a period from the given start point and the duration.578 *579 * @param startInstant the interval start, null means now580 * @param duration the duration of the interval, null means zero-length581 * @param type which set of fields this period supports, null means standard582 */583publicPeriod(ReadableInstant startInstant, ReadableDuration duration, PeriodType type) {
584super(startInstant, duration, type);
585 }
586587/**588 * Creates a period from the given duration and end point.589 *590 * @param duration the duration of the interval, null means zero-length591 * @param endInstant the interval end, null means now592 */593publicPeriod(ReadableDuration duration, ReadableInstant endInstant) {
594super(duration, endInstant, null);
595 }
596597/**598 * Creates a period from the given duration and end point.599 *600 * @param duration the duration of the interval, null means zero-length601 * @param endInstant the interval end, null means now602 * @param type which set of fields this period supports, null means standard603 */604publicPeriod(ReadableDuration duration, ReadableInstant endInstant, PeriodType type) {
605super(duration, endInstant, type);
606 }
607608/**609 * Creates a period by converting or copying from another object.610 * <p>611 * The recognised object types are defined in612 * {@link org.joda.time.convert.ConverterManager ConverterManager} and613 * include ReadablePeriod, ReadableInterval and String.614 * The String formats are described by {@link ISOPeriodFormat#standard()}.615 *616 * @param period period to convert617 * @throws IllegalArgumentException if period is invalid618 * @throws UnsupportedOperationException if an unsupported field's value is non-zero619 */620publicPeriod(Object period) {
621super(period, null, null);
622 }
623624/**625 * Creates a period by converting or copying from another object.626 * <p>627 * The recognised object types are defined in628 * {@link org.joda.time.convert.ConverterManager ConverterManager} and629 * include ReadablePeriod, ReadableInterval and String.630 * The String formats are described by {@link ISOPeriodFormat#standard()}.631 *632 * @param period period to convert633 * @param type which set of fields this period supports, null means use converter634 * @throws IllegalArgumentException if period is invalid635 * @throws UnsupportedOperationException if an unsupported field's value is non-zero636 */637publicPeriod(Object period, PeriodType type) {
638super(period, type, null);
639 }
640641/**642 * Creates a period by converting or copying from another object.643 * <p>644 * The recognised object types are defined in645 * {@link org.joda.time.convert.ConverterManager ConverterManager} and646 * include ReadablePeriod, ReadableInterval and String.647 * The String formats are described by {@link ISOPeriodFormat#standard()}.648 *649 * @param period period to convert650 * @param chrono the chronology to use, null means ISO in default zone651 * @throws IllegalArgumentException if period is invalid652 * @throws UnsupportedOperationException if an unsupported field's value is non-zero653 */654publicPeriod(Object period, Chronology chrono) {
655super(period, null, chrono);
656 }
657658/**659 * Creates a period by converting or copying from another object.660 * <p>661 * The recognised object types are defined in662 * {@link org.joda.time.convert.ConverterManager ConverterManager} and663 * include ReadablePeriod, ReadableInterval and String.664 * The String formats are described by {@link ISOPeriodFormat#standard()}.665 *666 * @param period period to convert667 * @param type which set of fields this period supports, null means use converter668 * @param chrono the chronology to use, null means ISO in default zone669 * @throws IllegalArgumentException if period is invalid670 * @throws UnsupportedOperationException if an unsupported field's value is non-zero671 */672publicPeriod(Object period, PeriodType type, Chronology chrono) {
673super(period, type, chrono);
674 }
675676/**677 * Constructor used when we trust ourselves.678 *679 * @param values the values to use, not null, not cloned680 * @param type which set of fields this period supports, not null681 */682privatePeriod(int[] values, PeriodType type) {
683super(values, type);
684 }
685686//-----------------------------------------------------------------------687/**688 * Get this period as an immutable <code>Period</code> object689 * by returning <code>this</code>.690 * 691 * @return <code>this</code>692 */693publicPeriod toPeriod() {
694returnthis;
695 }
696697//-----------------------------------------------------------------------698/**699 * Gets the years field part of the period.700 * 701 * @return the number of years in the period, zero if unsupported702 */703publicint getYears() {
704return getPeriodType().getIndexedField(this, PeriodType.YEAR_INDEX);
705 }
706707/**708 * Gets the months field part of the period.709 * 710 * @return the number of months in the period, zero if unsupported711 */712publicint getMonths() {
713return getPeriodType().getIndexedField(this, PeriodType.MONTH_INDEX);
714 }
715716/**717 * Gets the weeks field part of the period.718 * 719 * @return the number of weeks in the period, zero if unsupported720 */721publicint getWeeks() {
722return getPeriodType().getIndexedField(this, PeriodType.WEEK_INDEX);
723 }
724725/**726 * Gets the days field part of the period.727 * 728 * @return the number of days in the period, zero if unsupported729 */730publicint getDays() {
731return getPeriodType().getIndexedField(this, PeriodType.DAY_INDEX);
732 }
733734//-----------------------------------------------------------------------735/**736 * Gets the hours field part of the period.737 * 738 * @return the number of hours in the period, zero if unsupported739 */740publicint getHours() {
741return getPeriodType().getIndexedField(this, PeriodType.HOUR_INDEX);
742 }
743744/**745 * Gets the minutes field part of the period.746 * 747 * @return the number of minutes in the period, zero if unsupported748 */749publicint getMinutes() {
750return getPeriodType().getIndexedField(this, PeriodType.MINUTE_INDEX);
751 }
752753/**754 * Gets the seconds field part of the period.755 * 756 * @return the number of seconds in the period, zero if unsupported757 */758publicint getSeconds() {
759return getPeriodType().getIndexedField(this, PeriodType.SECOND_INDEX);
760 }
761762/**763 * Gets the millis field part of the period.764 * 765 * @return the number of millis in the period, zero if unsupported766 */767publicint getMillis() {
768return getPeriodType().getIndexedField(this, PeriodType.MILLI_INDEX);
769 }
770771//-----------------------------------------------------------------------772/**773 * Creates a new Period instance with the same field values but774 * 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 standard779 * @return the new period instance780 * @throws IllegalArgumentException if the new period won't accept all of the current fields781 */782publicPeriod withPeriodType(PeriodType type) {
783 type = DateTimeUtils.getPeriodType(type);
784if (type.equals(getPeriodType())) {
785returnthis;
786 }
787returnnewPeriod(this, type);
788 }
789790/**791 * Creates a new Period instance with the fields from the specified period792 * 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 ignored797 * @return the new period instance798 * @throws IllegalArgumentException if a field type is unsupported799 */800publicPeriod withFields(ReadablePeriod period) {
801if (period == null) {
802returnthis;
803 }
804int[] newValues = getValues(); // cloned805 newValues = super.mergePeriodInto(newValues, period);
806returnnewPeriod(newValues, getPeriodType());
807 }
808809//-----------------------------------------------------------------------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 null816 * @param value the value to set to817 * @return the new period instance818 * @throws IllegalArgumentException if the field type is null or unsupported819 */820publicPeriod withField(DurationFieldType field, int value) {
821if (field == null) {
822thrownew IllegalArgumentException("Field must not be null");
823 }
824int[] newValues = getValues(); // cloned825super.setFieldInto(newValues, field, value);
826returnnewPeriod(newValues, getPeriodType());
827 }
828829/**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 null835 * @param value the value to add836 * @return the new period instance837 * @throws IllegalArgumentException if the field type is null or unsupported838 */839publicPeriod withFieldAdded(DurationFieldType field, int value) {
840if (field == null) {
841thrownew IllegalArgumentException("Field must not be null");
842 }
843if (value == 0) {
844returnthis;
845 }
846int[] newValues = getValues(); // cloned847super.addFieldInto(newValues, field, value);
848returnnewPeriod(newValues, getPeriodType());
849 }
850851//-----------------------------------------------------------------------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 negative858 * @return the new period with the increased years859 * @throws UnsupportedOperationException if the field is not supported860 */861publicPeriod withYears(int years) {
862int[] values = getValues(); // cloned863 getPeriodType().setIndexedField(this, PeriodType.YEAR_INDEX, values, years);
864returnnewPeriod(values, getPeriodType());
865 }
866867/**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 negative873 * @return the new period with the increased months874 * @throws UnsupportedOperationException if the field is not supported875 */876publicPeriod withMonths(int months) {
877int[] values = getValues(); // cloned878 getPeriodType().setIndexedField(this, PeriodType.MONTH_INDEX, values, months);
879returnnewPeriod(values, getPeriodType());
880 }
881882/**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 negative888 * @return the new period with the increased weeks889 * @throws UnsupportedOperationException if the field is not supported890 */891publicPeriod withWeeks(int weeks) {
892int[] values = getValues(); // cloned893 getPeriodType().setIndexedField(this, PeriodType.WEEK_INDEX, values, weeks);
894returnnewPeriod(values, getPeriodType());
895 }
896897/**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 negative903 * @return the new period with the increased days904 * @throws UnsupportedOperationException if the field is not supported905 */906publicPeriod withDays(int days) {
907int[] values = getValues(); // cloned908 getPeriodType().setIndexedField(this, PeriodType.DAY_INDEX, values, days);
909returnnewPeriod(values, getPeriodType());
910 }
911912/**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 negative918 * @return the new period with the increased hours919 * @throws UnsupportedOperationException if the field is not supported920 */921publicPeriod withHours(int hours) {
922int[] values = getValues(); // cloned923 getPeriodType().setIndexedField(this, PeriodType.HOUR_INDEX, values, hours);
924returnnewPeriod(values, getPeriodType());
925 }
926927/**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 negative933 * @return the new period with the increased minutes934 * @throws UnsupportedOperationException if the field is not supported935 */936publicPeriod withMinutes(int minutes) {
937int[] values = getValues(); // cloned938 getPeriodType().setIndexedField(this, PeriodType.MINUTE_INDEX, values, minutes);
939returnnewPeriod(values, getPeriodType());
940 }
941942/**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 negative948 * @return the new period with the increased seconds949 * @throws UnsupportedOperationException if the field is not supported950 */951publicPeriod withSeconds(int seconds) {
952int[] values = getValues(); // cloned953 getPeriodType().setIndexedField(this, PeriodType.SECOND_INDEX, values, seconds);
954returnnewPeriod(values, getPeriodType());
955 }
956957/**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 negative963 * @return the new period with the increased millis964 * @throws UnsupportedOperationException if the field is not supported965 */966publicPeriod withMillis(int millis) {
967int[] values = getValues(); // cloned968 getPeriodType().setIndexedField(this, PeriodType.MILLI_INDEX, values, millis);
969returnnewPeriod(values, getPeriodType());
970 }
971972//-----------------------------------------------------------------------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 of977 * 2 hours 30 minutes plus 3 hours 40 minutes will produce a result978 * of 5 hours 70 minutes - see {@link #normalizedStandard()}.979 * <p>980 * If the period being added contains a non-zero amount for a field that981 * 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 this986 * @return the new updated period987 * @throws UnsupportedOperationException if any field is not supported988 * @since 1.5989 */990publicPeriod plus(ReadablePeriod period) {
991if (period == null) {
992returnthis;
993 }
994int[] values = getValues(); // cloned995 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));
1003returnnewPeriod(values, getPeriodType());
1004 }
10051006//-----------------------------------------------------------------------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 negative1013 * @return the new period with the increased years1014 * @throws UnsupportedOperationException if the field is not supported1015 */1016publicPeriod plusYears(int years) {
1017if (years == 0) {
1018returnthis;
1019 }
1020int[] values = getValues(); // cloned1021 getPeriodType().addIndexedField(this, PeriodType.YEAR_INDEX, values, years);
1022returnnewPeriod(values, getPeriodType());
1023 }
10241025/**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 negative1031 * @return the new period plus the increased months1032 * @throws UnsupportedOperationException if the field is not supported1033 */1034publicPeriod plusMonths(int months) {
1035if (months == 0) {
1036returnthis;
1037 }
1038int[] values = getValues(); // cloned1039 getPeriodType().addIndexedField(this, PeriodType.MONTH_INDEX, values, months);
1040returnnewPeriod(values, getPeriodType());
1041 }
10421043/**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 negative1049 * @return the new period plus the increased weeks1050 * @throws UnsupportedOperationException if the field is not supported1051 */1052publicPeriod plusWeeks(int weeks) {
1053if (weeks == 0) {
1054returnthis;
1055 }
1056int[] values = getValues(); // cloned1057 getPeriodType().addIndexedField(this, PeriodType.WEEK_INDEX, values, weeks);
1058returnnewPeriod(values, getPeriodType());
1059 }
10601061/**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 negative1067 * @return the new period plus the increased days1068 * @throws UnsupportedOperationException if the field is not supported1069 */1070publicPeriod plusDays(int days) {
1071if (days == 0) {
1072returnthis;
1073 }
1074int[] values = getValues(); // cloned1075 getPeriodType().addIndexedField(this, PeriodType.DAY_INDEX, values, days);
1076returnnewPeriod(values, getPeriodType());
1077 }
10781079/**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 negative1085 * @return the new period plus the increased hours1086 * @throws UnsupportedOperationException if the field is not supported1087 */1088publicPeriod plusHours(int hours) {
1089if (hours == 0) {
1090returnthis;
1091 }
1092int[] values = getValues(); // cloned1093 getPeriodType().addIndexedField(this, PeriodType.HOUR_INDEX, values, hours);
1094returnnewPeriod(values, getPeriodType());
1095 }
10961097/**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 negative1103 * @return the new period plus the increased minutes1104 * @throws UnsupportedOperationException if the field is not supported1105 */1106publicPeriod plusMinutes(int minutes) {
1107if (minutes == 0) {
1108returnthis;
1109 }
1110int[] values = getValues(); // cloned1111 getPeriodType().addIndexedField(this, PeriodType.MINUTE_INDEX, values, minutes);
1112returnnewPeriod(values, getPeriodType());
1113 }
11141115/**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 negative1121 * @return the new period plus the increased seconds1122 * @throws UnsupportedOperationException if the field is not supported1123 */1124publicPeriod plusSeconds(int seconds) {
1125if (seconds == 0) {
1126returnthis;
1127 }
1128int[] values = getValues(); // cloned1129 getPeriodType().addIndexedField(this, PeriodType.SECOND_INDEX, values, seconds);
1130returnnewPeriod(values, getPeriodType());
1131 }
11321133/**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 negative1139 * @return the new period plus the increased millis1140 * @throws UnsupportedOperationException if the field is not supported1141 */1142publicPeriod plusMillis(int millis) {
1143if (millis == 0) {
1144returnthis;
1145 }
1146int[] values = getValues(); // cloned1147 getPeriodType().addIndexedField(this, PeriodType.MILLI_INDEX, values, millis);
1148returnnewPeriod(values, getPeriodType());
1149 }
11501151//-----------------------------------------------------------------------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 of1156 * 3 hours 30 minutes minus 2 hours 40 minutes will produce a result1157 * 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 that1160 * 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 this1165 * @return the new updated period1166 * @throws UnsupportedOperationException if any field is not supported1167 * @since 1.51168 */1169publicPeriod minus(ReadablePeriod period) {
1170if (period == null) {
1171returnthis;
1172 }
1173int[] values = getValues(); // cloned1174 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));
1182returnnewPeriod(values, getPeriodType());
1183 }
11841185//-----------------------------------------------------------------------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 negative1192 * @return the new period with the increased years1193 * @throws UnsupportedOperationException if the field is not supported1194 */1195publicPeriod minusYears(int years) {
1196return plusYears(-years);
1197 }
11981199/**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 negative1205 * @return the new period minus the increased months1206 * @throws UnsupportedOperationException if the field is not supported1207 */1208publicPeriod minusMonths(int months) {
1209return plusMonths(-months);
1210 }
12111212/**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 negative1218 * @return the new period minus the increased weeks1219 * @throws UnsupportedOperationException if the field is not supported1220 */1221publicPeriod minusWeeks(int weeks) {
1222return plusWeeks(-weeks);
1223 }
12241225/**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 negative1231 * @return the new period minus the increased days1232 * @throws UnsupportedOperationException if the field is not supported1233 */1234publicPeriod minusDays(int days) {
1235return plusDays(-days);
1236 }
12371238/**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 negative1244 * @return the new period minus the increased hours1245 * @throws UnsupportedOperationException if the field is not supported1246 */1247publicPeriod minusHours(int hours) {
1248return plusHours(-hours);
1249 }
12501251/**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 negative1257 * @return the new period minus the increased minutes1258 * @throws UnsupportedOperationException if the field is not supported1259 */1260publicPeriod minusMinutes(int minutes) {
1261return plusMinutes(-minutes);
1262 }
12631264/**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 negative1270 * @return the new period minus the increased seconds1271 * @throws UnsupportedOperationException if the field is not supported1272 */1273publicPeriod minusSeconds(int seconds) {
1274return plusSeconds(-seconds);
1275 }
12761277/**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 negative1283 * @return the new period minus the increased millis1284 * @throws UnsupportedOperationException if the field is not supported1285 */1286publicPeriod minusMillis(int millis) {
1287return plusMillis(-millis);
1288 }
12891290//-----------------------------------------------------------------------1291/**1292 * Returns a new instance with each element in this period multiplied1293 * by the specified scalar.1294 *1295 * @param scalar the scalar to multiply by, not null1296 * @return a {@code Period} based on this period with the amounts multiplied by the scalar, never null1297 * @throws ArithmeticException if the capacity of any field is exceeded1298 * @since 2.11299 */1300publicPeriod multipliedBy(int scalar) {
1301if (this == ZERO || scalar == 1) {
1302returnthis;
1303 }
1304int[] values = getValues(); // cloned1305for (int i = 0; i < values.length; i++) {
1306 values[i] = FieldUtils.safeMultiply(values[i], scalar);
1307 }
1308returnnewPeriod(values, getPeriodType());
1309 }
13101311/**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 null1315 * @throws ArithmeticException if any field has the minimum value1316 * @since 2.11317 */1318publicPeriod negated() {
1319return multipliedBy(-1);
1320 }
13211322//-----------------------------------------------------------------------1323/**1324 * Converts this period to a period in weeks assuming a1325 * 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 all1329 * weeks are 7 days, all days are 24 hours, all hours are 60 minutes and1330 * all minutes are 60 seconds. This is not true when daylight savings time1331 * is considered, and may also not be true for some unusual chronologies.1332 * However, it is included as it is a useful operation for many1333 * 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 period1338 * @throws UnsupportedOperationException if the period contains years or months1339 * @throws ArithmeticException if the number of weeks is too large to be represented1340 * @since 1.51341 */1342publicWeeks toStandardWeeks() {
1343 checkYearsAndMonths("Weeks");
1344long millis = getMillis(); // assign to a long1345 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;
1349long weeks = ((long) getWeeks()) + millis / DateTimeConstants.MILLIS_PER_WEEK;
1350return Weeks.weeks(FieldUtils.safeToInt(weeks));
1351 }
13521353/**1354 * Converts this period to a period in days assuming a1355 * 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 all1359 * weeks are 7 days, all days are 24 hours, all hours are 60 minutes and1360 * all minutes are 60 seconds. This is not true when daylight savings time1361 * is considered, and may also not be true for some unusual chronologies.1362 * However, it is included as it is a useful operation for many1363 * 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 period1368 * @throws UnsupportedOperationException if the period contains years or months1369 * @throws ArithmeticException if the number of days is too large to be represented1370 * @since 1.51371 */1372publicDays toStandardDays() {
1373 checkYearsAndMonths("Days");
1374long millis = getMillis(); // assign to a long1375 millis += ((long) getSeconds()) * DateTimeConstants.MILLIS_PER_SECOND;
1376 millis += ((long) getMinutes()) * DateTimeConstants.MILLIS_PER_MINUTE;
1377 millis += ((long) getHours()) * DateTimeConstants.MILLIS_PER_HOUR;
1378long days = millis / DateTimeConstants.MILLIS_PER_DAY;
1379 days = FieldUtils.safeAdd(days, getDays());
1380 days = FieldUtils.safeAdd(days, ((long) getWeeks()) * ((long) DateTimeConstants.DAYS_PER_WEEK));
1381return Days.days(FieldUtils.safeToInt(days));
1382 }
13831384/**1385 * Converts this period to a period in hours assuming a1386 * 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 all1390 * weeks are 7 days, all days are 24 hours, all hours are 60 minutes and1391 * all minutes are 60 seconds. This is not true when daylight savings time1392 * is considered, and may also not be true for some unusual chronologies.1393 * However, it is included as it is a useful operation for many1394 * 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 period1399 * @throws UnsupportedOperationException if the period contains years or months1400 * @throws ArithmeticException if the number of hours is too large to be represented1401 * @since 1.51402 */1403publicHours toStandardHours() {
1404 checkYearsAndMonths("Hours");
1405long millis = getMillis(); // assign to a long1406 millis += ((long) getSeconds()) * DateTimeConstants.MILLIS_PER_SECOND;
1407 millis += ((long) getMinutes()) * DateTimeConstants.MILLIS_PER_MINUTE;
1408long 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));
1412return Hours.hours(FieldUtils.safeToInt(hours));
1413 }
14141415/**1416 * Converts this period to a period in minutes assuming a1417 * 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 all1421 * weeks are 7 days, all days are 24 hours, all hours are 60 minutes and1422 * all minutes are 60 seconds. This is not true when daylight savings time1423 * is considered, and may also not be true for some unusual chronologies.1424 * However, it is included as it is a useful operation for many1425 * 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 period1430 * @throws UnsupportedOperationException if the period contains years or months1431 * @throws ArithmeticException if the number of minutes is too large to be represented1432 * @since 1.51433 */1434publicMinutes toStandardMinutes() {
1435 checkYearsAndMonths("Minutes");
1436long millis = getMillis(); // assign to a long1437 millis += ((long) getSeconds()) * DateTimeConstants.MILLIS_PER_SECOND;
1438long 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));
1443return Minutes.minutes(FieldUtils.safeToInt(minutes));
1444 }
14451446/**1447 * Converts this period to a period in seconds assuming a1448 * 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 all1452 * weeks are 7 days, all days are 24 hours, all hours are 60 minutes and1453 * all minutes are 60 seconds. This is not true when daylight savings time1454 * is considered, and may also not be true for some unusual chronologies.1455 * However, it is included as it is a useful operation for many1456 * 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 period1461 * @throws UnsupportedOperationException if the period contains years or months1462 * @throws ArithmeticException if the number of seconds is too large to be represented1463 * @since 1.51464 */1465publicSeconds toStandardSeconds() {
1466 checkYearsAndMonths("Seconds");
1467long 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));
1473return Seconds.seconds(FieldUtils.safeToInt(seconds));
1474 }
14751476//-----------------------------------------------------------------------1477/**1478 * Converts this period to a duration assuming a1479 * 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 all1483 * weeks are 7 days, all days are 24 hours, all hours are 60 minutes and1484 * all minutes are 60 seconds. This is not true when daylight savings time1485 * is considered, and may also not be true for some unusual chronologies.1486 * However, it is included as it is a useful operation for many1487 * 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 period1492 * @throws UnsupportedOperationException if the period contains years or months1493 * @since 1.51494 */1495publicDuration toStandardDuration() {
1496 checkYearsAndMonths("Duration");
1497long millis = getMillis(); // no overflow can happen, even with Integer.MAX_VALUEs1498 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));
1503returnnewDuration(millis);
1504 }
15051506/**1507 * Check that there are no years or months in the period.1508 * 1509 * @param destintionType the destination type, not null1510 * @throws UnsupportedOperationException if the period contains years or months1511 */1512privatevoid checkYearsAndMonths(String destintionType) {
1513if (getMonths() != 0) {
1514thrownew UnsupportedOperationException("Cannot convert to " + destintionType + " as this period contains months and months vary in length");
1515 }
1516if (getYears() != 0) {
1517thrownew UnsupportedOperationException("Cannot convert to " + destintionType + " as this period contains years and years vary in length");
1518 }
1519 }
15201521//-----------------------------------------------------------------------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 are1528 * 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 not1530 * true when daylight savings time is considered, and may also not be true1531 * for some chronologies. However, it is included as it is a useful operation1532 * for many applications and business rules.1533 * <p>1534 * If the period contains years or months, then the months will be1535 * normalized to be between 0 and 11. The days field and below will be1536 * normalized as necessary, however this will not overflow into the months1537 * 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, thus1541 * days will be grouped into weeks.1542 * 1543 * @return a normalized period equivalent to this period1544 * @throws ArithmeticException if any field is too large to be represented1545 * @since 1.51546 */1547publicPeriod normalizedStandard() {
1548return normalizedStandard(PeriodType.standard());
1549 }
15501551//-----------------------------------------------------------------------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 are1559 * 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 not1561 * true when daylight savings time is considered, and may also not be true1562 * for some chronologies. However, it is included as it is a useful operation1563 * for many applications and business rules.1564 * <p>1565 * If the period contains years or months, then the months will be1566 * normalized to be between 0 and 11. The days field and below will be1567 * normalized as necessary, however this will not overflow into the months1568 * 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 allows1572 * 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 pass1574 * in <code>PeriodType.yearMonthDayTime()</code>.1575 * 1576 * @param type the period type of the new period, null means standard type1577 * @return a normalized period equivalent to this period1578 * @throws ArithmeticException if any field is too large to be represented1579 * @throws UnsupportedOperationException if this period contains non-zero1580 * years or months but the specified period type does not support them1581 * @since 1.51582 */1583publicPeriod normalizedStandard(PeriodType type) {
1584long millis = getMillis(); // no overflow can happen, even with Integer.MAX_VALUEs1585 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));
1590Period result = newPeriod(millis, DateTimeUtils.getPeriodType(type), ISOChronology.getInstanceUTC());
1591int years = getYears();
1592int months = getMonths();
1593if (years != 0 || months != 0) {
1594 years = FieldUtils.safeAdd(years, months / 12);
1595 months = months % 12;
1596if (years != 0) {
1597 result = result.withYears(years);
1598 }
1599if (months != 0) {
1600 result = result.withMonths(months);
1601 }
1602 }
1603return result;
1604 }
16051606 }