| 1 | /* |
| 2 | * Copyright 2001-2005 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.IOException; |
| 19 | import java.io.ObjectInputStream; |
| 20 | import java.io.ObjectOutputStream; |
| 21 | import java.io.Serializable; |
| 22 | import java.util.Locale; |
| 23 | |
| 24 | import org.joda.time.base.BaseDateTime; |
| 25 | import org.joda.time.chrono.ISOChronology; |
| 26 | import org.joda.time.field.AbstractReadableInstantFieldProperty; |
| 27 | import org.joda.time.field.FieldUtils; |
| 28 | import org.joda.time.format.ISODateTimeFormat; |
| 29 | |
| 30 | /** |
| 31 | * MutableDateTime is the standard implementation of a modifiable datetime class. |
| 32 | * It holds the datetime as milliseconds from the Java epoch of 1970-01-01T00:00:00Z. |
| 33 | * <p> |
| 34 | * This class uses a Chronology internally. The Chronology determines how the |
| 35 | * millisecond instant value is converted into the date time fields. |
| 36 | * The default Chronology is <code>ISOChronology</code> which is the agreed |
| 37 | * international standard and compatable with the modern Gregorian calendar. |
| 38 | * <p> |
| 39 | * Each individual field can be accessed in two ways: |
| 40 | * <ul> |
| 41 | * <li><code>getHourOfDay()</code> |
| 42 | * <li><code>hourOfDay().get()</code> |
| 43 | * </ul> |
| 44 | * The second technique also provides access to other useful methods on the |
| 45 | * field: |
| 46 | * <ul> |
| 47 | * <li>get numeric value |
| 48 | * <li>set numeric value |
| 49 | * <li>add to numeric value |
| 50 | * <li>add to numeric value wrapping with the field |
| 51 | * <li>get text vlaue |
| 52 | * <li>get short text value |
| 53 | * <li>set text value |
| 54 | * <li>field maximum value |
| 55 | * <li>field minimum value |
| 56 | * </ul> |
| 57 | * |
| 58 | * <p> |
| 59 | * MutableDateTime is mutable and not thread-safe, unless concurrent threads |
| 60 | * are not invoking mutator methods. |
| 61 | * |
| 62 | * @author Guy Allard |
| 63 | * @author Brian S O'Neill |
| 64 | * @author Stephen Colebourne |
| 65 | * @author Mike Schrag |
| 66 | * @since 1.0 |
| 67 | * @see DateTime |
| 68 | */ |
| 69 | public class MutableDateTime |
| 70 | extends BaseDateTime |
| 71 | implements ReadWritableDateTime, Cloneable, Serializable { |
| 72 | |
| 73 | /** Serialization version */ |
| 74 | private static final long serialVersionUID = 2852608688135209575L; |
| 75 | |
| 76 | /** Rounding is disabled */ |
| 77 | public static final int ROUND_NONE = 0; |
| 78 | /** Rounding mode as described by {@link DateTimeField#roundFloor} */ |
| 79 | public static final int ROUND_FLOOR = 1; |
| 80 | /** Rounding mode as described by {@link DateTimeField#roundCeiling} */ |
| 81 | public static final int ROUND_CEILING = 2; |
| 82 | /** Rounding mode as described by {@link DateTimeField#roundHalfFloor} */ |
| 83 | public static final int ROUND_HALF_FLOOR = 3; |
| 84 | /** Rounding mode as described by {@link DateTimeField#roundHalfCeiling} */ |
| 85 | public static final int ROUND_HALF_CEILING = 4; |
| 86 | /** Rounding mode as described by {@link DateTimeField#roundHalfEven} */ |
| 87 | public static final int ROUND_HALF_EVEN = 5; |
| 88 | |
| 89 | /** The field to round on */ |
| 90 | private DateTimeField iRoundingField; |
| 91 | /** The mode of rounding */ |
| 92 | private int iRoundingMode; |
| 93 | |
| 94 | //----------------------------------------------------------------------- |
| 95 | /** |
| 96 | * Constructs an instance set to the current system millisecond time |
| 97 | * using <code>ISOChronology</code> in the default time zone. |
| 98 | */ |
| 99 | public MutableDateTime() { |
| 100 | super(); |
| 101 | } |
| 102 | |
| 103 | /** |
| 104 | * Constructs an instance set to the current system millisecond time |
| 105 | * using <code>ISOChronology</code> in the specified time zone. |
| 106 | * <p> |
| 107 | * If the specified time zone is null, the default zone is used. |
| 108 | * |
| 109 | * @param zone the time zone, null means default zone |
| 110 | */ |
| 111 | public MutableDateTime(DateTimeZone zone) { |
| 112 | super(zone); |
| 113 | } |
| 114 | |
| 115 | /** |
| 116 | * Constructs an instance set to the current system millisecond time |
| 117 | * using the specified chronology. |
| 118 | * <p> |
| 119 | * If the chronology is null, <code>ISOChronology</code> |
| 120 | * in the default time zone is used. |
| 121 | * |
| 122 | * @param chronology the chronology, null means ISOChronology in default zone |
| 123 | */ |
| 124 | public MutableDateTime(Chronology chronology) { |
| 125 | super(chronology); |
| 126 | } |
| 127 | |
| 128 | //----------------------------------------------------------------------- |
| 129 | /** |
| 130 | * Constructs an instance set to the milliseconds from 1970-01-01T00:00:00Z |
| 131 | * using <code>ISOChronology</code> in the default time zone. |
| 132 | * |
| 133 | * @param instant the milliseconds from 1970-01-01T00:00:00Z |
| 134 | */ |
| 135 | public MutableDateTime(long instant) { |
| 136 | super(instant); |
| 137 | } |
| 138 | |
| 139 | /** |
| 140 | * Constructs an instance set to the milliseconds from 1970-01-01T00:00:00Z |
| 141 | * using <code>ISOChronology</code> in the specified time zone. |
| 142 | * <p> |
| 143 | * If the specified time zone is null, the default zone is used. |
| 144 | * |
| 145 | * @param instant the milliseconds from 1970-01-01T00:00:00Z |
| 146 | * @param zone the time zone, null means default zone |
| 147 | */ |
| 148 | public MutableDateTime(long instant, DateTimeZone zone) { |
| 149 | super(instant, zone); |
| 150 | } |
| 151 | |
| 152 | /** |
| 153 | * Constructs an instance set to the milliseconds from 1970-01-01T00:00:00Z |
| 154 | * using the specified chronology. |
| 155 | * <p> |
| 156 | * If the chronology is null, <code>ISOChronology</code> |
| 157 | * in the default time zone is used. |
| 158 | * |
| 159 | * @param instant the milliseconds from 1970-01-01T00:00:00Z |
| 160 | * @param chronology the chronology, null means ISOChronology in default zone |
| 161 | */ |
| 162 | public MutableDateTime(long instant, Chronology chronology) { |
| 163 | super(instant, chronology); |
| 164 | } |
| 165 | |
| 166 | //----------------------------------------------------------------------- |
| 167 | /** |
| 168 | * Constructs an instance from an Object that represents a datetime. |
| 169 | * <p> |
| 170 | * If the object implies a chronology (such as GregorianCalendar does), |
| 171 | * then that chronology will be used. Otherwise, ISO default is used. |
| 172 | * Thus if a GregorianCalendar is passed in, the chronology used will |
| 173 | * be GJ, but if a Date is passed in the chronology will be ISO. |
| 174 | * <p> |
| 175 | * The recognised object types are defined in |
| 176 | * {@link org.joda.time.convert.ConverterManager ConverterManager} and |
| 177 | * include ReadableInstant, String, Calendar and Date. |
| 178 | * |
| 179 | * @param instant the datetime object, null means now |
| 180 | * @throws IllegalArgumentException if the instant is invalid |
| 181 | */ |
| 182 | public MutableDateTime(Object instant) { |
| 183 | super(instant, (Chronology) null); |
| 184 | } |
| 185 | |
| 186 | /** |
| 187 | * Constructs an instance from an Object that represents a datetime, |
| 188 | * forcing the time zone to that specified. |
| 189 | * <p> |
| 190 | * If the object implies a chronology (such as GregorianCalendar does), |
| 191 | * then that chronology will be used, but with the time zone adjusted. |
| 192 | * Otherwise, ISO is used in the specified time zone. |
| 193 | * If the specified time zone is null, the default zone is used. |
| 194 | * Thus if a GregorianCalendar is passed in, the chronology used will |
| 195 | * be GJ, but if a Date is passed in the chronology will be ISO. |
| 196 | * <p> |
| 197 | * The recognised object types are defined in |
| 198 | * {@link org.joda.time.convert.ConverterManager ConverterManager} and |
| 199 | * include ReadableInstant, String, Calendar and Date. |
| 200 | * |
| 201 | * @param instant the datetime object, null means now |
| 202 | * @param zone the time zone, null means default time zone |
| 203 | * @throws IllegalArgumentException if the instant is invalid |
| 204 | */ |
| 205 | public MutableDateTime(Object instant, DateTimeZone zone) { |
| 206 | super(instant, zone); |
| 207 | } |
| 208 | |
| 209 | /** |
| 210 | * Constructs an instance from an Object that represents a datetime, |
| 211 | * using the specified chronology. |
| 212 | * <p> |
| 213 | * If the chronology is null, ISO in the default time zone is used. |
| 214 | * Any chronology implied by the object (such as GregorianCalendar does) |
| 215 | * is ignored. |
| 216 | * <p> |
| 217 | * The recognised object types are defined in |
| 218 | * {@link org.joda.time.convert.ConverterManager ConverterManager} and |
| 219 | * include ReadableInstant, String, Calendar and Date. |
| 220 | * |
| 221 | * @param instant the datetime object, null means now |
| 222 | * @param chronology the chronology, null means ISOChronology in default zone |
| 223 | * @throws IllegalArgumentException if the instant is invalid |
| 224 | */ |
| 225 | public MutableDateTime(Object instant, Chronology chronology) { |
| 226 | super(instant, DateTimeUtils.getChronology(chronology)); |
| 227 | } |
| 228 | |
| 229 | //----------------------------------------------------------------------- |
| 230 | /** |
| 231 | * Constructs an instance from datetime field values |
| 232 | * using <code>ISOChronology</code> in the default time zone. |
| 233 | * |
| 234 | * @param year the year |
| 235 | * @param monthOfYear the month of the year |
| 236 | * @param dayOfMonth the day of the month |
| 237 | * @param hourOfDay the hour of the day |
| 238 | * @param minuteOfHour the minute of the hour |
| 239 | * @param secondOfMinute the second of the minute |
| 240 | * @param millisOfSecond the millisecond of the second |
| 241 | */ |
| 242 | public MutableDateTime( |
| 243 | int year, |
| 244 | int monthOfYear, |
| 245 | int dayOfMonth, |
| 246 | int hourOfDay, |
| 247 | int minuteOfHour, |
| 248 | int secondOfMinute, |
| 249 | int millisOfSecond) { |
| 250 | super(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond); |
| 251 | } |
| 252 | |
| 253 | /** |
| 254 | * Constructs an instance from datetime field values |
| 255 | * using <code>ISOChronology</code> in the specified time zone. |
| 256 | * <p> |
| 257 | * If the specified time zone is null, the default zone is used. |
| 258 | * |
| 259 | * @param year the year |
| 260 | * @param monthOfYear the month of the year |
| 261 | * @param dayOfMonth the day of the month |
| 262 | * @param hourOfDay the hour of the day |
| 263 | * @param minuteOfHour the minute of the hour |
| 264 | * @param secondOfMinute the second of the minute |
| 265 | * @param millisOfSecond the millisecond of the second |
| 266 | * @param zone the time zone, null means default time zone |
| 267 | */ |
| 268 | public MutableDateTime( |
| 269 | int year, |
| 270 | int monthOfYear, |
| 271 | int dayOfMonth, |
| 272 | int hourOfDay, |
| 273 | int minuteOfHour, |
| 274 | int secondOfMinute, |
| 275 | int millisOfSecond, |
| 276 | DateTimeZone zone) { |
| 277 | super(year, monthOfYear, dayOfMonth, |
| 278 | hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond, zone); |
| 279 | } |
| 280 | |
| 281 | /** |
| 282 | * Constructs an instance from datetime field values |
| 283 | * using the specified chronology. |
| 284 | * <p> |
| 285 | * If the chronology is null, <code>ISOChronology</code> |
| 286 | * in the default time zone is used. |
| 287 | * |
| 288 | * @param year the year |
| 289 | * @param monthOfYear the month of the year |
| 290 | * @param dayOfMonth the day of the month |
| 291 | * @param hourOfDay the hour of the day |
| 292 | * @param minuteOfHour the minute of the hour |
| 293 | * @param secondOfMinute the second of the minute |
| 294 | * @param millisOfSecond the millisecond of the second |
| 295 | * @param chronology the chronology, null means ISOChronology in default zone |
| 296 | */ |
| 297 | public MutableDateTime( |
| 298 | int year, |
| 299 | int monthOfYear, |
| 300 | int dayOfMonth, |
| 301 | int hourOfDay, |
| 302 | int minuteOfHour, |
| 303 | int secondOfMinute, |
| 304 | int millisOfSecond, |
| 305 | Chronology chronology) { |
| 306 | super(year, monthOfYear, dayOfMonth, |
| 307 | hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond, chronology); |
| 308 | } |
| 309 | |
| 310 | //----------------------------------------------------------------------- |
| 311 | /** |
| 312 | * Gets the field used for rounding this instant, returning null if rounding |
| 313 | * is not enabled. |
| 314 | * |
| 315 | * @return the rounding field |
| 316 | */ |
| 317 | public DateTimeField getRoundingField() { |
| 318 | return iRoundingField; |
| 319 | } |
| 320 | |
| 321 | /** |
| 322 | * Gets the rounding mode for this instant, returning ROUND_NONE if rounding |
| 323 | * is not enabled. |
| 324 | * |
| 325 | * @return the rounding mode constant |
| 326 | */ |
| 327 | public int getRoundingMode() { |
| 328 | return iRoundingMode; |
| 329 | } |
| 330 | |
| 331 | /** |
| 332 | * Sets the status of rounding to use the specified field and ROUND_FLOOR mode. |
| 333 | * A null field will disable rounding. |
| 334 | * Once set, the instant is then rounded using the new field and mode. |
| 335 | * <p> |
| 336 | * Enabling rounding will cause all subsequent calls to {@link #setMillis(long)} |
| 337 | * to be rounded. This can be used to control the precision of the instant, |
| 338 | * for example by setting a rounding field of minuteOfDay, the seconds and |
| 339 | * milliseconds will always be zero. |
| 340 | * |
| 341 | * @param field rounding field or null to disable |
| 342 | */ |
| 343 | public void setRounding(DateTimeField field) { |
| 344 | setRounding(field, MutableDateTime.ROUND_FLOOR); |
| 345 | } |
| 346 | |
| 347 | /** |
| 348 | * Sets the status of rounding to use the specified field and mode. |
| 349 | * A null field or mode of ROUND_NONE will disable rounding. |
| 350 | * Once set, the instant is then rounded using the new field and mode. |
| 351 | * <p> |
| 352 | * Enabling rounding will cause all subsequent calls to {@link #setMillis(long)} |
| 353 | * to be rounded. This can be used to control the precision of the instant, |
| 354 | * for example by setting a rounding field of minuteOfDay, the seconds and |
| 355 | * milliseconds will always be zero. |
| 356 | * |
| 357 | * @param field rounding field or null to disable |
| 358 | * @param mode rounding mode or ROUND_NONE to disable |
| 359 | * @throws IllegalArgumentException if mode is unknown, no exception if field is null |
| 360 | */ |
| 361 | public void setRounding(DateTimeField field, int mode) { |
| 362 | if (field != null && (mode < ROUND_NONE || mode > ROUND_HALF_EVEN)) { |
| 363 | throw new IllegalArgumentException("Illegal rounding mode: " + mode); |
| 364 | } |
| 365 | iRoundingField = (mode == ROUND_NONE ? null : field); |
| 366 | iRoundingMode = (field == null ? ROUND_NONE : mode); |
| 367 | setMillis(getMillis()); |
| 368 | } |
| 369 | |
| 370 | //----------------------------------------------------------------------- |
| 371 | /** |
| 372 | * Set the milliseconds of the datetime. |
| 373 | * <p> |
| 374 | * All changes to the millisecond field occurs via this method. |
| 375 | * |
| 376 | * @param instant the milliseconds since 1970-01-01T00:00:00Z to set the |
| 377 | * datetime to |
| 378 | */ |
| 379 | public void setMillis(long instant) { |
| 380 | switch (iRoundingMode) { |
| 381 | case ROUND_NONE: |
| 382 | break; |
| 383 | case ROUND_FLOOR: |
| 384 | instant = iRoundingField.roundFloor(instant); |
| 385 | break; |
| 386 | case ROUND_CEILING: |
| 387 | instant = iRoundingField.roundCeiling(instant); |
| 388 | break; |
| 389 | case ROUND_HALF_FLOOR: |
| 390 | instant = iRoundingField.roundHalfFloor(instant); |
| 391 | break; |
| 392 | case ROUND_HALF_CEILING: |
| 393 | instant = iRoundingField.roundHalfCeiling(instant); |
| 394 | break; |
| 395 | case ROUND_HALF_EVEN: |
| 396 | instant = iRoundingField.roundHalfEven(instant); |
| 397 | break; |
| 398 | } |
| 399 | |
| 400 | super.setMillis(instant); |
| 401 | } |
| 402 | |
| 403 | /** |
| 404 | * Sets the millisecond instant of this instant from another. |
| 405 | * <p> |
| 406 | * This method does not change the chronology of this instant, just the |
| 407 | * millisecond instant. |
| 408 | * |
| 409 | * @param instant the instant to use, null means now |
| 410 | */ |
| 411 | public void setMillis(ReadableInstant instant) { |
| 412 | long instantMillis = DateTimeUtils.getInstantMillis(instant); |
| 413 | setMillis(instantMillis); // set via this class not super |
| 414 | } |
| 415 | |
| 416 | //----------------------------------------------------------------------- |
| 417 | /** |
| 418 | * Add an amount of time to the datetime. |
| 419 | * |
| 420 | * @param duration the millis to add |
| 421 | * @throws ArithmeticException if the result exceeds the capacity of the instant |
| 422 | */ |
| 423 | public void add(long duration) { |
| 424 | setMillis(FieldUtils.safeAdd(getMillis(), duration)); // set via this class not super |
| 425 | } |
| 426 | |
| 427 | /** |
| 428 | * Adds a duration to this instant. |
| 429 | * <p> |
| 430 | * This will typically change the value of most fields. |
| 431 | * |
| 432 | * @param duration the duration to add, null means add zero |
| 433 | * @throws ArithmeticException if the result exceeds the capacity of the instant |
| 434 | */ |
| 435 | public void add(ReadableDuration duration) { |
| 436 | add(duration, 1); |
| 437 | } |
| 438 | |
| 439 | /** |
| 440 | * Adds a duration to this instant specifying how many times to add. |
| 441 | * <p> |
| 442 | * This will typically change the value of most fields. |
| 443 | * |
| 444 | * @param duration the duration to add, null means add zero |
| 445 | * @param scalar direction and amount to add, which may be negative |
| 446 | * @throws ArithmeticException if the result exceeds the capacity of the instant |
| 447 | */ |
| 448 | public void add(ReadableDuration duration, int scalar) { |
| 449 | if (duration != null) { |
| 450 | add(FieldUtils.safeMultiply(duration.getMillis(), scalar)); |
| 451 | } |
| 452 | } |
| 453 | |
| 454 | /** |
| 455 | * Adds a period to this instant. |
| 456 | * <p> |
| 457 | * This will typically change the value of most fields. |
| 458 | * |
| 459 | * @param period the period to add, null means add zero |
| 460 | * @throws ArithmeticException if the result exceeds the capacity of the instant |
| 461 | */ |
| 462 | public void add(ReadablePeriod period) { |
| 463 | add(period, 1); |
| 464 | } |
| 465 | |
| 466 | /** |
| 467 | * Adds a period to this instant specifying how many times to add. |
| 468 | * <p> |
| 469 | * This will typically change the value of most fields. |
| 470 | * |
| 471 | * @param period the period to add, null means add zero |
| 472 | * @param scalar direction and amount to add, which may be negative |
| 473 | * @throws ArithmeticException if the result exceeds the capacity of the instant |
| 474 | */ |
| 475 | public void add(ReadablePeriod period, int scalar) { |
| 476 | if (period != null) { |
| 477 | setMillis(getChronology().add(period, getMillis(), scalar)); // set via this class not super |
| 478 | } |
| 479 | } |
| 480 | |
| 481 | //----------------------------------------------------------------------- |
| 482 | /** |
| 483 | * Set the chronology of the datetime. |
| 484 | * <p> |
| 485 | * All changes to the chronology occur via this method. |
| 486 | * |
| 487 | * @param chronology the chronology to use, null means ISOChronology in default zone |
| 488 | */ |
| 489 | public void setChronology(Chronology chronology) { |
| 490 | super.setChronology(chronology); |
| 491 | } |
| 492 | |
| 493 | //----------------------------------------------------------------------- |
| 494 | /** |
| 495 | * Sets the time zone of the datetime, changing the chronology and field values. |
| 496 | * <p> |
| 497 | * Changing the zone using this method retains the millisecond instant. |
| 498 | * The millisecond instant is adjusted in the new zone to compensate. |
| 499 | * |
| 500 | * chronology. Setting the time zone does not affect the millisecond value |
| 501 | * of this instant. |
| 502 | * <p> |
| 503 | * If the chronology already has this time zone, no change occurs. |
| 504 | * |
| 505 | * @param newZone the time zone to use, null means default zone |
| 506 | * @see #setZoneRetainFields |
| 507 | */ |
| 508 | public void setZone(DateTimeZone newZone) { |
| 509 | newZone = DateTimeUtils.getZone(newZone); |
| 510 | Chronology chrono = getChronology(); |
| 511 | if (chrono.getZone() != newZone) { |
| 512 | setChronology(chrono.withZone(newZone)); // set via this class not super |
| 513 | } |
| 514 | } |
| 515 | |
| 516 | /** |
| 517 | * Sets the time zone of the datetime, changing the chronology and millisecond. |
| 518 | * <p> |
| 519 | * Changing the zone using this method retains the field values. |
| 520 | * The millisecond instant is adjusted in the new zone to compensate. |
| 521 | * <p> |
| 522 | * If the chronology already has this time zone, no change occurs. |
| 523 | * |
| 524 | * @param newZone the time zone to use, null means default zone |
| 525 | * @see #setZone |
| 526 | */ |
| 527 | public void setZoneRetainFields(DateTimeZone newZone) { |
| 528 | newZone = DateTimeUtils.getZone(newZone); |
| 529 | DateTimeZone originalZone = DateTimeUtils.getZone(getZone()); |
| 530 | if (newZone == originalZone) { |
| 531 | return; |
| 532 | } |
| 533 | |
| 534 | long millis = originalZone.getMillisKeepLocal(newZone, getMillis()); |
| 535 | setChronology(getChronology().withZone(newZone)); // set via this class not super |
| 536 | setMillis(millis); |
| 537 | } |
| 538 | |
| 539 | //----------------------------------------------------------------------- |
| 540 | /** |
| 541 | * Sets the value of one of the fields of the instant, such as hourOfDay. |
| 542 | * |
| 543 | * @param type a field type, usually obtained from DateTimeFieldType, not null |
| 544 | * @param value the value to set the field to |
| 545 | * @throws IllegalArgumentException if the value is null or invalid |
| 546 | */ |
| 547 | public void set(DateTimeFieldType type, int value) { |
| 548 | if (type == null) { |
| 549 | throw new IllegalArgumentException("Field must not be null"); |
| 550 | } |
| 551 | setMillis(type.getField(getChronology()).set(getMillis(), value)); |
| 552 | } |
| 553 | |
| 554 | /** |
| 555 | * Adds to the instant specifying the duration and multiple to add. |
| 556 | * |
| 557 | * @param type a field type, usually obtained from DateTimeFieldType, not null |
| 558 | * @param amount the amount to add of this duration |
| 559 | * @throws IllegalArgumentException if the value is null or invalid |
| 560 | * @throws ArithmeticException if the result exceeds the capacity of the instant |
| 561 | */ |
| 562 | public void add(DurationFieldType type, int amount) { |
| 563 | if (type == null) { |
| 564 | throw new IllegalArgumentException("Field must not be null"); |
| 565 | } |
| 566 | setMillis(type.getField(getChronology()).add(getMillis(), amount)); |
| 567 | } |
| 568 | |
| 569 | //----------------------------------------------------------------------- |
| 570 | /** |
| 571 | * Set the year to the specified value. |
| 572 | * |
| 573 | * @param year the year |
| 574 | * @throws IllegalArgumentException if the value is invalid |
| 575 | */ |
| 576 | public void setYear(final int year) { |
| 577 | setMillis(getChronology().year().set(getMillis(), year)); |
| 578 | } |
| 579 | |
| 580 | /** |
| 581 | * Add a number of years to the date. |
| 582 | * |
| 583 | * @param years the years to add |
| 584 | * @throws IllegalArgumentException if the value is invalid |
| 585 | */ |
| 586 | public void addYears(final int years) { |
| 587 | setMillis(getChronology().years().add(getMillis(), years)); |
| 588 | } |
| 589 | |
| 590 | //----------------------------------------------------------------------- |
| 591 | /** |
| 592 | * Set the weekyear to the specified value. |
| 593 | * |
| 594 | * @param weekyear the weekyear |
| 595 | * @throws IllegalArgumentException if the value is invalid |
| 596 | */ |
| 597 | public void setWeekyear(final int weekyear) { |
| 598 | setMillis(getChronology().weekyear().set(getMillis(), weekyear)); |
| 599 | } |
| 600 | |
| 601 | /** |
| 602 | * Add a number of weekyears to the date. |
| 603 | * |
| 604 | * @param weekyears the weekyears to add |
| 605 | * @throws IllegalArgumentException if the value is invalid |
| 606 | */ |
| 607 | public void addWeekyears(final int weekyears) { |
| 608 | setMillis(getChronology().weekyears().add(getMillis(), weekyears)); |
| 609 | } |
| 610 | |
| 611 | //----------------------------------------------------------------------- |
| 612 | /** |
| 613 | * Set the month of the year to the specified value. |
| 614 | * |
| 615 | * @param monthOfYear the month of the year |
| 616 | * @throws IllegalArgumentException if the value is invalid |
| 617 | */ |
| 618 | public void setMonthOfYear(final int monthOfYear) { |
| 619 | setMillis(getChronology().monthOfYear().set(getMillis(), monthOfYear)); |
| 620 | } |
| 621 | |
| 622 | /** |
| 623 | * Add a number of months to the date. |
| 624 | * |
| 625 | * @param months the months to add |
| 626 | * @throws IllegalArgumentException if the value is invalid |
| 627 | */ |
| 628 | public void addMonths(final int months) { |
| 629 | setMillis(getChronology().months().add(getMillis(), months)); |
| 630 | } |
| 631 | |
| 632 | //----------------------------------------------------------------------- |
| 633 | /** |
| 634 | * Set the week of weekyear to the specified value. |
| 635 | * |
| 636 | * @param weekOfWeekyear the week of the weekyear |
| 637 | * @throws IllegalArgumentException if the value is invalid |
| 638 | */ |
| 639 | public void setWeekOfWeekyear(final int weekOfWeekyear) { |
| 640 | setMillis(getChronology().weekOfWeekyear().set(getMillis(), weekOfWeekyear)); |
| 641 | } |
| 642 | |
| 643 | /** |
| 644 | * Add a number of weeks to the date. |
| 645 | * |
| 646 | * @param weeks the weeks to add |
| 647 | * @throws IllegalArgumentException if the value is invalid |
| 648 | */ |
| 649 | public void addWeeks(final int weeks) { |
| 650 | setMillis(getChronology().weeks().add(getMillis(), weeks)); |
| 651 | } |
| 652 | |
| 653 | //----------------------------------------------------------------------- |
| 654 | /** |
| 655 | * Set the day of year to the specified value. |
| 656 | * |
| 657 | * @param dayOfYear the day of the year |
| 658 | * @throws IllegalArgumentException if the value is invalid |
| 659 | */ |
| 660 | public void setDayOfYear(final int dayOfYear) { |
| 661 | setMillis(getChronology().dayOfYear().set(getMillis(), dayOfYear)); |
| 662 | } |
| 663 | |
| 664 | /** |
| 665 | * Set the day of the month to the specified value. |
| 666 | * |
| 667 | * @param dayOfMonth the day of the month |
| 668 | * @throws IllegalArgumentException if the value is invalid |
| 669 | */ |
| 670 | public void setDayOfMonth(final int dayOfMonth) { |
| 671 | setMillis(getChronology().dayOfMonth().set(getMillis(), dayOfMonth)); |
| 672 | } |
| 673 | |
| 674 | /** |
| 675 | * Set the day of week to the specified value. |
| 676 | * |
| 677 | * @param dayOfWeek the day of the week |
| 678 | * @throws IllegalArgumentException if the value is invalid |
| 679 | */ |
| 680 | public void setDayOfWeek(final int dayOfWeek) { |
| 681 | setMillis(getChronology().dayOfWeek().set(getMillis(), dayOfWeek)); |
| 682 | } |
| 683 | |
| 684 | /** |
| 685 | * Add a number of days to the date. |
| 686 | * |
| 687 | * @param days the days to add |
| 688 | * @throws IllegalArgumentException if the value is invalid |
| 689 | */ |
| 690 | public void addDays(final int days) { |
| 691 | setMillis(getChronology().days().add(getMillis(), days)); |
| 692 | } |
| 693 | |
| 694 | //----------------------------------------------------------------------- |
| 695 | /** |
| 696 | * Set the hour of the day to the specified value. |
| 697 | * |
| 698 | * @param hourOfDay the hour of day |
| 699 | * @throws IllegalArgumentException if the value is invalid |
| 700 | */ |
| 701 | public void setHourOfDay(final int hourOfDay) { |
| 702 | setMillis(getChronology().hourOfDay().set(getMillis(), hourOfDay)); |
| 703 | } |
| 704 | |
| 705 | /** |
| 706 | * Add a number of hours to the date. |
| 707 | * |
| 708 | * @param hours the hours to add |
| 709 | * @throws IllegalArgumentException if the value is invalid |
| 710 | */ |
| 711 | public void addHours(final int hours) { |
| 712 | setMillis(getChronology().hours().add(getMillis(), hours)); |
| 713 | } |
| 714 | |
| 715 | //----------------------------------------------------------------------- |
| 716 | /** |
| 717 | * Set the minute of the day to the specified value. |
| 718 | * |
| 719 | * @param minuteOfDay the minute of day |
| 720 | * @throws IllegalArgumentException if the value is invalid |
| 721 | */ |
| 722 | public void setMinuteOfDay(final int minuteOfDay) { |
| 723 | setMillis(getChronology().minuteOfDay().set(getMillis(), minuteOfDay)); |
| 724 | } |
| 725 | |
| 726 | /** |
| 727 | * Set the minute of the hour to the specified value. |
| 728 | * |
| 729 | * @param minuteOfHour the minute of hour |
| 730 | * @throws IllegalArgumentException if the value is invalid |
| 731 | */ |
| 732 | public void setMinuteOfHour(final int minuteOfHour) { |
| 733 | setMillis(getChronology().minuteOfHour().set(getMillis(), minuteOfHour)); |
| 734 | } |
| 735 | |
| 736 | /** |
| 737 | * Add a number of minutes to the date. |
| 738 | * |
| 739 | * @param minutes the minutes to add |
| 740 | * @throws IllegalArgumentException if the value is invalid |
| 741 | */ |
| 742 | public void addMinutes(final int minutes) { |
| 743 | setMillis(getChronology().minutes().add(getMillis(), minutes)); |
| 744 | } |
| 745 | |
| 746 | //----------------------------------------------------------------------- |
| 747 | /** |
| 748 | * Set the second of the day to the specified value. |
| 749 | * |
| 750 | * @param secondOfDay the second of day |
| 751 | * @throws IllegalArgumentException if the value is invalid |
| 752 | */ |
| 753 | public void setSecondOfDay(final int secondOfDay) { |
| 754 | setMillis(getChronology().secondOfDay().set(getMillis(), secondOfDay)); |
| 755 | } |
| 756 | |
| 757 | /** |
| 758 | * Set the second of the minute to the specified value. |
| 759 | * |
| 760 | * @param secondOfMinute the second of minute |
| 761 | * @throws IllegalArgumentException if the value is invalid |
| 762 | */ |
| 763 | public void setSecondOfMinute(final int secondOfMinute) { |
| 764 | setMillis(getChronology().secondOfMinute().set(getMillis(), secondOfMinute)); |
| 765 | } |
| 766 | |
| 767 | /** |
| 768 | * Add a number of seconds to the date. |
| 769 | * |
| 770 | * @param seconds the seconds to add |
| 771 | * @throws IllegalArgumentException if the value is invalid |
| 772 | */ |
| 773 | public void addSeconds(final int seconds) { |
| 774 | setMillis(getChronology().seconds().add(getMillis(), seconds)); |
| 775 | } |
| 776 | |
| 777 | //----------------------------------------------------------------------- |
| 778 | /** |
| 779 | * Set the millis of the day to the specified value. |
| 780 | * |
| 781 | * @param millisOfDay the millis of day |
| 782 | * @throws IllegalArgumentException if the value is invalid |
| 783 | */ |
| 784 | public void setMillisOfDay(final int millisOfDay) { |
| 785 | setMillis(getChronology().millisOfDay().set(getMillis(), millisOfDay)); |
| 786 | } |
| 787 | |
| 788 | /** |
| 789 | * Set the millis of the second to the specified value. |
| 790 | * |
| 791 | * @param millisOfSecond the millis of second |
| 792 | * @throws IllegalArgumentException if the value is invalid |
| 793 | */ |
| 794 | public void setMillisOfSecond(final int millisOfSecond) { |
| 795 | setMillis(getChronology().millisOfSecond().set(getMillis(), millisOfSecond)); |
| 796 | } |
| 797 | |
| 798 | /** |
| 799 | * Add a number of milliseconds to the date. The implementation of this |
| 800 | * method differs from the {@link #add(long)} method in that a |
| 801 | * DateTimeField performs the addition. |
| 802 | * |
| 803 | * @param millis the milliseconds to add |
| 804 | * @throws IllegalArgumentException if the value is invalid |
| 805 | */ |
| 806 | public void addMillis(final int millis) { |
| 807 | setMillis(getChronology().millis().add(getMillis(), millis)); |
| 808 | } |
| 809 | |
| 810 | //----------------------------------------------------------------------- |
| 811 | /** |
| 812 | * Set the date from milliseconds. |
| 813 | * The time part of this object will be unaffected. |
| 814 | * |
| 815 | * @param instant an instant to copy the date from, time part ignored |
| 816 | * @throws IllegalArgumentException if the value is invalid |
| 817 | */ |
| 818 | public void setDate(final long instant) { |
| 819 | setMillis(getChronology().millisOfDay().set(instant, getMillisOfDay())); |
| 820 | } |
| 821 | |
| 822 | /** |
| 823 | * Set the date from another instant. |
| 824 | * The time part of this object will be unaffected. |
| 825 | * |
| 826 | * @param instant an instant to copy the date from, time part ignored |
| 827 | * @throws IllegalArgumentException if the object is invalid |
| 828 | */ |
| 829 | public void setDate(final ReadableInstant instant) { |
| 830 | long instantMillis = DateTimeUtils.getInstantMillis(instant); |
| 831 | Chronology instantChrono = DateTimeUtils.getInstantChronology(instant); |
| 832 | DateTimeZone zone = instantChrono.getZone(); |
| 833 | if (zone != null) { |
| 834 | instantMillis = zone.getMillisKeepLocal(DateTimeZone.UTC, instantMillis); |
| 835 | } |
| 836 | setDate(instantMillis); |
| 837 | } |
| 838 | |
| 839 | /** |
| 840 | * Set the date from fields. |
| 841 | * The time part of this object will be unaffected. |
| 842 | * |
| 843 | * @param year the year |
| 844 | * @param monthOfYear the month of the year |
| 845 | * @param dayOfMonth the day of the month |
| 846 | * @throws IllegalArgumentException if the value is invalid |
| 847 | */ |
| 848 | public void setDate( |
| 849 | final int year, |
| 850 | final int monthOfYear, |
| 851 | final int dayOfMonth) { |
| 852 | Chronology c = getChronology(); |
| 853 | long instantMidnight = c.getDateTimeMillis(year, monthOfYear, dayOfMonth, 0); |
| 854 | setDate(instantMidnight); |
| 855 | } |
| 856 | |
| 857 | //----------------------------------------------------------------------- |
| 858 | /** |
| 859 | * Set the time from milliseconds. |
| 860 | * The date part of this object will be unaffected. |
| 861 | * |
| 862 | * @param millis an instant to copy the time from, date part ignored |
| 863 | * @throws IllegalArgumentException if the value is invalid |
| 864 | */ |
| 865 | public void setTime(final long millis) { |
| 866 | int millisOfDay = ISOChronology.getInstanceUTC().millisOfDay().get(millis); |
| 867 | setMillis(getChronology().millisOfDay().set(getMillis(), millisOfDay)); |
| 868 | } |
| 869 | |
| 870 | /** |
| 871 | * Set the time from another instant. |
| 872 | * The date part of this object will be unaffected. |
| 873 | * |
| 874 | * @param instant an instant to copy the time from, date part ignored |
| 875 | * @throws IllegalArgumentException if the object is invalid |
| 876 | */ |
| 877 | public void setTime(final ReadableInstant instant) { |
| 878 | long instantMillis = DateTimeUtils.getInstantMillis(instant); |
| 879 | Chronology instantChrono = DateTimeUtils.getInstantChronology(instant); |
| 880 | DateTimeZone zone = instantChrono.getZone(); |
| 881 | if (zone != null) { |
| 882 | instantMillis = zone.getMillisKeepLocal(DateTimeZone.UTC, instantMillis); |
| 883 | } |
| 884 | setTime(instantMillis); |
| 885 | } |
| 886 | |
| 887 | /** |
| 888 | * Set the time from fields. |
| 889 | * The date part of this object will be unaffected. |
| 890 | * |
| 891 | * @param hour the hour |
| 892 | * @param minuteOfHour the minute of the hour |
| 893 | * @param secondOfMinute the second of the minute |
| 894 | * @param millisOfSecond the millisecond of the second |
| 895 | * @throws IllegalArgumentException if the value is invalid |
| 896 | */ |
| 897 | public void setTime( |
| 898 | final int hour, |
| 899 | final int minuteOfHour, |
| 900 | final int secondOfMinute, |
| 901 | final int millisOfSecond) { |
| 902 | long instant = getChronology().getDateTimeMillis( |
| 903 | getMillis(), hour, minuteOfHour, secondOfMinute, millisOfSecond); |
| 904 | setMillis(instant); |
| 905 | } |
| 906 | |
| 907 | /** |
| 908 | * Set the date and time from fields. |
| 909 | * |
| 910 | * @param year the year |
| 911 | * @param monthOfYear the month of the year |
| 912 | * @param dayOfMonth the day of the month |
| 913 | * @param hourOfDay the hour of the day |
| 914 | * @param minuteOfHour the minute of the hour |
| 915 | * @param secondOfMinute the second of the minute |
| 916 | * @param millisOfSecond the millisecond of the second |
| 917 | * @throws IllegalArgumentException if the value is invalid |
| 918 | */ |
| 919 | public void setDateTime( |
| 920 | final int year, |
| 921 | final int monthOfYear, |
| 922 | final int dayOfMonth, |
| 923 | final int hourOfDay, |
| 924 | final int minuteOfHour, |
| 925 | final int secondOfMinute, |
| 926 | final int millisOfSecond) { |
| 927 | long instant = getChronology().getDateTimeMillis( |
| 928 | year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond); |
| 929 | setMillis(instant); |
| 930 | } |
| 931 | |
| 932 | //----------------------------------------------------------------------- |
| 933 | /** |
| 934 | * Gets the property object for the specified type, which contains many useful methods. |
| 935 | * |
| 936 | * @param type the field type to get the chronology for |
| 937 | * @return the property object |
| 938 | * @throws IllegalArgumentException if the field is null or unsupported |
| 939 | * @since 1.2 |
| 940 | */ |
| 941 | public Property property(DateTimeFieldType type) { |
| 942 | if (type == null) { |
| 943 | throw new IllegalArgumentException("The DateTimeFieldType must not be null"); |
| 944 | } |
| 945 | DateTimeField field = type.getField(getChronology()); |
| 946 | if (field.isSupported() == false) { |
| 947 | throw new IllegalArgumentException("Field '" + type + "' is not supported"); |
| 948 | } |
| 949 | return new Property(this, field); |
| 950 | } |
| 951 | |
| 952 | /** |
| 953 | * Get the era property. |
| 954 | * |
| 955 | * @return the era property |
| 956 | */ |
| 957 | public Property era() { |
| 958 | return new Property(this, getChronology().era()); |
| 959 | } |
| 960 | |
| 961 | /** |
| 962 | * Get the century of era property. |
| 963 | * |
| 964 | * @return the year of era property |
| 965 | */ |
| 966 | public Property centuryOfEra() { |
| 967 | return new Property(this, getChronology().centuryOfEra()); |
| 968 | } |
| 969 | |
| 970 | /** |
| 971 | * Get the year of century property. |
| 972 | * |
| 973 | * @return the year of era property |
| 974 | */ |
| 975 | public Property yearOfCentury() { |
| 976 | return new Property(this, getChronology().yearOfCentury()); |
| 977 | } |
| 978 | |
| 979 | /** |
| 980 | * Get the year of era property. |
| 981 | * |
| 982 | * @return the year of era property |
| 983 | */ |
| 984 | public Property yearOfEra() { |
| 985 | return new Property(this, getChronology().yearOfEra()); |
| 986 | } |
| 987 | |
| 988 | /** |
| 989 | * Get the year property. |
| 990 | * |
| 991 | * @return the year property |
| 992 | */ |
| 993 | public Property year() { |
| 994 | return new Property(this, getChronology().year()); |
| 995 | } |
| 996 | |
| 997 | /** |
| 998 | * Get the year of a week based year property. |
| 999 | * |
| 1000 | * @return the year of a week based year property |
| 1001 | */ |
| 1002 | public Property weekyear() { |
| 1003 | return new Property(this, getChronology().weekyear()); |
| 1004 | } |
| 1005 | |
| 1006 | /** |
| 1007 | * Get the month of year property. |
| 1008 | * |
| 1009 | * @return the month of year property |
| 1010 | */ |
| 1011 | public Property monthOfYear() { |
| 1012 | return new Property(this, getChronology().monthOfYear()); |
| 1013 | } |
| 1014 | |
| 1015 | /** |
| 1016 | * Get the week of a week based year property. |
| 1017 | * |
| 1018 | * @return the week of a week based year property |
| 1019 | */ |
| 1020 | public Property weekOfWeekyear() { |
| 1021 | return new Property(this, getChronology().weekOfWeekyear()); |
| 1022 | } |
| 1023 | |
| 1024 | /** |
| 1025 | * Get the day of year property. |
| 1026 | * |
| 1027 | * @return the day of year property |
| 1028 | */ |
| 1029 | public Property dayOfYear() { |
| 1030 | return new Property(this, getChronology().dayOfYear()); |
| 1031 | } |
| 1032 | |
| 1033 | /** |
| 1034 | * Get the day of month property. |
| 1035 | * <p> |
| 1036 | * The values for day of month are defined in {@link DateTimeConstants}. |
| 1037 | * |
| 1038 | * @return the day of month property |
| 1039 | */ |
| 1040 | public Property dayOfMonth() { |
| 1041 | return new Property(this, getChronology().dayOfMonth()); |
| 1042 | } |
| 1043 | |
| 1044 | /** |
| 1045 | * Get the day of week property. |
| 1046 | * <p> |
| 1047 | * The values for day of week are defined in {@link DateTimeConstants}. |
| 1048 | * |
| 1049 | * @return the day of week property |
| 1050 | */ |
| 1051 | public Property dayOfWeek() { |
| 1052 | return new Property(this, getChronology().dayOfWeek()); |
| 1053 | } |
| 1054 | |
| 1055 | //----------------------------------------------------------------------- |
| 1056 | /** |
| 1057 | * Get the hour of day field property |
| 1058 | * |
| 1059 | * @return the hour of day property |
| 1060 | */ |
| 1061 | public Property hourOfDay() { |
| 1062 | return new Property(this, getChronology().hourOfDay()); |
| 1063 | } |
| 1064 | |
| 1065 | /** |
| 1066 | * Get the minute of day property |
| 1067 | * |
| 1068 | * @return the minute of day property |
| 1069 | */ |
| 1070 | public Property minuteOfDay() { |
| 1071 | return new Property(this, getChronology().minuteOfDay()); |
| 1072 | } |
| 1073 | |
| 1074 | /** |
| 1075 | * Get the minute of hour field property |
| 1076 | * |
| 1077 | * @return the minute of hour property |
| 1078 | */ |
| 1079 | public Property minuteOfHour() { |
| 1080 | return new Property(this, getChronology().minuteOfHour()); |
| 1081 | } |
| 1082 | |
| 1083 | /** |
| 1084 | * Get the second of day property |
| 1085 | * |
| 1086 | * @return the second of day property |
| 1087 | */ |
| 1088 | public Property secondOfDay() { |
| 1089 | return new Property(this, getChronology().secondOfDay()); |
| 1090 | } |
| 1091 | |
| 1092 | /** |
| 1093 | * Get the second of minute field property |
| 1094 | * |
| 1095 | * @return the second of minute property |
| 1096 | */ |
| 1097 | public Property secondOfMinute() { |
| 1098 | return new Property(this, getChronology().secondOfMinute()); |
| 1099 | } |
| 1100 | |
| 1101 | /** |
| 1102 | * Get the millis of day property |
| 1103 | * |
| 1104 | * @return the millis of day property |
| 1105 | */ |
| 1106 | public Property millisOfDay() { |
| 1107 | return new Property(this, getChronology().millisOfDay()); |
| 1108 | } |
| 1109 | |
| 1110 | /** |
| 1111 | * Get the millis of second property |
| 1112 | * |
| 1113 | * @return the millis of second property |
| 1114 | */ |
| 1115 | public Property millisOfSecond() { |
| 1116 | return new Property(this, getChronology().millisOfSecond()); |
| 1117 | } |
| 1118 | |
| 1119 | //----------------------------------------------------------------------- |
| 1120 | /** |
| 1121 | * Clone this object without having to cast the returned object. |
| 1122 | * |
| 1123 | * @return a clone of the this object. |
| 1124 | */ |
| 1125 | public MutableDateTime copy() { |
| 1126 | return (MutableDateTime) clone(); |
| 1127 | } |
| 1128 | |
| 1129 | //----------------------------------------------------------------------- |
| 1130 | /** |
| 1131 | * Clone this object. |
| 1132 | * |
| 1133 | * @return a clone of this object. |
| 1134 | */ |
| 1135 | public Object clone() { |
| 1136 | try { |
| 1137 | return super.clone(); |
| 1138 | } catch (CloneNotSupportedException ex) { |
| 1139 | throw new InternalError("Clone error"); |
| 1140 | } |
| 1141 | } |
| 1142 | |
| 1143 | /** |
| 1144 | * Output the date time in ISO8601 format (yyyy-MM-ddTHH:mm:ss.SSSZZ). |
| 1145 | * |
| 1146 | * @return ISO8601 time formatted string. |
| 1147 | */ |
| 1148 | public String toString() { |
| 1149 | return ISODateTimeFormat.dateTime().print(this); |
| 1150 | } |
| 1151 | |
| 1152 | /** |
| 1153 | * MutableDateTime.Property binds a MutableDateTime to a |
| 1154 | * DateTimeField allowing powerful datetime functionality to be easily |
| 1155 | * accessed. |
| 1156 | * <p> |
| 1157 | * The example below shows how to use the property to change the value of a |
| 1158 | * MutableDateTime object. |
| 1159 | * <pre> |
| 1160 | * MutableDateTime dt = new MutableDateTime(1972, 12, 3, 13, 32, 19, 123); |
| 1161 | * dt.year().add(20); |
| 1162 | * dt.second().roundFloor().minute().set(10); |
| 1163 | * </pre> |
| 1164 | * <p> |
| 1165 | * MutableDateTime.Propery itself is thread-safe and immutable, but the |
| 1166 | * MutableDateTime being operated on is not. |
| 1167 | * |
| 1168 | * @author Stephen Colebourne |
| 1169 | * @author Brian S O'Neill |
| 1170 | * @since 1.0 |
| 1171 | */ |
| 1172 | public static final class Property extends AbstractReadableInstantFieldProperty { |
| 1173 | |
| 1174 | /** Serialization version */ |
| 1175 | private static final long serialVersionUID = -4481126543819298617L; |
| 1176 | |
| 1177 | /** The instant this property is working against */ |
| 1178 | private MutableDateTime iInstant; |
| 1179 | /** The field this property is working against */ |
| 1180 | private DateTimeField iField; |
| 1181 | |
| 1182 | /** |
| 1183 | * Constructor. |
| 1184 | * |
| 1185 | * @param instant the instant to set |
| 1186 | * @param field the field to use |
| 1187 | */ |
| 1188 | Property(MutableDateTime instant, DateTimeField field) { |
| 1189 | super(); |
| 1190 | iInstant = instant; |
| 1191 | iField = field; |
| 1192 | } |
| 1193 | |
| 1194 | /** |
| 1195 | * Writes the property in a safe serialization format. |
| 1196 | */ |
| 1197 | private void writeObject(ObjectOutputStream oos) throws IOException { |
| 1198 | oos.writeObject(iInstant); |
| 1199 | oos.writeObject(iField.getType()); |
| 1200 | } |
| 1201 | |
| 1202 | /** |
| 1203 | * Reads the property from a safe serialization format. |
| 1204 | */ |
| 1205 | private void readObject(ObjectInputStream oos) throws IOException, ClassNotFoundException { |
| 1206 | iInstant = (MutableDateTime) oos.readObject(); |
| 1207 | DateTimeFieldType type = (DateTimeFieldType) oos.readObject(); |
| 1208 | iField = type.getField(iInstant.getChronology()); |
| 1209 | } |
| 1210 | |
| 1211 | //----------------------------------------------------------------------- |
| 1212 | /** |
| 1213 | * Gets the field being used. |
| 1214 | * |
| 1215 | * @return the field |
| 1216 | */ |
| 1217 | public DateTimeField getField() { |
| 1218 | return iField; |
| 1219 | } |
| 1220 | |
| 1221 | /** |
| 1222 | * Gets the milliseconds of the datetime that this property is linked to. |
| 1223 | * |
| 1224 | * @return the milliseconds |
| 1225 | */ |
| 1226 | protected long getMillis() { |
| 1227 | return iInstant.getMillis(); |
| 1228 | } |
| 1229 | |
| 1230 | /** |
| 1231 | * Gets the chronology of the datetime that this property is linked to. |
| 1232 | * |
| 1233 | * @return the chronology |
| 1234 | * @since 1.4 |
| 1235 | */ |
| 1236 | protected Chronology getChronology() { |
| 1237 | return iInstant.getChronology(); |
| 1238 | } |
| 1239 | |
| 1240 | /** |
| 1241 | * Gets the mutable datetime being used. |
| 1242 | * |
| 1243 | * @return the mutable datetime |
| 1244 | */ |
| 1245 | public MutableDateTime getMutableDateTime() { |
| 1246 | return iInstant; |
| 1247 | } |
| 1248 | |
| 1249 | //----------------------------------------------------------------------- |
| 1250 | /** |
| 1251 | * Adds a value to the millis value. |
| 1252 | * |
| 1253 | * @param value the value to add |
| 1254 | * @return the mutable datetime being used, so calls can be chained |
| 1255 | * @see DateTimeField#add(long,int) |
| 1256 | */ |
| 1257 | public MutableDateTime add(int value) { |
| 1258 | iInstant.setMillis(getField().add(iInstant.getMillis(), value)); |
| 1259 | return iInstant; |
| 1260 | } |
| 1261 | |
| 1262 | /** |
| 1263 | * Adds a value to the millis value. |
| 1264 | * |
| 1265 | * @param value the value to add |
| 1266 | * @return the mutable datetime being used, so calls can be chained |
| 1267 | * @see DateTimeField#add(long,long) |
| 1268 | */ |
| 1269 | public MutableDateTime add(long value) { |
| 1270 | iInstant.setMillis(getField().add(iInstant.getMillis(), value)); |
| 1271 | return iInstant; |
| 1272 | } |
| 1273 | |
| 1274 | /** |
| 1275 | * Adds a value, possibly wrapped, to the millis value. |
| 1276 | * |
| 1277 | * @param value the value to add |
| 1278 | * @return the mutable datetime being used, so calls can be chained |
| 1279 | * @see DateTimeField#addWrapField |
| 1280 | */ |
| 1281 | public MutableDateTime addWrapField(int value) { |
| 1282 | iInstant.setMillis(getField().addWrapField(iInstant.getMillis(), value)); |
| 1283 | return iInstant; |
| 1284 | } |
| 1285 | |
| 1286 | //----------------------------------------------------------------------- |
| 1287 | /** |
| 1288 | * Sets a value. |
| 1289 | * |
| 1290 | * @param value the value to set. |
| 1291 | * @return the mutable datetime being used, so calls can be chained |
| 1292 | * @see DateTimeField#set(long,int) |
| 1293 | */ |
| 1294 | public MutableDateTime set(int value) { |
| 1295 | iInstant.setMillis(getField().set(iInstant.getMillis(), value)); |
| 1296 | return iInstant; |
| 1297 | } |
| 1298 | |
| 1299 | /** |
| 1300 | * Sets a text value. |
| 1301 | * |
| 1302 | * @param text the text value to set |
| 1303 | * @param locale optional locale to use for selecting a text symbol |
| 1304 | * @return the mutable datetime being used, so calls can be chained |
| 1305 | * @throws IllegalArgumentException if the text value isn't valid |
| 1306 | * @see DateTimeField#set(long,java.lang.String,java.util.Locale) |
| 1307 | */ |
| 1308 | public MutableDateTime set(String text, Locale locale) { |
| 1309 | iInstant.setMillis(getField().set(iInstant.getMillis(), text, locale)); |
| 1310 | return iInstant; |
| 1311 | } |
| 1312 | |
| 1313 | /** |
| 1314 | * Sets a text value. |
| 1315 | * |
| 1316 | * @param text the text value to set |
| 1317 | * @return the mutable datetime being used, so calls can be chained |
| 1318 | * @throws IllegalArgumentException if the text value isn't valid |
| 1319 | * @see DateTimeField#set(long,java.lang.String) |
| 1320 | */ |
| 1321 | public MutableDateTime set(String text) { |
| 1322 | set(text, null); |
| 1323 | return iInstant; |
| 1324 | } |
| 1325 | |
| 1326 | //----------------------------------------------------------------------- |
| 1327 | /** |
| 1328 | * Round to the lowest whole unit of this field. |
| 1329 | * |
| 1330 | * @return the mutable datetime being used, so calls can be chained |
| 1331 | * @see DateTimeField#roundFloor |
| 1332 | */ |
| 1333 | public MutableDateTime roundFloor() { |
| 1334 | iInstant.setMillis(getField().roundFloor(iInstant.getMillis())); |
| 1335 | return iInstant; |
| 1336 | } |
| 1337 | |
| 1338 | /** |
| 1339 | * Round to the highest whole unit of this field. |
| 1340 | * |
| 1341 | * @return the mutable datetime being used, so calls can be chained |
| 1342 | * @see DateTimeField#roundCeiling |
| 1343 | */ |
| 1344 | public MutableDateTime roundCeiling() { |
| 1345 | iInstant.setMillis(getField().roundCeiling(iInstant.getMillis())); |
| 1346 | return iInstant; |
| 1347 | } |
| 1348 | |
| 1349 | /** |
| 1350 | * Round to the nearest whole unit of this field, favoring the floor if |
| 1351 | * halfway. |
| 1352 | * |
| 1353 | * @return the mutable datetime being used, so calls can be chained |
| 1354 | * @see DateTimeField#roundHalfFloor |
| 1355 | */ |
| 1356 | public MutableDateTime roundHalfFloor() { |
| 1357 | iInstant.setMillis(getField().roundHalfFloor(iInstant.getMillis())); |
| 1358 | return iInstant; |
| 1359 | } |
| 1360 | |
| 1361 | /** |
| 1362 | * Round to the nearest whole unit of this field, favoring the ceiling if |
| 1363 | * halfway. |
| 1364 | * |
| 1365 | * @return the mutable datetime being used, so calls can be chained |
| 1366 | * @see DateTimeField#roundHalfCeiling |
| 1367 | */ |
| 1368 | public MutableDateTime roundHalfCeiling() { |
| 1369 | iInstant.setMillis(getField().roundHalfCeiling(iInstant.getMillis())); |
| 1370 | return iInstant; |
| 1371 | } |
| 1372 | |
| 1373 | /** |
| 1374 | * Round to the nearest whole unit of this field. If halfway, the ceiling |
| 1375 | * is favored over the floor only if it makes this field's value even. |
| 1376 | * |
| 1377 | * @return the mutable datetime being used, so calls can be chained |
| 1378 | * @see DateTimeField#roundHalfEven |
| 1379 | */ |
| 1380 | public MutableDateTime roundHalfEven() { |
| 1381 | iInstant.setMillis(getField().roundHalfEven(iInstant.getMillis())); |
| 1382 | return iInstant; |
| 1383 | } |
| 1384 | } |
| 1385 | |
| 1386 | } |