001 /* 002 * Copyright 2001-2006 Stephen Colebourne 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.joda.time; 017 018 import java.io.IOException; 019 import java.io.ObjectInputStream; 020 import java.io.ObjectOutputStream; 021 import java.io.Serializable; 022 import java.util.Locale; 023 024 import org.joda.time.base.BaseDateTime; 025 import org.joda.time.field.AbstractReadableInstantFieldProperty; 026 import org.joda.time.format.ISODateTimeFormat; 027 028 /** 029 * DateMidnight defines a date where the time component is fixed at midnight. 030 * The class uses a time zone, thus midnight is local unless a UTC time zone is used. 031 * <p> 032 * It is important to emphasise that this class represents the time of midnight on 033 * any given day. 034 * Note that midnight is defined as 00:00, which is at the very start of a day. 035 * <p> 036 * This class does not represent a day, but the millisecond instant at midnight. 037 * If you need a class that represents the whole day, then an {@link Interval} or 038 * a {@link LocalDate} may be more suitable. 039 * <p> 040 * This class uses a Chronology internally. The Chronology determines how the 041 * millisecond instant value is converted into the date time fields. 042 * The default Chronology is <code>ISOChronology</code> which is the agreed 043 * international standard and compatable with the modern Gregorian calendar. 044 * 045 * <p>Each individual field can be queried in two ways: 046 * <ul> 047 * <li><code>getDayOfMonth()</code> 048 * <li><code>dayOfMonth().get()</code> 049 * </ul> 050 * The second technique also provides access to other useful methods on the 051 * field: 052 * <ul> 053 * <li>numeric value 054 * <li>text value 055 * <li>short text value 056 * <li>maximum/minimum values 057 * <li>add/subtract 058 * <li>set 059 * <li>rounding 060 * </ul> 061 * 062 * <p> 063 * DateMidnight is thread-safe and immutable, provided that the Chronology is as well. 064 * All standard Chronology classes supplied are thread-safe and immutable. 065 * 066 * @author Stephen Colebourne 067 * @since 1.0 068 */ 069 public final class DateMidnight 070 extends BaseDateTime 071 implements ReadableDateTime, Serializable { 072 073 /** Serialization lock */ 074 private static final long serialVersionUID = 156371964018738L; 075 076 // Constructors 077 //----------------------------------------------------------------------- 078 /** 079 * Constructs an instance set to the current system millisecond time 080 * using <code>ISOChronology</code> in the default time zone. 081 * The constructed object will have a local time of midnight. 082 */ 083 public DateMidnight() { 084 super(); 085 } 086 087 /** 088 * Constructs an instance set to the current system millisecond time 089 * using <code>ISOChronology</code> in the specified time zone. 090 * The constructed object will have a local time of midnight. 091 * <p> 092 * If the specified time zone is null, the default zone is used. 093 * 094 * @param zone the time zone, null means default zone 095 */ 096 public DateMidnight(DateTimeZone zone) { 097 super(zone); 098 } 099 100 /** 101 * Constructs an instance set to the current system millisecond time 102 * using the specified chronology. 103 * The constructed object will have a local time of midnight. 104 * <p> 105 * If the chronology is null, <code>ISOChronology</code> 106 * in the default time zone is used. 107 * 108 * @param chronology the chronology, null means ISOChronology in default zone 109 */ 110 public DateMidnight(Chronology chronology) { 111 super(chronology); 112 } 113 114 //----------------------------------------------------------------------- 115 /** 116 * Constructs an instance set to the milliseconds from 1970-01-01T00:00:00Z 117 * using <code>ISOChronology</code> in the default time zone. 118 * The constructed object will have a local time of midnight. 119 * 120 * @param instant the milliseconds from 1970-01-01T00:00:00Z 121 */ 122 public DateMidnight(long instant) { 123 super(instant); 124 } 125 126 /** 127 * Constructs an instance set to the milliseconds from 1970-01-01T00:00:00Z 128 * using <code>ISOChronology</code> in the specified time zone. 129 * The constructed object will have a local time of midnight. 130 * <p> 131 * If the specified time zone is null, the default zone is used. 132 * 133 * @param instant the milliseconds from 1970-01-01T00:00:00Z 134 * @param zone the time zone, null means default zone 135 */ 136 public DateMidnight(long instant, DateTimeZone zone) { 137 super(instant, zone); 138 } 139 140 /** 141 * Constructs an instance set to the milliseconds from 1970-01-01T00:00:00Z 142 * using the specified chronology. 143 * The constructed object will have a local time of midnight. 144 * <p> 145 * If the chronology is null, <code>ISOChronology</code> 146 * in the default time zone is used. 147 * 148 * @param instant the milliseconds from 1970-01-01T00:00:00Z 149 * @param chronology the chronology, null means ISOChronology in default zone 150 */ 151 public DateMidnight(long instant, Chronology chronology) { 152 super(instant, chronology); 153 } 154 155 //----------------------------------------------------------------------- 156 /** 157 * Constructs an instance from an Object that represents a datetime. 158 * The constructed object will have a local time of midnight. 159 * <p> 160 * If the object implies a chronology (such as GregorianCalendar does), 161 * then that chronology will be used. Otherwise, ISO default is used. 162 * Thus if a GregorianCalendar is passed in, the chronology used will 163 * be GJ, but if a Date is passed in the chronology will be ISO. 164 * <p> 165 * The recognised object types are defined in 166 * {@link org.joda.time.convert.ConverterManager ConverterManager} and 167 * include ReadableInstant, String, Calendar and Date. 168 * The String formats are described by {@link ISODateTimeFormat#dateTimeParser()}. 169 * 170 * @param instant the datetime object, null means now 171 * @throws IllegalArgumentException if the instant is invalid 172 */ 173 public DateMidnight(Object instant) { 174 super(instant, (Chronology) null); 175 } 176 177 /** 178 * Constructs an instance from an Object that represents a datetime, 179 * forcing the time zone to that specified. 180 * The constructed object will have a local time of midnight. 181 * <p> 182 * If the object implies a chronology (such as GregorianCalendar does), 183 * then that chronology will be used, but with the time zone adjusted. 184 * Otherwise, ISO is used in the specified time zone. 185 * If the specified time zone is null, the default zone is used. 186 * Thus if a GregorianCalendar is passed in, the chronology used will 187 * be GJ, but if a Date is passed in the chronology will be ISO. 188 * <p> 189 * The recognised object types are defined in 190 * {@link org.joda.time.convert.ConverterManager ConverterManager} and 191 * include ReadableInstant, String, Calendar and Date. 192 * The String formats are described by {@link ISODateTimeFormat#dateTimeParser()}. 193 * 194 * @param instant the datetime object, null means now 195 * @param zone the time zone, null means default time zone 196 * @throws IllegalArgumentException if the instant is invalid 197 */ 198 public DateMidnight(Object instant, DateTimeZone zone) { 199 super(instant, zone); 200 } 201 202 /** 203 * Constructs an instance from an Object that represents a datetime, 204 * using the specified chronology. 205 * The constructed object will have a local time of midnight. 206 * <p> 207 * If the chronology is null, ISO in the default time zone is used. 208 * Any chronology implied by the object (such as GregorianCalendar does) 209 * is ignored. 210 * <p> 211 * The recognised object types are defined in 212 * {@link org.joda.time.convert.ConverterManager ConverterManager} and 213 * include ReadableInstant, String, Calendar and Date. 214 * The String formats are described by {@link ISODateTimeFormat#dateTimeParser()}. 215 * 216 * @param instant the datetime object, null means now 217 * @param chronology the chronology, null means ISOChronology in default zone 218 * @throws IllegalArgumentException if the instant is invalid 219 */ 220 public DateMidnight(Object instant, Chronology chronology) { 221 super(instant, DateTimeUtils.getChronology(chronology)); 222 } 223 224 //----------------------------------------------------------------------- 225 /** 226 * Constructs an instance from datetime field values 227 * using <code>ISOChronology</code> in the default time zone. 228 * The constructed object will have a local time of midnight. 229 * 230 * @param year the year 231 * @param monthOfYear the month of the year 232 * @param dayOfMonth the day of the month 233 */ 234 public DateMidnight(int year, int monthOfYear, int dayOfMonth) { 235 super(year, monthOfYear, dayOfMonth, 0, 0, 0, 0); 236 } 237 238 /** 239 * Constructs an instance from datetime field values 240 * using <code>ISOChronology</code> in the specified time zone. 241 * The constructed object will have a local time of midnight. 242 * <p> 243 * If the specified time zone is null, the default zone is used. 244 * 245 * @param year the year 246 * @param monthOfYear the month of the year 247 * @param dayOfMonth the day of the month 248 * @param zone the time zone, null means default time zone 249 */ 250 public DateMidnight(int year, int monthOfYear, int dayOfMonth, DateTimeZone zone) { 251 super(year, monthOfYear, dayOfMonth, 0, 0, 0, 0, zone); 252 } 253 254 /** 255 * Constructs an instance from datetime field values 256 * using the specified chronology. 257 * The constructed object will have a local time of midnight. 258 * <p> 259 * If the chronology is null, <code>ISOChronology</code> 260 * in the default time zone is used. 261 * 262 * @param year the year 263 * @param monthOfYear the month of the year 264 * @param dayOfMonth the day of the month 265 * @param chronology the chronology, null means ISOChronology in default zone 266 */ 267 public DateMidnight(int year, int monthOfYear, int dayOfMonth, Chronology chronology) { 268 super(year, monthOfYear, dayOfMonth, 0, 0, 0, 0, chronology); 269 } 270 271 /** 272 * Rounds the specified instant to midnight. 273 * 274 * @param instant the milliseconds from 1970-01-01T00:00:00Z to round 275 * @param chronology the chronology to use, not null 276 * @return the updated instant, rounded to midnight 277 */ 278 protected long checkInstant(long instant, Chronology chronology) { 279 return chronology.dayOfMonth().roundFloor(instant); 280 } 281 282 //----------------------------------------------------------------------- 283 /** 284 * Returns a copy of this date with a different millisecond instant. 285 * The returned object will have a local time of midnight. 286 * <p> 287 * Only the millis will change, the chronology and time zone are kept. 288 * The returned object will be either be a new instance or <code>this</code>. 289 * 290 * @param newMillis the new millis, from 1970-01-01T00:00:00Z 291 * @return a copy of this instant with different millis 292 */ 293 public DateMidnight withMillis(long newMillis) { 294 Chronology chrono = getChronology(); 295 newMillis = checkInstant(newMillis, chrono); 296 return (newMillis == getMillis() ? this : new DateMidnight(newMillis, chrono)); 297 } 298 299 /** 300 * Returns a copy of this date with a different chronology, potentially 301 * changing the day in unexpected ways. 302 * <p> 303 * This method creates a new DateMidnight using the midnight millisecond value 304 * and the new chronology. If the same or similar chronology is specified, but 305 * with a different time zone, the day may change. This occurs because the new 306 * DateMidnight rounds down the millisecond value to get to midnight, and the 307 * time zone change may result in a rounding down to a different day. 308 * <p> 309 * For example, changing time zone from London (+00:00) to Paris (+01:00) will 310 * retain the same day, but changing from Paris to London will change the day. 311 * (When its midnight in London its the same day in Paris, but when its midnight 312 * in Paris its still the previous day in London) 313 * <p> 314 * To avoid these unusual effects, use {@link #withZoneRetainFields(DateTimeZone)} 315 * to change time zones. 316 * 317 * @param newChronology the new chronology 318 * @return a copy of this instant with a different chronology 319 */ 320 public DateMidnight withChronology(Chronology newChronology) { 321 return (newChronology == getChronology() ? this : new DateMidnight(getMillis(), newChronology)); 322 } 323 324 /** 325 * Returns a copy of this date with a different time zone, preserving the day 326 * The returned object will have a local time of midnight in the new zone on 327 * the same day as the original instant. 328 * 329 * @param newZone the new time zone, null means default 330 * @return a copy of this instant with a different time zone 331 */ 332 public DateMidnight withZoneRetainFields(DateTimeZone newZone) { 333 newZone = DateTimeUtils.getZone(newZone); 334 DateTimeZone originalZone = DateTimeUtils.getZone(getZone()); 335 if (newZone == originalZone) { 336 return this; 337 } 338 339 long millis = originalZone.getMillisKeepLocal(newZone, getMillis()); 340 return new DateMidnight(millis, getChronology().withZone(newZone)); 341 } 342 343 //----------------------------------------------------------------------- 344 /** 345 * Returns a copy of this date with the partial set of fields replacing those 346 * from this instance. 347 * <p> 348 * For example, if the partial is a <code>LocalDate</code> then the date fields 349 * would be changed in the returned instance. 350 * If the partial is null, then <code>this</code> is returned. 351 * 352 * @param partial the partial set of fields to apply to this datetime, null ignored 353 * @return a copy of this datetime with a different set of fields 354 * @throws IllegalArgumentException if any value is invalid 355 */ 356 public DateMidnight withFields(ReadablePartial partial) { 357 if (partial == null) { 358 return this; 359 } 360 return withMillis(getChronology().set(partial, getMillis())); 361 } 362 363 /** 364 * Returns a copy of this date with the specified field set to a new value. 365 * <p> 366 * For example, if the field type is <code>dayOfMonth</code> then the day of month 367 * field would be changed in the returned instance. 368 * If the field type is null, then <code>this</code> is returned. 369 * <p> 370 * These three lines are equivalent: 371 * <pre> 372 * DateTime updated = dt.withField(DateTimeFieldType.dayOfMonth(), 6); 373 * DateTime updated = dt.dayOfMonth().setCopy(6); 374 * DateTime updated = dt.property(DateTimeFieldType.dayOfMonth()).setCopy(6); 375 * </pre> 376 * 377 * @param fieldType the field type to set, not null 378 * @param value the value to set 379 * @return a copy of this datetime with the field set 380 * @throws IllegalArgumentException if the value is null or invalid 381 */ 382 public DateMidnight withField(DateTimeFieldType fieldType, int value) { 383 if (fieldType == null) { 384 throw new IllegalArgumentException("Field must not be null"); 385 } 386 long instant = fieldType.getField(getChronology()).set(getMillis(), value); 387 return withMillis(instant); 388 } 389 390 /** 391 * Returns a copy of this date with the value of the specified field increased. 392 * <p> 393 * If the addition is zero or the field is null, then <code>this</code> is returned. 394 * <p> 395 * These three lines are equivalent: 396 * <pre> 397 * DateMidnight added = dt.withFieldAdded(DateTimeFieldType.year(), 6); 398 * DateMidnight added = dt.plusYears(6); 399 * DateMidnight added = dt.year().addToCopy(6); 400 * </pre> 401 * 402 * @param fieldType the field type to add to, not null 403 * @param amount the amount to add 404 * @return a copy of this datetime with the field updated 405 * @throws IllegalArgumentException if the value is null or invalid 406 * @throws ArithmeticException if the new datetime exceeds the capacity of a long 407 */ 408 public DateMidnight withFieldAdded(DurationFieldType fieldType, int amount) { 409 if (fieldType == null) { 410 throw new IllegalArgumentException("Field must not be null"); 411 } 412 if (amount == 0) { 413 return this; 414 } 415 long instant = fieldType.getField(getChronology()).add(getMillis(), amount); 416 return withMillis(instant); 417 } 418 419 //----------------------------------------------------------------------- 420 /** 421 * Returns a copy of this date with the specified duration added. 422 * <p> 423 * If the addition is zero, then <code>this</code> is returned. 424 * 425 * @param durationToAdd the duration to add to this one 426 * @param scalar the amount of times to add, such as -1 to subtract once 427 * @return a copy of this datetime with the duration added 428 * @throws ArithmeticException if the new datetime exceeds the capacity of a long 429 */ 430 public DateMidnight withDurationAdded(long durationToAdd, int scalar) { 431 if (durationToAdd == 0 || scalar == 0) { 432 return this; 433 } 434 long instant = getChronology().add(getMillis(), durationToAdd, scalar); 435 return withMillis(instant); 436 } 437 438 /** 439 * Returns a copy of this date with the specified duration added. 440 * <p> 441 * If the addition is zero, then <code>this</code> is returned. 442 * 443 * @param durationToAdd the duration to add to this one, null means zero 444 * @param scalar the amount of times to add, such as -1 to subtract once 445 * @return a copy of this datetime with the duration added 446 * @throws ArithmeticException if the new datetime exceeds the capacity of a long 447 */ 448 public DateMidnight withDurationAdded(ReadableDuration durationToAdd, int scalar) { 449 if (durationToAdd == null || scalar == 0) { 450 return this; 451 } 452 return withDurationAdded(durationToAdd.getMillis(), scalar); 453 } 454 455 /** 456 * Returns a copy of this date with the specified period added. 457 * <p> 458 * If the addition is zero, then <code>this</code> is returned. 459 * <p> 460 * This method is typically used to add multiple copies of complex 461 * period instances. Adding one field is best achieved using methods 462 * like {@link #withFieldAdded(DurationFieldType, int)} 463 * or {@link #plusYears(int)}. 464 * 465 * @param period the period to add to this one, null means zero 466 * @param scalar the amount of times to add, such as -1 to subtract once 467 * @return a copy of this datetime with the period added 468 * @throws ArithmeticException if the new datetime exceeds the capacity of a long 469 */ 470 public DateMidnight withPeriodAdded(ReadablePeriod period, int scalar) { 471 if (period == null || scalar == 0) { 472 return this; 473 } 474 long instant = getChronology().add(period, getMillis(), scalar); 475 return withMillis(instant); 476 } 477 478 //----------------------------------------------------------------------- 479 /** 480 * Returns a copy of this date with the specified duration added. 481 * <p> 482 * If the amount is zero, then <code>this</code> is returned. 483 * 484 * @param duration the duration, in millis, to add to this one 485 * @return a copy of this datetime with the duration added 486 * @throws ArithmeticException if the new datetime exceeds the capacity of a long 487 */ 488 public DateMidnight plus(long duration) { 489 return withDurationAdded(duration, 1); 490 } 491 492 /** 493 * Returns a copy of this date with the specified duration added. 494 * <p> 495 * If the amount is zero or null, then <code>this</code> is returned. 496 * 497 * @param duration the duration to add to this one, null means zero 498 * @return a copy of this datetime with the duration added 499 * @throws ArithmeticException if the new datetime exceeds the capacity of a long 500 */ 501 public DateMidnight plus(ReadableDuration duration) { 502 return withDurationAdded(duration, 1); 503 } 504 505 /** 506 * Returns a copy of this date with the specified period added. 507 * <p> 508 * If the amount is zero or null, then <code>this</code> is returned. 509 * <p> 510 * This method is typically used to add complex period instances. 511 * Adding one field is best achieved using methods 512 * like {@link #plusYears(int)}. 513 * 514 * @param period the duration to add to this one, null means zero 515 * @return a copy of this datetime with the period added 516 * @throws ArithmeticException if the new datetime exceeds the capacity of a long 517 */ 518 public DateMidnight plus(ReadablePeriod period) { 519 return withPeriodAdded(period, 1); 520 } 521 522 //----------------------------------------------------------------------- 523 /** 524 * Returns a copy of this date plus the specified number of years. 525 * <p> 526 * This datetime instance is immutable and unaffected by this method call. 527 * <p> 528 * The following three lines are identical in effect: 529 * <pre> 530 * DateMidnight added = dt.plusYears(6); 531 * DateMidnight added = dt.plus(Period.years(6)); 532 * DateMidnight added = dt.withFieldAdded(DurationFieldType.years(), 6); 533 * </pre> 534 * 535 * @param years the amount of years to add, may be negative 536 * @return the new datetime plus the increased years 537 * @since 1.1 538 */ 539 public DateMidnight plusYears(int years) { 540 if (years == 0) { 541 return this; 542 } 543 long instant = getChronology().years().add(getMillis(), years); 544 return withMillis(instant); 545 } 546 547 /** 548 * Returns a copy of this date plus the specified number of months. 549 * <p> 550 * This datetime instance is immutable and unaffected by this method call. 551 * <p> 552 * The following three lines are identical in effect: 553 * <pre> 554 * DateMidnight added = dt.plusMonths(6); 555 * DateMidnight added = dt.plus(Period.months(6)); 556 * DateMidnight added = dt.withFieldAdded(DurationFieldType.months(), 6); 557 * </pre> 558 * 559 * @param months the amount of months to add, may be negative 560 * @return the new datetime plus the increased months 561 * @since 1.1 562 */ 563 public DateMidnight plusMonths(int months) { 564 if (months == 0) { 565 return this; 566 } 567 long instant = getChronology().months().add(getMillis(), months); 568 return withMillis(instant); 569 } 570 571 /** 572 * Returns a copy of this date plus the specified number of weeks. 573 * <p> 574 * This datetime instance is immutable and unaffected by this method call. 575 * <p> 576 * The following three lines are identical in effect: 577 * <pre> 578 * DateMidnight added = dt.plusWeeks(6); 579 * DateMidnight added = dt.plus(Period.weeks(6)); 580 * DateMidnight added = dt.withFieldAdded(DurationFieldType.weeks(), 6); 581 * </pre> 582 * 583 * @param weeks the amount of weeks to add, may be negative 584 * @return the new datetime plus the increased weeks 585 * @since 1.1 586 */ 587 public DateMidnight plusWeeks(int weeks) { 588 if (weeks == 0) { 589 return this; 590 } 591 long instant = getChronology().weeks().add(getMillis(), weeks); 592 return withMillis(instant); 593 } 594 595 /** 596 * Returns a copy of this date plus the specified number of days. 597 * <p> 598 * This datetime instance is immutable and unaffected by this method call. 599 * <p> 600 * The following three lines are identical in effect: 601 * <pre> 602 * DateMidnight added = dt.plusDays(6); 603 * DateMidnight added = dt.plus(Period.days(6)); 604 * DateMidnight added = dt.withFieldAdded(DurationFieldType.days(), 6); 605 * </pre> 606 * 607 * @param days the amount of days to add, may be negative 608 * @return the new datetime plus the increased days 609 * @since 1.1 610 */ 611 public DateMidnight plusDays(int days) { 612 if (days == 0) { 613 return this; 614 } 615 long instant = getChronology().days().add(getMillis(), days); 616 return withMillis(instant); 617 } 618 619 //----------------------------------------------------------------------- 620 /** 621 * Returns a copy of this date with the specified duration taken away. 622 * <p> 623 * If the amount is zero or null, then <code>this</code> is returned. 624 * 625 * @param duration the duration, in millis, to reduce this instant by 626 * @return a copy of this datetime with the duration taken away 627 * @throws ArithmeticException if the new datetime exceeds the capacity of a long 628 */ 629 public DateMidnight minus(long duration) { 630 return withDurationAdded(duration, -1); 631 } 632 633 /** 634 * Returns a copy of this date with the specified duration taken away. 635 * <p> 636 * If the amount is zero or null, then <code>this</code> is returned. 637 * 638 * @param duration the duration to reduce this instant by 639 * @return a copy of this datetime with the duration taken away 640 * @throws ArithmeticException if the new datetime exceeds the capacity of a long 641 */ 642 public DateMidnight minus(ReadableDuration duration) { 643 return withDurationAdded(duration, -1); 644 } 645 646 /** 647 * Returns a copy of this date with the specified period taken away. 648 * <p> 649 * If the amount is zero or null, then <code>this</code> is returned. 650 * <p> 651 * This method is typically used to subtract complex period instances. 652 * Subtracting one field is best achieved using methods 653 * like {@link #minusYears(int)}. 654 * 655 * @param period the period to reduce this instant by 656 * @return a copy of this datetime with the period taken away 657 * @throws ArithmeticException if the new datetime exceeds the capacity of a long 658 */ 659 public DateMidnight minus(ReadablePeriod period) { 660 return withPeriodAdded(period, -1); 661 } 662 663 //----------------------------------------------------------------------- 664 /** 665 * Returns a copy of this date minus the specified number of years. 666 * <p> 667 * This datetime instance is immutable and unaffected by this method call. 668 * <p> 669 * The following three lines are identical in effect: 670 * <pre> 671 * DateTime subtracted = dt.minusYears(6); 672 * DateTime subtracted = dt.minus(Period.years(6)); 673 * DateTime subtracted = dt.withFieldAdded(DurationFieldType.years(), -6); 674 * </pre> 675 * 676 * @param years the amount of years to subtract, may be negative 677 * @return the new datetime minus the increased years 678 * @since 1.1 679 */ 680 public DateMidnight minusYears(int years) { 681 if (years == 0) { 682 return this; 683 } 684 long instant = getChronology().years().subtract(getMillis(), years); 685 return withMillis(instant); 686 } 687 688 /** 689 * Returns a copy of this date minus the specified number of months. 690 * <p> 691 * This datetime instance is immutable and unaffected by this method call. 692 * <p> 693 * The following three lines are identical in effect: 694 * <pre> 695 * DateMidnight subtracted = dt.minusMonths(6); 696 * DateMidnight subtracted = dt.minus(Period.months(6)); 697 * DateMidnight subtracted = dt.withFieldAdded(DurationFieldType.months(), -6); 698 * </pre> 699 * 700 * @param months the amount of months to subtract, may be negative 701 * @return the new datetime minus the increased months 702 * @since 1.1 703 */ 704 public DateMidnight minusMonths(int months) { 705 if (months == 0) { 706 return this; 707 } 708 long instant = getChronology().months().subtract(getMillis(), months); 709 return withMillis(instant); 710 } 711 712 /** 713 * Returns a copy of this date minus the specified number of weeks. 714 * <p> 715 * This datetime instance is immutable and unaffected by this method call. 716 * <p> 717 * The following three lines are identical in effect: 718 * <pre> 719 * DateMidnight subtracted = dt.minusWeeks(6); 720 * DateMidnight subtracted = dt.minus(Period.weeks(6)); 721 * DateMidnight subtracted = dt.withFieldAdded(DurationFieldType.weeks(), -6); 722 * </pre> 723 * 724 * @param weeks the amount of weeks to subtract, may be negative 725 * @return the new datetime minus the increased weeks 726 * @since 1.1 727 */ 728 public DateMidnight minusWeeks(int weeks) { 729 if (weeks == 0) { 730 return this; 731 } 732 long instant = getChronology().weeks().subtract(getMillis(), weeks); 733 return withMillis(instant); 734 } 735 736 /** 737 * Returns a copy of this date minus the specified number of days. 738 * <p> 739 * This datetime instance is immutable and unaffected by this method call. 740 * <p> 741 * The following three lines are identical in effect: 742 * <pre> 743 * DateMidnight subtracted = dt.minusDays(6); 744 * DateMidnight subtracted = dt.minus(Period.days(6)); 745 * DateMidnight subtracted = dt.withFieldAdded(DurationFieldType.days(), -6); 746 * </pre> 747 * 748 * @param days the amount of days to subtract, may be negative 749 * @return the new datetime minus the increased days 750 * @since 1.1 751 */ 752 public DateMidnight minusDays(int days) { 753 if (days == 0) { 754 return this; 755 } 756 long instant = getChronology().days().subtract(getMillis(), days); 757 return withMillis(instant); 758 } 759 760 //----------------------------------------------------------------------- 761 /** 762 * Gets the property object for the specified type, which contains many useful methods. 763 * 764 * @param type the field type to get the chronology for 765 * @return the property object 766 * @throws IllegalArgumentException if the field is null or unsupported 767 */ 768 public Property property(DateTimeFieldType type) { 769 if (type == null) { 770 throw new IllegalArgumentException("The DateTimeFieldType must not be null"); 771 } 772 DateTimeField field = type.getField(getChronology()); 773 if (field.isSupported() == false) { 774 throw new IllegalArgumentException("Field '" + type + "' is not supported"); 775 } 776 return new Property(this, field); 777 } 778 779 //----------------------------------------------------------------------- 780 /** 781 * Converts this object to a <code>YearMonthDay</code> using the 782 * same date and chronology. 783 * 784 * @return a YearMonthDay using the same millis and chronology 785 * @deprecated Use LocalDate instead of YearMonthDay 786 */ 787 public YearMonthDay toYearMonthDay() { 788 return new YearMonthDay(getMillis(), getChronology()); 789 } 790 791 /** 792 * Converts this object to a <code>LocalDate</code> with the 793 * same date and chronology. 794 * 795 * @return a LocalDate with the same date and chronology 796 * @since 1.3 797 */ 798 public LocalDate toLocalDate() { 799 return new LocalDate(getMillis(), getChronology()); 800 } 801 802 /** 803 * Converts this object to an <code>Interval</code> encompassing 804 * the whole of this day. 805 * <p> 806 * The interval starts at midnight 00:00 and ends at 00:00 the following day, 807 * (which is not included in the interval, as intervals are half-open). 808 * 809 * @return an interval over the day 810 */ 811 public Interval toInterval() { 812 Chronology chrono = getChronology(); 813 long start = getMillis(); 814 long end = DurationFieldType.days().getField(chrono).add(start, 1); 815 return new Interval(start, end, chrono); 816 } 817 818 //----------------------------------------------------------------------- 819 /** 820 * Returns a copy of this date with the era field updated. 821 * <p> 822 * DateMidnight is immutable, so there are no set methods. 823 * Instead, this method returns a new instance with the value of 824 * era changed. 825 * 826 * @param era the era to set 827 * @return a copy of this object with the field set 828 * @throws IllegalArgumentException if the value is invalid 829 * @since 1.3 830 */ 831 public DateMidnight withEra(int era) { 832 return withMillis(getChronology().era().set(getMillis(), era)); 833 } 834 835 /** 836 * Returns a copy of this date with the century of era field updated. 837 * <p> 838 * DateMidnight is immutable, so there are no set methods. 839 * Instead, this method returns a new instance with the value of 840 * century of era changed. 841 * 842 * @param centuryOfEra the centurey of era to set 843 * @return a copy of this object with the field set 844 * @throws IllegalArgumentException if the value is invalid 845 * @since 1.3 846 */ 847 public DateMidnight withCenturyOfEra(int centuryOfEra) { 848 return withMillis(getChronology().centuryOfEra().set(getMillis(), centuryOfEra)); 849 } 850 851 /** 852 * Returns a copy of this date with the year of era field updated. 853 * <p> 854 * DateMidnight is immutable, so there are no set methods. 855 * Instead, this method returns a new instance with the value of 856 * year of era changed. 857 * 858 * @param yearOfEra the year of era to set 859 * @return a copy of this object with the field set 860 * @throws IllegalArgumentException if the value is invalid 861 * @since 1.3 862 */ 863 public DateMidnight withYearOfEra(int yearOfEra) { 864 return withMillis(getChronology().yearOfEra().set(getMillis(), yearOfEra)); 865 } 866 867 /** 868 * Returns a copy of this date with the year of century field updated. 869 * <p> 870 * DateMidnight is immutable, so there are no set methods. 871 * Instead, this method returns a new instance with the value of 872 * year of century changed. 873 * 874 * @param yearOfCentury the year of century to set 875 * @return a copy of this object with the field set 876 * @throws IllegalArgumentException if the value is invalid 877 * @since 1.3 878 */ 879 public DateMidnight withYearOfCentury(int yearOfCentury) { 880 return withMillis(getChronology().yearOfCentury().set(getMillis(), yearOfCentury)); 881 } 882 883 /** 884 * Returns a copy of this date with the year field updated. 885 * <p> 886 * DateMidnight is immutable, so there are no set methods. 887 * Instead, this method returns a new instance with the value of 888 * year changed. 889 * 890 * @param year the year to set 891 * @return a copy of this object with the field set 892 * @throws IllegalArgumentException if the value is invalid 893 * @since 1.3 894 */ 895 public DateMidnight withYear(int year) { 896 return withMillis(getChronology().year().set(getMillis(), year)); 897 } 898 899 /** 900 * Returns a copy of this date with the weekyear field updated. 901 * <p> 902 * DateMidnight is immutable, so there are no set methods. 903 * Instead, this method returns a new instance with the value of 904 * weekyear changed. 905 * 906 * @param weekyear the weekyear to set 907 * @return a copy of this object with the field set 908 * @throws IllegalArgumentException if the value is invalid 909 * @since 1.3 910 */ 911 public DateMidnight withWeekyear(int weekyear) { 912 return withMillis(getChronology().weekyear().set(getMillis(), weekyear)); 913 } 914 915 /** 916 * Returns a copy of this date with the month of year field updated. 917 * <p> 918 * DateMidnight is immutable, so there are no set methods. 919 * Instead, this method returns a new instance with the value of 920 * month of year changed. 921 * 922 * @param monthOfYear the month of year to set 923 * @return a copy of this object with the field set 924 * @throws IllegalArgumentException if the value is invalid 925 * @since 1.3 926 */ 927 public DateMidnight withMonthOfYear(int monthOfYear) { 928 return withMillis(getChronology().monthOfYear().set(getMillis(), monthOfYear)); 929 } 930 931 /** 932 * Returns a copy of this date with the week of weekyear field updated. 933 * <p> 934 * DateMidnight is immutable, so there are no set methods. 935 * Instead, this method returns a new instance with the value of 936 * week of weekyear changed. 937 * 938 * @param weekOfWeekyear the week of weekyear to set 939 * @return a copy of this object with the field set 940 * @throws IllegalArgumentException if the value is invalid 941 * @since 1.3 942 */ 943 public DateMidnight withWeekOfWeekyear(int weekOfWeekyear) { 944 return withMillis(getChronology().weekOfWeekyear().set(getMillis(), weekOfWeekyear)); 945 } 946 947 /** 948 * Returns a copy of this date with the day of year field updated. 949 * <p> 950 * DateMidnight is immutable, so there are no set methods. 951 * Instead, this method returns a new instance with the value of 952 * day of year changed. 953 * 954 * @param dayOfYear the day of year to set 955 * @return a copy of this object with the field set 956 * @throws IllegalArgumentException if the value is invalid 957 * @since 1.3 958 */ 959 public DateMidnight withDayOfYear(int dayOfYear) { 960 return withMillis(getChronology().dayOfYear().set(getMillis(), dayOfYear)); 961 } 962 963 /** 964 * Returns a copy of this date with the day of month field updated. 965 * <p> 966 * DateMidnight is immutable, so there are no set methods. 967 * Instead, this method returns a new instance with the value of 968 * day of month changed. 969 * 970 * @param dayOfMonth the day of month to set 971 * @return a copy of this object with the field set 972 * @throws IllegalArgumentException if the value is invalid 973 * @since 1.3 974 */ 975 public DateMidnight withDayOfMonth(int dayOfMonth) { 976 return withMillis(getChronology().dayOfMonth().set(getMillis(), dayOfMonth)); 977 } 978 979 /** 980 * Returns a copy of this date with the day of week field updated. 981 * <p> 982 * DateMidnight is immutable, so there are no set methods. 983 * Instead, this method returns a new instance with the value of 984 * day of week changed. 985 * 986 * @param dayOfWeek the day of week to set 987 * @return a copy of this object with the field set 988 * @throws IllegalArgumentException if the value is invalid 989 * @since 1.3 990 */ 991 public DateMidnight withDayOfWeek(int dayOfWeek) { 992 return withMillis(getChronology().dayOfWeek().set(getMillis(), dayOfWeek)); 993 } 994 995 // Date properties 996 //----------------------------------------------------------------------- 997 /** 998 * Get the era property which provides access to advanced functionality. 999 * 1000 * @return the era property 1001 */ 1002 public Property era() { 1003 return new Property(this, getChronology().era()); 1004 } 1005 1006 /** 1007 * Get the century of era property which provides access to advanced functionality. 1008 * 1009 * @return the year of era property 1010 */ 1011 public Property centuryOfEra() { 1012 return new Property(this, getChronology().centuryOfEra()); 1013 } 1014 1015 /** 1016 * Get the year of century property which provides access to advanced functionality. 1017 * 1018 * @return the year of era property 1019 */ 1020 public Property yearOfCentury() { 1021 return new Property(this, getChronology().yearOfCentury()); 1022 } 1023 1024 /** 1025 * Get the year of era property which provides access to advanced functionality. 1026 * 1027 * @return the year of era property 1028 */ 1029 public Property yearOfEra() { 1030 return new Property(this, getChronology().yearOfEra()); 1031 } 1032 1033 /** 1034 * Get the year property which provides access to advanced functionality. 1035 * 1036 * @return the year property 1037 */ 1038 public Property year() { 1039 return new Property(this, getChronology().year()); 1040 } 1041 1042 /** 1043 * Get the year of a week based year property which provides access to advanced functionality. 1044 * 1045 * @return the year of a week based year property 1046 */ 1047 public Property weekyear() { 1048 return new Property(this, getChronology().weekyear()); 1049 } 1050 1051 /** 1052 * Get the month of year property which provides access to advanced functionality. 1053 * 1054 * @return the month of year property 1055 */ 1056 public Property monthOfYear() { 1057 return new Property(this, getChronology().monthOfYear()); 1058 } 1059 1060 /** 1061 * Get the week of a week based year property which provides access to advanced functionality. 1062 * 1063 * @return the week of a week based year property 1064 */ 1065 public Property weekOfWeekyear() { 1066 return new Property(this, getChronology().weekOfWeekyear()); 1067 } 1068 1069 /** 1070 * Get the day of year property which provides access to advanced functionality. 1071 * 1072 * @return the day of year property 1073 */ 1074 public Property dayOfYear() { 1075 return new Property(this, getChronology().dayOfYear()); 1076 } 1077 1078 /** 1079 * Get the day of month property which provides access to advanced functionality. 1080 * 1081 * @return the day of month property 1082 */ 1083 public Property dayOfMonth() { 1084 return new Property(this, getChronology().dayOfMonth()); 1085 } 1086 1087 /** 1088 * Get the day of week property which provides access to advanced functionality. 1089 * 1090 * @return the day of week property 1091 */ 1092 public Property dayOfWeek() { 1093 return new Property(this, getChronology().dayOfWeek()); 1094 } 1095 1096 //----------------------------------------------------------------------- 1097 /** 1098 * DateMidnight.Property binds a DateMidnight to a DateTimeField allowing powerful 1099 * datetime functionality to be easily accessed. 1100 * <p> 1101 * The simplest use of this class is as an alternative get method, here used to 1102 * get the year '1972' (as an int) and the month 'December' (as a String). 1103 * <pre> 1104 * DateMidnight dt = new DateMidnight(1972, 12, 3); 1105 * int year = dt.year().get(); 1106 * String monthStr = dt.monthOfYear().getAsText(); 1107 * </pre> 1108 * <p> 1109 * Methods are also provided that allow date modification. These return new instances 1110 * of DateMidnight - they do not modify the original. The example below yields two 1111 * independent immutable date objects 20 years apart. 1112 * <pre> 1113 * DateMidnight dt = new DateMidnight(1972, 12, 3); 1114 * DateMidnight dt20 = dt.year().addToCopy(20); 1115 * </pre> 1116 * Serious modification of dates (ie. more than just changing one or two fields) 1117 * should use the {@link org.joda.time.MutableDateTime MutableDateTime} class. 1118 * <p> 1119 * DateMidnight.Property itself is thread-safe and immutable. 1120 * 1121 * @author Stephen Colebourne 1122 * @author Brian S O'Neill 1123 * @since 1.0 1124 */ 1125 public static final class Property extends AbstractReadableInstantFieldProperty { 1126 1127 /** Serialization lock */ 1128 private static final long serialVersionUID = 257629620L; 1129 1130 /** The instant this property is working against */ 1131 private DateMidnight iInstant; 1132 /** The field this property is working against */ 1133 private DateTimeField iField; 1134 1135 /** 1136 * Constructor. 1137 * 1138 * @param instant the instant to set 1139 * @param field the field to use 1140 */ 1141 Property(DateMidnight instant, DateTimeField field) { 1142 super(); 1143 iInstant = instant; 1144 iField = field; 1145 } 1146 1147 /** 1148 * Writes the property in a safe serialization format. 1149 */ 1150 private void writeObject(ObjectOutputStream oos) throws IOException { 1151 oos.writeObject(iInstant); 1152 oos.writeObject(iField.getType()); 1153 } 1154 1155 /** 1156 * Reads the property from a safe serialization format. 1157 */ 1158 private void readObject(ObjectInputStream oos) throws IOException, ClassNotFoundException { 1159 iInstant = (DateMidnight) oos.readObject(); 1160 DateTimeFieldType type = (DateTimeFieldType) oos.readObject(); 1161 iField = type.getField(iInstant.getChronology()); 1162 } 1163 1164 //----------------------------------------------------------------------- 1165 /** 1166 * Gets the field being used. 1167 * 1168 * @return the field 1169 */ 1170 public DateTimeField getField() { 1171 return iField; 1172 } 1173 1174 /** 1175 * Gets the milliseconds of the datetime that this property is linked to. 1176 * 1177 * @return the milliseconds 1178 */ 1179 protected long getMillis() { 1180 return iInstant.getMillis(); 1181 } 1182 1183 /** 1184 * Gets the chronology of the datetime that this property is linked to. 1185 * 1186 * @return the chronology 1187 * @since 1.4 1188 */ 1189 protected Chronology getChronology() { 1190 return iInstant.getChronology(); 1191 } 1192 1193 /** 1194 * Gets the datetime being used. 1195 * 1196 * @return the datetime 1197 */ 1198 public DateMidnight getDateMidnight() { 1199 return iInstant; 1200 } 1201 1202 //----------------------------------------------------------------------- 1203 /** 1204 * Adds to this field in a copy of this DateMidnight. 1205 * <p> 1206 * The DateMidnight attached to this property is unchanged by this call. 1207 * This operation is faster than converting a DateMidnight to a MutableDateTime 1208 * and back again when setting one field. When setting multiple fields, 1209 * it is generally quicker to make the conversion to MutableDateTime. 1210 * 1211 * @param value the value to add to the field in the copy 1212 * @return a copy of the DateMidnight with the field value changed 1213 * @throws IllegalArgumentException if the value isn't valid 1214 */ 1215 public DateMidnight addToCopy(int value) { 1216 return iInstant.withMillis(iField.add(iInstant.getMillis(), value)); 1217 } 1218 1219 /** 1220 * Adds to this field in a copy of this DateMidnight. 1221 * <p> 1222 * The DateMidnight attached to this property is unchanged by this call. 1223 * This operation is faster than converting a DateMidnight to a MutableDateTime 1224 * and back again when setting one field. When setting multiple fields, 1225 * it is generally quicker to make the conversion to MutableDateTime. 1226 * 1227 * @param value the value to add to the field in the copy 1228 * @return a copy of the DateMidnight with the field value changed 1229 * @throws IllegalArgumentException if the value isn't valid 1230 */ 1231 public DateMidnight addToCopy(long value) { 1232 return iInstant.withMillis(iField.add(iInstant.getMillis(), value)); 1233 } 1234 1235 /** 1236 * Adds to this field, possibly wrapped, in a copy of this DateMidnight. 1237 * A wrapped operation only changes this field. 1238 * Thus 31st January addWrapField one day goes to the 1st January. 1239 * <p> 1240 * The DateMidnight attached to this property is unchanged by this call. 1241 * This operation is faster than converting a DateMidnight to a MutableDateTime 1242 * and back again when setting one field. When setting multiple fields, 1243 * it is generally quicker to make the conversion to MutableDateTime. 1244 * 1245 * @param value the value to add to the field in the copy 1246 * @return a copy of the DateMidnight with the field value changed 1247 * @throws IllegalArgumentException if the value isn't valid 1248 */ 1249 public DateMidnight addWrapFieldToCopy(int value) { 1250 return iInstant.withMillis(iField.addWrapField(iInstant.getMillis(), value)); 1251 } 1252 1253 //----------------------------------------------------------------------- 1254 /** 1255 * Sets this field in a copy of the DateMidnight. 1256 * <p> 1257 * The DateMidnight attached to this property is unchanged by this call. 1258 * This operation is faster than converting a DateMidnight to a MutableDateTime 1259 * and back again when setting one field. When setting multiple fields, 1260 * it is generally quicker to make the conversion to MutableDateTime. 1261 * 1262 * @param value the value to set the field in the copy to 1263 * @return a copy of the DateMidnight with the field value changed 1264 * @throws IllegalArgumentException if the value isn't valid 1265 */ 1266 public DateMidnight setCopy(int value) { 1267 return iInstant.withMillis(iField.set(iInstant.getMillis(), value)); 1268 } 1269 1270 /** 1271 * Sets this field in a copy of the DateMidnight to a parsed text value. 1272 * <p> 1273 * The DateMidnight attached to this property is unchanged by this call. 1274 * This operation is faster than converting a DateMidnight to a MutableDateTime 1275 * and back again when setting one field. When setting multiple fields, 1276 * it is generally quicker to make the conversion to MutableDateTime. 1277 * 1278 * @param text the text value to set 1279 * @param locale optional locale to use for selecting a text symbol 1280 * @return a copy of the DateMidnight with the field value changed 1281 * @throws IllegalArgumentException if the text value isn't valid 1282 */ 1283 public DateMidnight setCopy(String text, Locale locale) { 1284 return iInstant.withMillis(iField.set(iInstant.getMillis(), text, locale)); 1285 } 1286 1287 /** 1288 * Sets this field in a copy of the DateMidnight to a parsed text value. 1289 * <p> 1290 * The DateMidnight attached to this property is unchanged by this call. 1291 * This operation is faster than converting a DateMidnight to a MutableDateTime 1292 * and back again when setting one field. When setting multiple fields, 1293 * it is generally quicker to make the conversion to MutableDateTime. 1294 * 1295 * @param text the text value to set 1296 * @return a copy of the DateMidnight with the field value changed 1297 * @throws IllegalArgumentException if the text value isn't valid 1298 */ 1299 public DateMidnight setCopy(String text) { 1300 return setCopy(text, null); 1301 } 1302 1303 //----------------------------------------------------------------------- 1304 /** 1305 * Returns a new DateMidnight with this field set to the maximum value 1306 * for this field. 1307 * <p> 1308 * This operation is useful for obtaining a DateTime on the last day 1309 * of the month, as month lengths vary. 1310 * <pre> 1311 * DateMidnight lastDayOfMonth = dt.dayOfMonth().withMaximumValue(); 1312 * </pre> 1313 * <p> 1314 * The DateMidnight attached to this property is unchanged by this call. 1315 * 1316 * @return a copy of the DateMidnight with this field set to its maximum 1317 * @since 1.2 1318 */ 1319 public DateMidnight withMaximumValue() { 1320 return setCopy(getMaximumValue()); 1321 } 1322 1323 /** 1324 * Returns a new DateMidnight with this field set to the minimum value 1325 * for this field. 1326 * <p> 1327 * The DateMidnight attached to this property is unchanged by this call. 1328 * 1329 * @return a copy of the DateMidnight with this field set to its minimum 1330 * @since 1.2 1331 */ 1332 public DateMidnight withMinimumValue() { 1333 return setCopy(getMinimumValue()); 1334 } 1335 1336 //----------------------------------------------------------------------- 1337 /** 1338 * Rounds to the lowest whole unit of this field on a copy of this DateMidnight. 1339 * 1340 * @return a copy of the DateMidnight with the field value changed 1341 */ 1342 public DateMidnight roundFloorCopy() { 1343 return iInstant.withMillis(iField.roundFloor(iInstant.getMillis())); 1344 } 1345 1346 /** 1347 * Rounds to the highest whole unit of this field on a copy of this DateMidnight. 1348 * 1349 * @return a copy of the DateMidnight with the field value changed 1350 */ 1351 public DateMidnight roundCeilingCopy() { 1352 return iInstant.withMillis(iField.roundCeiling(iInstant.getMillis())); 1353 } 1354 1355 /** 1356 * Rounds to the nearest whole unit of this field on a copy of this DateMidnight, 1357 * favoring the floor if halfway. 1358 * 1359 * @return a copy of the DateMidnight with the field value changed 1360 */ 1361 public DateMidnight roundHalfFloorCopy() { 1362 return iInstant.withMillis(iField.roundHalfFloor(iInstant.getMillis())); 1363 } 1364 1365 /** 1366 * Rounds to the nearest whole unit of this field on a copy of this DateMidnight, 1367 * favoring the ceiling if halfway. 1368 * 1369 * @return a copy of the DateMidnight with the field value changed 1370 */ 1371 public DateMidnight roundHalfCeilingCopy() { 1372 return iInstant.withMillis(iField.roundHalfCeiling(iInstant.getMillis())); 1373 } 1374 1375 /** 1376 * Rounds to the nearest whole unit of this field on a copy of this DateMidnight. 1377 * If halfway, the ceiling is favored over the floor only if it makes this field's value even. 1378 * 1379 * @return a copy of the DateMidnight with the field value changed 1380 */ 1381 public DateMidnight roundHalfEvenCopy() { 1382 return iInstant.withMillis(iField.roundHalfEven(iInstant.getMillis())); 1383 } 1384 1385 } 1386 }