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