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 }