001 /* 002 * Copyright 2001-2011 Stephen Colebourne 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.joda.time; 017 018 import java.io.Serializable; 019 import java.util.Calendar; 020 import java.util.Date; 021 import java.util.Locale; 022 023 import org.joda.time.base.BasePartial; 024 import org.joda.time.chrono.ISOChronology; 025 import org.joda.time.field.AbstractPartialFieldProperty; 026 import org.joda.time.field.FieldUtils; 027 import org.joda.time.format.ISODateTimeFormat; 028 029 /** 030 * YearMonthDay is an immutable partial supporting the year, monthOfYear 031 * and dayOfMonth fields. 032 * <p> 033 * NOTE: This class only supports the three fields listed above. Thus, you 034 * cannot query the dayOfWeek or centuryOfEra fields for example. 035 * The new <code>LocalDate</code> class removes this restriction. 036 * <p> 037 * Calculations on YearMonthDay are performed using a {@link Chronology}. 038 * This chronology is set to be in the UTC time zone for all calculations. 039 * <p> 040 * Each individual field can be queried in two ways: 041 * <ul> 042 * <li><code>getMonthOfYear()</code> 043 * <li><code>monthOfYear().get()</code> 044 * </ul> 045 * The second technique also provides access to other useful methods on the 046 * field: 047 * <ul> 048 * <li>numeric value - <code>monthOfYear().get()</code> 049 * <li>text value - <code>monthOfYear().getAsText()</code> 050 * <li>short text value - <code>monthOfYear().getAsShortText()</code> 051 * <li>maximum/minimum values - <code>monthOfYear().getMaximumValue()</code> 052 * <li>add/subtract - <code>monthOfYear().addToCopy()</code> 053 * <li>set - <code>monthOfYear().setCopy()</code> 054 * </ul> 055 * <p> 056 * YearMonthDay is thread-safe and immutable, provided that the Chronology is as well. 057 * All standard Chronology classes supplied are thread-safe and immutable. 058 * 059 * @author Stephen Colebourne 060 * @since 1.0 061 * @deprecated Use LocalDate which has a much better internal implementation and 062 * has been available since 1.3 063 */ 064 @Deprecated 065 public final class YearMonthDay 066 extends BasePartial 067 implements ReadablePartial, Serializable { 068 069 /** Serialization version */ 070 private static final long serialVersionUID = 797544782896179L; 071 /** The singleton set of field types */ 072 private static final DateTimeFieldType[] FIELD_TYPES = new DateTimeFieldType[] { 073 DateTimeFieldType.year(), 074 DateTimeFieldType.monthOfYear(), 075 DateTimeFieldType.dayOfMonth(), 076 }; 077 078 /** The index of the year field in the field array */ 079 public static final int YEAR = 0; 080 /** The index of the monthOfYear field in the field array */ 081 public static final int MONTH_OF_YEAR = 1; 082 /** The index of the dayOfMonth field in the field array */ 083 public static final int DAY_OF_MONTH = 2; 084 085 //----------------------------------------------------------------------- 086 /** 087 * Constructs a YearMonthDay from a <code>java.util.Calendar</code> 088 * using exactly the same field values avoiding any time zone effects. 089 * <p> 090 * Each field is queried from the Calendar and assigned to the YearMonthDay. 091 * This is useful if you have been using the Calendar as a local date, 092 * ignoing the zone. 093 * <p> 094 * This factory method ignores the type of the calendar and always 095 * creates a YearMonthDay with ISO chronology. It is expected that you 096 * will only pass in instances of <code>GregorianCalendar</code> however 097 * this is not validated. 098 * 099 * @param calendar the Calendar to extract fields from 100 * @return the created YearMonthDay 101 * @throws IllegalArgumentException if the calendar is null 102 * @throws IllegalArgumentException if the date is invalid for the ISO chronology 103 * @since 1.2 104 */ 105 public static YearMonthDay fromCalendarFields(Calendar calendar) { 106 if (calendar == null) { 107 throw new IllegalArgumentException("The calendar must not be null"); 108 } 109 return new YearMonthDay( 110 calendar.get(Calendar.YEAR), 111 calendar.get(Calendar.MONTH) + 1, 112 calendar.get(Calendar.DAY_OF_MONTH) 113 ); 114 } 115 116 /** 117 * Constructs a YearMonthDay from a <code>java.util.Date</code> 118 * using exactly the same field values avoiding any time zone effects. 119 * <p> 120 * Each field is queried from the Date and assigned to the YearMonthDay. 121 * This is useful if you have been using the Date as a local date, 122 * ignoing the zone. 123 * <p> 124 * This factory method always creates a YearMonthDay with ISO chronology. 125 * 126 * @param date the Date to extract fields from 127 * @return the created YearMonthDay 128 * @throws IllegalArgumentException if the calendar is null 129 * @throws IllegalArgumentException if the date is invalid for the ISO chronology 130 * @since 1.2 131 */ 132 public static YearMonthDay fromDateFields(Date date) { 133 if (date == null) { 134 throw new IllegalArgumentException("The date must not be null"); 135 } 136 return new YearMonthDay( 137 date.getYear() + 1900, 138 date.getMonth() + 1, 139 date.getDate() 140 ); 141 } 142 143 //----------------------------------------------------------------------- 144 /** 145 * Constructs a YearMonthDay with the current date, using ISOChronology in 146 * the default zone to extract the fields. 147 * <p> 148 * The constructor uses the default time zone, resulting in the local time 149 * being initialised. Once the constructor is complete, all further calculations 150 * are performed without reference to a timezone (by switching to UTC). 151 */ 152 public YearMonthDay() { 153 super(); 154 } 155 156 /** 157 * Constructs a YearMonthDay with the current date, using ISOChronology in 158 * the specified zone to extract the fields. 159 * <p> 160 * The constructor uses the specified time zone to obtain the current date. 161 * Once the constructor is complete, all further calculations 162 * are performed without reference to a timezone (by switching to UTC). 163 * 164 * @param zone the zone to use, null means default zone 165 * @since 1.1 166 */ 167 public YearMonthDay(DateTimeZone zone) { 168 super(ISOChronology.getInstance(zone)); 169 } 170 171 /** 172 * Constructs a YearMonthDay with the current date, using the specified chronology 173 * and zone to extract the fields. 174 * <p> 175 * The constructor uses the time zone of the chronology specified. 176 * Once the constructor is complete, all further calculations are performed 177 * without reference to a timezone (by switching to UTC). 178 * 179 * @param chronology the chronology, null means ISOChronology in the default zone 180 */ 181 public YearMonthDay(Chronology chronology) { 182 super(chronology); 183 } 184 185 /** 186 * Constructs a YearMonthDay extracting the partial fields from the specified 187 * milliseconds using the ISOChronology in the default zone. 188 * <p> 189 * The constructor uses the default time zone, resulting in the local time 190 * being initialised. Once the constructor is complete, all further calculations 191 * are performed without reference to a timezone (by switching to UTC). 192 * 193 * @param instant the milliseconds from 1970-01-01T00:00:00Z 194 */ 195 public YearMonthDay(long instant) { 196 super(instant); 197 } 198 199 /** 200 * Constructs a YearMonthDay extracting the partial fields from the specified 201 * milliseconds using the chronology provided. 202 * <p> 203 * The constructor uses the time zone of the chronology specified. 204 * Once the constructor is complete, all further calculations are performed 205 * without reference to a timezone (by switching to UTC). 206 * 207 * @param instant the milliseconds from 1970-01-01T00:00:00Z 208 * @param chronology the chronology, null means ISOChronology in the default zone 209 */ 210 public YearMonthDay(long instant, Chronology chronology) { 211 super(instant, chronology); 212 } 213 214 /** 215 * Constructs a YearMonthDay from an Object that represents a time. 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 * The String formats are described by {@link ISODateTimeFormat#dateOptionalTimeParser()}. 221 * <p> 222 * The chronology used will be derived from the object, defaulting to ISO. 223 * <p> 224 * NOTE: Prior to v1.3 the string format was described by 225 * {@link ISODateTimeFormat#dateTimeParser()}. Time ony strings are now rejected. 226 * 227 * @param instant the datetime object, null means now 228 * @throws IllegalArgumentException if the instant is invalid 229 */ 230 public YearMonthDay(Object instant) { 231 super(instant, null, ISODateTimeFormat.dateOptionalTimeParser()); 232 } 233 234 /** 235 * Constructs a YearMonthDay from an Object that represents a time, using the 236 * specified chronology. 237 * <p> 238 * The recognised object types are defined in 239 * {@link org.joda.time.convert.ConverterManager ConverterManager} and 240 * include ReadableInstant, String, Calendar and Date. 241 * The String formats are described by {@link ISODateTimeFormat#dateOptionalTimeParser()}. 242 * <p> 243 * The constructor uses the time zone of the chronology specified. 244 * Once the constructor is complete, all further calculations are performed 245 * without reference to a timezone (by switching to UTC). 246 * The specified chronology overrides that of the object. 247 * <p> 248 * NOTE: Prior to v1.3 the string format was described by 249 * {@link ISODateTimeFormat#dateTimeParser()}. Time only strings are now rejected. 250 * 251 * @param instant the datetime object, null means now 252 * @param chronology the chronology, null means ISO default 253 * @throws IllegalArgumentException if the instant is invalid 254 */ 255 public YearMonthDay(Object instant, Chronology chronology) { 256 super(instant, DateTimeUtils.getChronology(chronology), ISODateTimeFormat.dateOptionalTimeParser()); 257 } 258 259 /** 260 * Constructs a YearMonthDay with specified time field values 261 * using <code>ISOChronology</code> in the default zone. 262 * <p> 263 * The constructor uses the no time zone initialising the fields as provided. 264 * Once the constructor is complete, all further calculations 265 * are performed without reference to a timezone (by switching to UTC). 266 * 267 * @param year the year 268 * @param monthOfYear the month of the year 269 * @param dayOfMonth the day of the month 270 */ 271 public YearMonthDay(int year, int monthOfYear, int dayOfMonth) { 272 this(year, monthOfYear, dayOfMonth, null); 273 } 274 275 /** 276 * Constructs a YearMonthDay with specified time field values. 277 * <p> 278 * The constructor uses the time zone of the chronology specified. 279 * Once the constructor is complete, all further calculations are performed 280 * without reference to a timezone (by switching to UTC). 281 * 282 * @param year the year 283 * @param monthOfYear the month of the year 284 * @param dayOfMonth the day of the month 285 * @param chronology the chronology, null means ISOChronology in the default zone 286 */ 287 public YearMonthDay(int year, int monthOfYear, int dayOfMonth, Chronology chronology) { 288 super(new int[] {year, monthOfYear, dayOfMonth}, chronology); 289 } 290 291 /** 292 * Constructs a YearMonthDay with chronology from this instance and new values. 293 * 294 * @param partial the partial to base this new instance on 295 * @param values the new set of values 296 */ 297 YearMonthDay(YearMonthDay partial, int[] values) { 298 super(partial, values); 299 } 300 301 /** 302 * Constructs a YearMonthDay with values from this instance and a new chronology. 303 * 304 * @param partial the partial to base this new instance on 305 * @param chrono the new chronology 306 */ 307 YearMonthDay(YearMonthDay partial, Chronology chrono) { 308 super(partial, chrono); 309 } 310 311 //----------------------------------------------------------------------- 312 /** 313 * Gets the number of fields in this partial. 314 * 315 * @return the field count 316 */ 317 public int size() { 318 return 3; 319 } 320 321 /** 322 * Gets the field for a specific index in the chronology specified. 323 * <p> 324 * This method must not use any instance variables. 325 * 326 * @param index the index to retrieve 327 * @param chrono the chronology to use 328 * @return the field 329 */ 330 protected DateTimeField getField(int index, Chronology chrono) { 331 switch (index) { 332 case YEAR: 333 return chrono.year(); 334 case MONTH_OF_YEAR: 335 return chrono.monthOfYear(); 336 case DAY_OF_MONTH: 337 return chrono.dayOfMonth(); 338 default: 339 throw new IndexOutOfBoundsException("Invalid index: " + index); 340 } 341 } 342 343 /** 344 * Gets the field type at the specified index. 345 * 346 * @param index the index to retrieve 347 * @return the field at the specified index 348 * @throws IndexOutOfBoundsException if the index is invalid 349 */ 350 public DateTimeFieldType getFieldType(int index) { 351 return FIELD_TYPES[index]; 352 } 353 354 /** 355 * Gets an array of the field type of each of the fields that this partial supports. 356 * <p> 357 * The fields are returned largest to smallest, Year, Month, Day 358 * 359 * @return the array of field types (cloned), largest to smallest 360 */ 361 public DateTimeFieldType[] getFieldTypes() { 362 return (DateTimeFieldType[]) FIELD_TYPES.clone(); 363 } 364 365 //----------------------------------------------------------------------- 366 /** 367 * Returns a copy of this date with the specified chronology. 368 * This instance is immutable and unaffected by this method call. 369 * <p> 370 * This method retains the values of the fields, thus the result will 371 * typically refer to a different instant. 372 * <p> 373 * The time zone of the specified chronology is ignored, as YearMonthDay 374 * operates without a time zone. 375 * 376 * @param newChronology the new chronology, null means ISO 377 * @return a copy of this datetime with a different chronology 378 * @throws IllegalArgumentException if the values are invalid for the new chronology 379 */ 380 public YearMonthDay withChronologyRetainFields(Chronology newChronology) { 381 newChronology = DateTimeUtils.getChronology(newChronology); 382 newChronology = newChronology.withUTC(); 383 if (newChronology == getChronology()) { 384 return this; 385 } else { 386 YearMonthDay newYearMonthDay = new YearMonthDay(this, newChronology); 387 newChronology.validate(newYearMonthDay, getValues()); 388 return newYearMonthDay; 389 } 390 } 391 392 /** 393 * Returns a copy of this date with the specified field set to a new value. 394 * <p> 395 * For example, if the field type is <code>dayOfMonth</code> then the day 396 * would be changed in the returned instance. 397 * <p> 398 * These three lines are equivalent: 399 * <pre> 400 * YearMonthDay updated = ymd.withField(DateTimeFieldType.dayOfMonth(), 6); 401 * YearMonthDay updated = ymd.dayOfMonth().setCopy(6); 402 * YearMonthDay updated = ymd.property(DateTimeFieldType.dayOfMonth()).setCopy(6); 403 * </pre> 404 * 405 * @param fieldType the field type to set, not null 406 * @param value the value to set 407 * @return a copy of this instance with the field set 408 * @throws IllegalArgumentException if the value is null or invalid 409 */ 410 public YearMonthDay withField(DateTimeFieldType fieldType, int value) { 411 int index = indexOfSupported(fieldType); 412 if (value == getValue(index)) { 413 return this; 414 } 415 int[] newValues = getValues(); 416 newValues = getField(index).set(this, index, newValues, value); 417 return new YearMonthDay(this, newValues); 418 } 419 420 /** 421 * Returns a copy of this date with the value of the specified field increased. 422 * <p> 423 * If the addition is zero, then <code>this</code> is returned. 424 * <p> 425 * These three lines are equivalent: 426 * <pre> 427 * YearMonthDay added = ymd.withFieldAdded(DurationFieldType.days(), 6); 428 * YearMonthDay added = ymd.plusDays(6); 429 * YearMonthDay added = ymd.dayOfMonth().addToCopy(6); 430 * </pre> 431 * 432 * @param fieldType the field type to add to, not null 433 * @param amount the amount to add 434 * @return a copy of this instance with the field updated 435 * @throws IllegalArgumentException if the value is null or invalid 436 * @throws ArithmeticException if the new datetime exceeds the capacity 437 */ 438 public YearMonthDay withFieldAdded(DurationFieldType fieldType, int amount) { 439 int index = indexOfSupported(fieldType); 440 if (amount == 0) { 441 return this; 442 } 443 int[] newValues = getValues(); 444 newValues = getField(index).add(this, index, newValues, amount); 445 return new YearMonthDay(this, newValues); 446 } 447 448 /** 449 * Returns a copy of this date with the specified period added. 450 * <p> 451 * If the addition is zero, then <code>this</code> is returned. 452 * Fields in the period that aren't present in the partial are ignored. 453 * <p> 454 * This method is typically used to add multiple copies of complex 455 * period instances. Adding one field is best achieved using methods 456 * like {@link #withFieldAdded(DurationFieldType, int)} 457 * or {@link #plusYears(int)}. 458 * 459 * @param period the period to add to this one, null means zero 460 * @param scalar the amount of times to add, such as -1 to subtract once 461 * @return a copy of this instance with the period added 462 * @throws ArithmeticException if the new datetime exceeds the capacity 463 */ 464 public YearMonthDay withPeriodAdded(ReadablePeriod period, int scalar) { 465 if (period == null || scalar == 0) { 466 return this; 467 } 468 int[] newValues = getValues(); 469 for (int i = 0; i < period.size(); i++) { 470 DurationFieldType fieldType = period.getFieldType(i); 471 int index = indexOf(fieldType); 472 if (index >= 0) { 473 newValues = getField(index).add(this, index, newValues, 474 FieldUtils.safeMultiply(period.getValue(i), scalar)); 475 } 476 } 477 return new YearMonthDay(this, newValues); 478 } 479 480 //----------------------------------------------------------------------- 481 /** 482 * Returns a copy of this date with the specified period added. 483 * <p> 484 * If the amount is zero or null, then <code>this</code> is returned. 485 * <p> 486 * This method is typically used to add complex period instances. 487 * Adding one field is best achieved using methods 488 * like {@link #plusYears(int)}. 489 * 490 * @param period the duration to add to this one, null means zero 491 * @return a copy of this instance with the period added 492 * @throws ArithmeticException if the new datetime exceeds the capacity of a long 493 */ 494 public YearMonthDay plus(ReadablePeriod period) { 495 return withPeriodAdded(period, 1); 496 } 497 498 //----------------------------------------------------------------------- 499 /** 500 * Returns a copy of this date plus the specified number of years. 501 * <p> 502 * This date instance is immutable and unaffected by this method call. 503 * <p> 504 * The following three lines are identical in effect: 505 * <pre> 506 * YearMonthDay added = dt.plusYears(6); 507 * YearMonthDay added = dt.plus(Period.years(6)); 508 * YearMonthDay added = dt.withFieldAdded(DurationFieldType.years(), 6); 509 * </pre> 510 * 511 * @param years the amount of years to add, may be negative 512 * @return the new date plus the increased years 513 * @since 1.1 514 */ 515 public YearMonthDay plusYears(int years) { 516 return withFieldAdded(DurationFieldType.years(), years); 517 } 518 519 /** 520 * Returns a copy of this date plus the specified number of months. 521 * <p> 522 * This date instance is immutable and unaffected by this method call. 523 * <p> 524 * The following three lines are identical in effect: 525 * <pre> 526 * YearMonthDay added = dt.plusMonths(6); 527 * YearMonthDay added = dt.plus(Period.months(6)); 528 * YearMonthDay added = dt.withFieldAdded(DurationFieldType.months(), 6); 529 * </pre> 530 * 531 * @param months the amount of months to add, may be negative 532 * @return the new date plus the increased months 533 * @since 1.1 534 */ 535 public YearMonthDay plusMonths(int months) { 536 return withFieldAdded(DurationFieldType.months(), months); 537 } 538 539 /** 540 * Returns a copy of this date plus the specified number of days. 541 * <p> 542 * This date instance is immutable and unaffected by this method call. 543 * <p> 544 * The following three lines are identical in effect: 545 * <pre> 546 * YearMonthDay added = dt.plusDays(6); 547 * YearMonthDay added = dt.plus(Period.days(6)); 548 * YearMonthDay added = dt.withFieldAdded(DurationFieldType.days(), 6); 549 * </pre> 550 * 551 * @param days the amount of days to add, may be negative 552 * @return the new date plus the increased days 553 * @since 1.1 554 */ 555 public YearMonthDay plusDays(int days) { 556 return withFieldAdded(DurationFieldType.days(), days); 557 } 558 559 //----------------------------------------------------------------------- 560 /** 561 * Returns a copy of this date with the specified period taken away. 562 * <p> 563 * If the amount is zero or null, then <code>this</code> is returned. 564 * <p> 565 * This method is typically used to subtract complex period instances. 566 * Subtracting one field is best achieved using methods 567 * like {@link #minusYears(int)}. 568 * 569 * @param period the period to reduce this instant by 570 * @return a copy of this instance with the period taken away 571 * @throws ArithmeticException if the new datetime exceeds the capacity of a long 572 */ 573 public YearMonthDay minus(ReadablePeriod period) { 574 return withPeriodAdded(period, -1); 575 } 576 577 //----------------------------------------------------------------------- 578 /** 579 * Returns a copy of this date minus the specified number of years. 580 * <p> 581 * This datetime instance is immutable and unaffected by this method call. 582 * <p> 583 * The following three lines are identical in effect: 584 * <pre> 585 * YearMonthDay subtracted = dt.minusYears(6); 586 * YearMonthDay subtracted = dt.minus(Period.years(6)); 587 * YearMonthDay subtracted = dt.withFieldAdded(DurationFieldType.years(), -6); 588 * </pre> 589 * 590 * @param years the amount of years to subtract, may be negative 591 * @return the new datetime minus the increased years 592 * @since 1.1 593 */ 594 public YearMonthDay minusYears(int years) { 595 return withFieldAdded(DurationFieldType.years(), FieldUtils.safeNegate(years)); 596 } 597 598 /** 599 * Returns a copy of this date minus the specified number of months. 600 * <p> 601 * This datetime instance is immutable and unaffected by this method call. 602 * <p> 603 * The following three lines are identical in effect: 604 * <pre> 605 * YearMonthDay subtracted = dt.minusMonths(6); 606 * YearMonthDay subtracted = dt.minus(Period.months(6)); 607 * YearMonthDay subtracted = dt.withFieldAdded(DurationFieldType.months(), -6); 608 * </pre> 609 * 610 * @param months the amount of months to subtract, may be negative 611 * @return the new datetime minus the increased months 612 * @since 1.1 613 */ 614 public YearMonthDay minusMonths(int months) { 615 return withFieldAdded(DurationFieldType.months(), FieldUtils.safeNegate(months)); 616 } 617 618 /** 619 * Returns a copy of this date minus the specified number of days. 620 * <p> 621 * This datetime instance is immutable and unaffected by this method call. 622 * <p> 623 * The following three lines are identical in effect: 624 * <pre> 625 * YearMonthDay subtracted = dt.minusDays(6); 626 * YearMonthDay subtracted = dt.minus(Period.days(6)); 627 * YearMonthDay subtracted = dt.withFieldAdded(DurationFieldType.days(), -6); 628 * </pre> 629 * 630 * @param days the amount of days to subtract, may be negative 631 * @return the new datetime minus the increased days 632 * @since 1.1 633 */ 634 public YearMonthDay minusDays(int days) { 635 return withFieldAdded(DurationFieldType.days(), FieldUtils.safeNegate(days)); 636 } 637 638 //----------------------------------------------------------------------- 639 /** 640 * Gets the property object for the specified type, which contains 641 * many useful methods. 642 * 643 * @param type the field type to get the property for 644 * @return the property object 645 * @throws IllegalArgumentException if the field is null or unsupported 646 */ 647 public Property property(DateTimeFieldType type) { 648 return new Property(this, indexOfSupported(type)); 649 } 650 651 //----------------------------------------------------------------------- 652 /** 653 * Converts this object to a LocalDate with the same date and chronology. 654 * 655 * @return a LocalDate with the same date and chronology 656 * @since 1.3 657 */ 658 public LocalDate toLocalDate() { 659 return new LocalDate(getYear(), getMonthOfYear(), getDayOfMonth(), getChronology()); 660 } 661 662 //----------------------------------------------------------------------- 663 /** 664 * Converts this YearMonthDay to a full datetime at midnight using the 665 * default time zone. 666 * 667 * @return this date as a datetime at midnight 668 */ 669 public DateTime toDateTimeAtMidnight() { 670 return toDateTimeAtMidnight(null); 671 } 672 673 /** 674 * Converts this YearMonthDay to a full datetime at midnight using the 675 * specified time zone. 676 * <p> 677 * This method uses the chronology from this instance plus the time zone 678 * specified. 679 * 680 * @param zone the zone to use, null means default 681 * @return this date as a datetime at midnight 682 */ 683 public DateTime toDateTimeAtMidnight(DateTimeZone zone) { 684 Chronology chrono = getChronology().withZone(zone); 685 return new DateTime(getYear(), getMonthOfYear(), getDayOfMonth(), 0, 0, 0, 0, chrono); 686 } 687 688 //----------------------------------------------------------------------- 689 /** 690 * Converts this partial to a full datetime using the default time zone 691 * setting the date fields from this instance and the time fields from 692 * the current time. 693 * 694 * @return this date as a datetime with the time as the current time 695 */ 696 public DateTime toDateTimeAtCurrentTime() { 697 return toDateTimeAtCurrentTime(null); 698 } 699 700 /** 701 * Converts this partial to a full datetime using the specified time zone 702 * setting the date fields from this instance and the time fields from 703 * the current time. 704 * <p> 705 * This method uses the chronology from this instance plus the time zone 706 * specified. 707 * 708 * @param zone the zone to use, null means default 709 * @return this date as a datetime with the time as the current time 710 */ 711 public DateTime toDateTimeAtCurrentTime(DateTimeZone zone) { 712 Chronology chrono = getChronology().withZone(zone); 713 long instantMillis = DateTimeUtils.currentTimeMillis(); 714 long resolved = chrono.set(this, instantMillis); 715 return new DateTime(resolved, chrono); 716 } 717 718 //----------------------------------------------------------------------- 719 /** 720 * Converts this object to a DateMidnight in the default time zone. 721 * 722 * @return the DateMidnight instance in the default zone 723 */ 724 public DateMidnight toDateMidnight() { 725 return toDateMidnight(null); 726 } 727 728 /** 729 * Converts this object to a DateMidnight. 730 * 731 * @param zone the zone to get the DateMidnight in, null means default 732 * @return the DateMidnight instance 733 */ 734 public DateMidnight toDateMidnight(DateTimeZone zone) { 735 Chronology chrono = getChronology().withZone(zone); 736 return new DateMidnight(getYear(), getMonthOfYear(), getDayOfMonth(), chrono); 737 } 738 739 //----------------------------------------------------------------------- 740 /** 741 * Converts this object to a DateTime using a TimeOfDay to fill in the 742 * missing fields and using the default time zone. 743 * This instance is immutable and unaffected by this method call. 744 * <p> 745 * The resulting chronology is determined by the chronology of this 746 * YearMonthDay plus the time zone. 747 * The chronology of the time is ignored - only the field values are used. 748 * 749 * @param time the time of day to use, null means current time 750 * @return the DateTime instance 751 */ 752 public DateTime toDateTime(TimeOfDay time) { 753 return toDateTime(time, null); 754 } 755 756 /** 757 * Converts this object to a DateTime using a TimeOfDay to fill in the 758 * missing fields. 759 * This instance is immutable and unaffected by this method call. 760 * <p> 761 * The resulting chronology is determined by the chronology of this 762 * YearMonthDay plus the time zone. 763 * The chronology of the time is ignored - only the field values are used. 764 * 765 * @param time the time of day to use, null means current time 766 * @param zone the zone to get the DateTime in, null means default 767 * @return the DateTime instance 768 */ 769 public DateTime toDateTime(TimeOfDay time, DateTimeZone zone) { 770 Chronology chrono = getChronology().withZone(zone); 771 long instant = DateTimeUtils.currentTimeMillis(); 772 instant = chrono.set(this, instant); 773 if (time != null) { 774 instant = chrono.set(time, instant); 775 } 776 return new DateTime(instant, chrono); 777 } 778 779 //----------------------------------------------------------------------- 780 /** 781 * Converts this object to an Interval representing the whole day 782 * in the default time zone. 783 * 784 * @return a interval over the day 785 */ 786 public Interval toInterval() { 787 return toInterval(null); 788 } 789 790 /** 791 * Converts this object to an Interval representing the whole day. 792 * 793 * @param zone the zone to get the Interval in, null means default 794 * @return a interval over the day 795 */ 796 public Interval toInterval(DateTimeZone zone) { 797 zone = DateTimeUtils.getZone(zone); 798 return toDateMidnight(zone).toInterval(); 799 } 800 801 //----------------------------------------------------------------------- 802 /** 803 * Get the year field value. 804 * 805 * @return the year 806 */ 807 public int getYear() { 808 return getValue(YEAR); 809 } 810 811 /** 812 * Get the month of year field value. 813 * 814 * @return the month of year 815 */ 816 public int getMonthOfYear() { 817 return getValue(MONTH_OF_YEAR); 818 } 819 820 /** 821 * Get the day of month field value. 822 * 823 * @return the day of month 824 */ 825 public int getDayOfMonth() { 826 return getValue(DAY_OF_MONTH); 827 } 828 829 //----------------------------------------------------------------------- 830 /** 831 * Returns a copy of this date with the year field updated. 832 * <p> 833 * YearMonthDay is immutable, so there are no set methods. 834 * Instead, this method returns a new instance with the value of 835 * year changed. 836 * 837 * @param year the year to set 838 * @return a copy of this object with the field set 839 * @throws IllegalArgumentException if the value is invalid 840 * @since 1.3 841 */ 842 public YearMonthDay withYear(int year) { 843 int[] newValues = getValues(); 844 newValues = getChronology().year().set(this, YEAR, newValues, year); 845 return new YearMonthDay(this, newValues); 846 } 847 848 /** 849 * Returns a copy of this date with the month of year field updated. 850 * <p> 851 * YearMonthDay is immutable, so there are no set methods. 852 * Instead, this method returns a new instance with the value of 853 * month of year changed. 854 * 855 * @param monthOfYear the month of year to set 856 * @return a copy of this object with the field set 857 * @throws IllegalArgumentException if the value is invalid 858 * @since 1.3 859 */ 860 public YearMonthDay withMonthOfYear(int monthOfYear) { 861 int[] newValues = getValues(); 862 newValues = getChronology().monthOfYear().set(this, MONTH_OF_YEAR, newValues, monthOfYear); 863 return new YearMonthDay(this, newValues); 864 } 865 866 /** 867 * Returns a copy of this date with the day of month field updated. 868 * <p> 869 * YearMonthDay is immutable, so there are no set methods. 870 * Instead, this method returns a new instance with the value of 871 * day of month changed. 872 * 873 * @param dayOfMonth the day of month to set 874 * @return a copy of this object with the field set 875 * @throws IllegalArgumentException if the value is invalid 876 * @since 1.3 877 */ 878 public YearMonthDay withDayOfMonth(int dayOfMonth) { 879 int[] newValues = getValues(); 880 newValues = getChronology().dayOfMonth().set(this, DAY_OF_MONTH, newValues, dayOfMonth); 881 return new YearMonthDay(this, newValues); 882 } 883 884 //----------------------------------------------------------------------- 885 /** 886 * Get the year field property which provides access to advanced functionality. 887 * 888 * @return the year property 889 */ 890 public Property year() { 891 return new Property(this, YEAR); 892 } 893 894 /** 895 * Get the month of year field property which provides access to advanced functionality. 896 * 897 * @return the month of year property 898 */ 899 public Property monthOfYear() { 900 return new Property(this, MONTH_OF_YEAR); 901 } 902 903 /** 904 * Get the day of month field property which provides access to advanced functionality. 905 * 906 * @return the day of month property 907 */ 908 public Property dayOfMonth() { 909 return new Property(this, DAY_OF_MONTH); 910 } 911 912 //----------------------------------------------------------------------- 913 /** 914 * Output the date in the ISO8601 format YYYY-MM-DD. 915 * 916 * @return ISO8601 formatted string 917 */ 918 public String toString() { 919 return ISODateTimeFormat.yearMonthDay().print(this); 920 } 921 922 //----------------------------------------------------------------------- 923 /** 924 * The property class for <code>YearMonthDay</code>. 925 * <p> 926 * This class binds a <code>YearMonthDay</code> to a <code>DateTimeField</code>. 927 * 928 * @author Stephen Colebourne 929 * @since 1.0 930 * @deprecated Use LocalDate which has a much better internal implementation 931 */ 932 @Deprecated 933 public static class Property extends AbstractPartialFieldProperty implements Serializable { 934 935 /** Serialization version */ 936 private static final long serialVersionUID = 5727734012190224363L; 937 938 /** The partial */ 939 private final YearMonthDay iYearMonthDay; 940 /** The field index */ 941 private final int iFieldIndex; 942 943 /** 944 * Constructs a property. 945 * 946 * @param partial the partial instance 947 * @param fieldIndex the index in the partial 948 */ 949 Property(YearMonthDay partial, int fieldIndex) { 950 super(); 951 iYearMonthDay = partial; 952 iFieldIndex = fieldIndex; 953 } 954 955 /** 956 * Gets the field that this property uses. 957 * 958 * @return the field 959 */ 960 public DateTimeField getField() { 961 return iYearMonthDay.getField(iFieldIndex); 962 } 963 964 /** 965 * Gets the partial that this property belongs to. 966 * 967 * @return the partial 968 */ 969 protected ReadablePartial getReadablePartial() { 970 return iYearMonthDay; 971 } 972 973 /** 974 * Gets the partial that this property belongs to. 975 * 976 * @return the partial 977 */ 978 public YearMonthDay getYearMonthDay() { 979 return iYearMonthDay; 980 } 981 982 /** 983 * Gets the value of this field. 984 * 985 * @return the field value 986 */ 987 public int get() { 988 return iYearMonthDay.getValue(iFieldIndex); 989 } 990 991 //----------------------------------------------------------------------- 992 /** 993 * Adds to the value of this field in a copy of this YearMonthDay. 994 * <p> 995 * The value will be added to this field. If the value is too large to be 996 * added solely to this field then it will affect larger fields. 997 * Smaller fields are unaffected. 998 * <p> 999 * If the result would be too large, beyond the maximum year, then an 1000 * IllegalArgumentException is thrown. 1001 * <p> 1002 * The YearMonthDay attached to this property is unchanged by this call. 1003 * Instead, a new instance is returned. 1004 * 1005 * @param valueToAdd the value to add to the field in the copy 1006 * @return a copy of the YearMonthDay with the field value changed 1007 * @throws IllegalArgumentException if the value isn't valid 1008 */ 1009 public YearMonthDay addToCopy(int valueToAdd) { 1010 int[] newValues = iYearMonthDay.getValues(); 1011 newValues = getField().add(iYearMonthDay, iFieldIndex, newValues, valueToAdd); 1012 return new YearMonthDay(iYearMonthDay, newValues); 1013 } 1014 1015 /** 1016 * Adds to the value of this field in a copy of this YearMonthDay wrapping 1017 * within this field if the maximum value is reached. 1018 * <p> 1019 * The value will be added to this field. If the value is too large to be 1020 * added solely to this field then it wraps within this field. 1021 * Other fields are unaffected. 1022 * <p> 1023 * For example, 1024 * <code>2004-12-20</code> addWrapField one month returns <code>2004-01-20</code>. 1025 * <p> 1026 * The YearMonthDay attached to this property is unchanged by this call. 1027 * Instead, a new instance is returned. 1028 * 1029 * @param valueToAdd the value to add to the field in the copy 1030 * @return a copy of the YearMonthDay with the field value changed 1031 * @throws IllegalArgumentException if the value isn't valid 1032 */ 1033 public YearMonthDay addWrapFieldToCopy(int valueToAdd) { 1034 int[] newValues = iYearMonthDay.getValues(); 1035 newValues = getField().addWrapField(iYearMonthDay, iFieldIndex, newValues, valueToAdd); 1036 return new YearMonthDay(iYearMonthDay, newValues); 1037 } 1038 1039 //----------------------------------------------------------------------- 1040 /** 1041 * Sets this field in a copy of the YearMonthDay. 1042 * <p> 1043 * The YearMonthDay attached to this property is unchanged by this call. 1044 * Instead, a new instance is returned. 1045 * 1046 * @param value the value to set the field in the copy to 1047 * @return a copy of the YearMonthDay with the field value changed 1048 * @throws IllegalArgumentException if the value isn't valid 1049 */ 1050 public YearMonthDay setCopy(int value) { 1051 int[] newValues = iYearMonthDay.getValues(); 1052 newValues = getField().set(iYearMonthDay, iFieldIndex, newValues, value); 1053 return new YearMonthDay(iYearMonthDay, newValues); 1054 } 1055 1056 /** 1057 * Sets this field in a copy of the YearMonthDay to a parsed text value. 1058 * <p> 1059 * The YearMonthDay attached to this property is unchanged by this call. 1060 * Instead, a new instance is returned. 1061 * 1062 * @param text the text value to set 1063 * @param locale optional locale to use for selecting a text symbol 1064 * @return a copy of the YearMonthDay with the field value changed 1065 * @throws IllegalArgumentException if the text value isn't valid 1066 */ 1067 public YearMonthDay setCopy(String text, Locale locale) { 1068 int[] newValues = iYearMonthDay.getValues(); 1069 newValues = getField().set(iYearMonthDay, iFieldIndex, newValues, text, locale); 1070 return new YearMonthDay(iYearMonthDay, newValues); 1071 } 1072 1073 /** 1074 * Sets this field in a copy of the YearMonthDay to a parsed text value. 1075 * <p> 1076 * The YearMonthDay attached to this property is unchanged by this call. 1077 * Instead, a new instance is returned. 1078 * 1079 * @param text the text value to set 1080 * @return a copy of the YearMonthDay with the field value changed 1081 * @throws IllegalArgumentException if the text value isn't valid 1082 */ 1083 public YearMonthDay setCopy(String text) { 1084 return setCopy(text, null); 1085 } 1086 1087 //----------------------------------------------------------------------- 1088 /** 1089 * Returns a new YearMonthDay with this field set to the maximum value 1090 * for this field. 1091 * <p> 1092 * This operation is useful for obtaining a DateTime on the last day 1093 * of the month, as month lengths vary. 1094 * <pre> 1095 * YearMonthDay lastDayOfMonth = dt.dayOfMonth().withMaximumValue(); 1096 * </pre> 1097 * <p> 1098 * The YearMonthDay attached to this property is unchanged by this call. 1099 * 1100 * @return a copy of the YearMonthDay with this field set to its maximum 1101 * @since 1.2 1102 */ 1103 public YearMonthDay withMaximumValue() { 1104 return setCopy(getMaximumValue()); 1105 } 1106 1107 /** 1108 * Returns a new YearMonthDay with this field set to the minimum value 1109 * for this field. 1110 * <p> 1111 * The YearMonthDay attached to this property is unchanged by this call. 1112 * 1113 * @return a copy of the YearMonthDay with this field set to its minimum 1114 * @since 1.2 1115 */ 1116 public YearMonthDay withMinimumValue() { 1117 return setCopy(getMinimumValue()); 1118 } 1119 } 1120 1121 }