001 /* 002 * Copyright 2001-2007 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.Calendar; 023 import java.util.Date; 024 import java.util.HashSet; 025 import java.util.Locale; 026 import java.util.Set; 027 028 import org.joda.time.base.BaseLocal; 029 import org.joda.time.chrono.ISOChronology; 030 import org.joda.time.convert.ConverterManager; 031 import org.joda.time.convert.PartialConverter; 032 import org.joda.time.field.AbstractReadableInstantFieldProperty; 033 import org.joda.time.field.FieldUtils; 034 import org.joda.time.format.DateTimeFormat; 035 import org.joda.time.format.ISODateTimeFormat; 036 037 /** 038 * LocalDate is an immutable datetime class representing a date 039 * without a time zone. 040 * <p> 041 * LocalDate implements the {@link ReadablePartial} interface. 042 * To do this, the interface methods focus on the key fields - 043 * Year, MonthOfYear and DayOfMonth. 044 * However, <b>all</b> date fields may in fact be queried. 045 * <p> 046 * LocalDate differs from DateMidnight in that this class does not 047 * have a time zone and does not represent a single instant in time. 048 * <p> 049 * Calculations on LocalDate are performed using a {@link Chronology}. 050 * This chronology will be set internally to be in the UTC time zone 051 * for all calculations. 052 * 053 * <p>Each individual field can be queried in two ways: 054 * <ul> 055 * <li><code>getMonthOfYear()</code> 056 * <li><code>monthOfYear().get()</code> 057 * </ul> 058 * The second technique also provides access to other useful methods on the 059 * field: 060 * <ul> 061 * <li>numeric value 062 * <li>text value 063 * <li>short text value 064 * <li>maximum/minimum values 065 * <li>add/subtract 066 * <li>set 067 * <li>rounding 068 * </ul> 069 * 070 * <p> 071 * LocalDate is thread-safe and immutable, provided that the Chronology is as well. 072 * All standard Chronology classes supplied are thread-safe and immutable. 073 * 074 * @author Stephen Colebourne 075 * @since 1.3 076 */ 077 public final class LocalDate 078 extends BaseLocal 079 implements ReadablePartial, Serializable { 080 081 /** Serialization lock */ 082 private static final long serialVersionUID = -8775358157899L; 083 084 /** The index of the year field in the field array */ 085 private static final int YEAR = 0; 086 /** The index of the monthOfYear field in the field array */ 087 private static final int MONTH_OF_YEAR = 1; 088 /** The index of the dayOfMonth field in the field array */ 089 private static final int DAY_OF_MONTH = 2; 090 /** Set of known duration types. */ 091 private static final Set DATE_DURATION_TYPES = new HashSet(); 092 static { 093 DATE_DURATION_TYPES.add(DurationFieldType.days()); 094 DATE_DURATION_TYPES.add(DurationFieldType.weeks()); 095 DATE_DURATION_TYPES.add(DurationFieldType.months()); 096 DATE_DURATION_TYPES.add(DurationFieldType.weekyears()); 097 DATE_DURATION_TYPES.add(DurationFieldType.years()); 098 DATE_DURATION_TYPES.add(DurationFieldType.centuries()); 099 // eras are supported, although the DurationField generally isn't 100 DATE_DURATION_TYPES.add(DurationFieldType.eras()); 101 } 102 103 /** The local millis from 1970-01-01T00:00:00 */ 104 private long iLocalMillis; 105 /** The chronology to use in UTC */ 106 private Chronology iChronology; 107 108 //----------------------------------------------------------------------- 109 /** 110 * Constructs a LocalDate from a <code>java.util.Calendar</code> 111 * using exactly the same field values. 112 * <p> 113 * Each field is queried from the Calendar and assigned to the LocalDate. 114 * This is useful if you have been using the Calendar as a local date, 115 * ignoring the zone. 116 * <p> 117 * One advantage of this method is that this method is unaffected if the 118 * version of the time zone data differs between the JDK and Joda-Time. 119 * That is because the local field values are transferred, calculated using 120 * the JDK time zone data and without using the Joda-Time time zone data. 121 * <p> 122 * This factory method ignores the type of the calendar and always 123 * creates a LocalDate with ISO chronology. It is expected that you 124 * will only pass in instances of <code>GregorianCalendar</code> however 125 * this is not validated. 126 * 127 * @param calendar the Calendar to extract fields from 128 * @return the created LocalDate 129 * @throws IllegalArgumentException if the calendar is null 130 * @throws IllegalArgumentException if the date is invalid for the ISO chronology 131 */ 132 public static LocalDate fromCalendarFields(Calendar calendar) { 133 if (calendar == null) { 134 throw new IllegalArgumentException("The calendar must not be null"); 135 } 136 return new LocalDate( 137 calendar.get(Calendar.YEAR), 138 calendar.get(Calendar.MONTH) + 1, 139 calendar.get(Calendar.DAY_OF_MONTH) 140 ); 141 } 142 143 /** 144 * Constructs a LocalDate from a <code>java.util.Date</code> 145 * using exactly the same field values. 146 * <p> 147 * Each field is queried from the Date and assigned to the LocalDate. 148 * This is useful if you have been using the Date as a local date, 149 * ignoring the zone. 150 * <p> 151 * One advantage of this method is that this method is unaffected if the 152 * version of the time zone data differs between the JDK and Joda-Time. 153 * That is because the local field values are transferred, calculated using 154 * the JDK time zone data and without using the Joda-Time time zone data. 155 * <p> 156 * This factory method always creates a LocalDate with ISO chronology. 157 * 158 * @param date the Date to extract fields from 159 * @return the created LocalDate 160 * @throws IllegalArgumentException if the calendar is null 161 * @throws IllegalArgumentException if the date is invalid for the ISO chronology 162 */ 163 public static LocalDate fromDateFields(Date date) { 164 if (date == null) { 165 throw new IllegalArgumentException("The date must not be null"); 166 } 167 return new LocalDate( 168 date.getYear() + 1900, 169 date.getMonth() + 1, 170 date.getDate() 171 ); 172 } 173 174 //----------------------------------------------------------------------- 175 /** 176 * Constructs an instance set to the current local time evaluated using 177 * ISO chronology in the default zone. 178 * <p> 179 * Once the constructor is completed, the zone is no longer used. 180 */ 181 public LocalDate() { 182 this(DateTimeUtils.currentTimeMillis(), ISOChronology.getInstance()); 183 } 184 185 /** 186 * Constructs an instance set to the current local time evaluated using 187 * ISO chronology in the specified zone. 188 * <p> 189 * If the specified time zone is null, the default zone is used. 190 * Once the constructor is completed, the zone is no longer used. 191 * 192 * @param zone the time zone, null means default zone 193 */ 194 public LocalDate(DateTimeZone zone) { 195 this(DateTimeUtils.currentTimeMillis(), ISOChronology.getInstance(zone)); 196 } 197 198 /** 199 * Constructs an instance set to the current local time evaluated using 200 * specified chronology. 201 * <p> 202 * If the chronology is null, ISO chronology in the default time zone is used. 203 * Once the constructor is completed, the zone is no longer used. 204 * 205 * @param chronology the chronology, null means ISOChronology in default zone 206 */ 207 public LocalDate(Chronology chronology) { 208 this(DateTimeUtils.currentTimeMillis(), chronology); 209 } 210 211 //----------------------------------------------------------------------- 212 /** 213 * Constructs an instance set to the local time defined by the specified 214 * instant evaluated using ISO chronology in the default zone. 215 * <p> 216 * Once the constructor is completed, the zone is no longer used. 217 * 218 * @param instant the milliseconds from 1970-01-01T00:00:00Z 219 */ 220 public LocalDate(long instant) { 221 this(instant, ISOChronology.getInstance()); 222 } 223 224 /** 225 * Constructs an instance set to the local time defined by the specified 226 * instant evaluated using ISO chronology in the specified zone. 227 * <p> 228 * If the specified time zone is null, the default zone is used. 229 * Once the constructor is completed, the zone is no longer used. 230 * 231 * @param instant the milliseconds from 1970-01-01T00:00:00Z 232 * @param zone the time zone, null means default zone 233 */ 234 public LocalDate(long instant, DateTimeZone zone) { 235 this(instant, ISOChronology.getInstance(zone)); 236 } 237 238 /** 239 * Constructs an instance set to the local time defined by the specified 240 * instant evaluated using the specified chronology. 241 * <p> 242 * If the chronology is null, ISO chronology in the default zone is used. 243 * Once the constructor is completed, the zone is no longer used. 244 * 245 * @param instant the milliseconds from 1970-01-01T00:00:00Z 246 * @param chronology the chronology, null means ISOChronology in default zone 247 */ 248 public LocalDate(long instant, Chronology chronology) { 249 chronology = DateTimeUtils.getChronology(chronology); 250 251 long localMillis = chronology.getZone().getMillisKeepLocal(DateTimeZone.UTC, instant); 252 chronology = chronology.withUTC(); 253 iLocalMillis = chronology.dayOfMonth().roundFloor(localMillis); 254 iChronology = chronology; 255 } 256 257 //----------------------------------------------------------------------- 258 /** 259 * Constructs an instance from an Object that represents a datetime. 260 * The time zone will be retrieved from the object if possible, 261 * otherwise the default time zone will be used. 262 * <p> 263 * If the object contains no chronology, <code>ISOChronology</code> is used. 264 * Once the constructor is completed, the zone is no longer used. 265 * <p> 266 * The recognised object types are defined in 267 * {@link org.joda.time.convert.ConverterManager ConverterManager} and 268 * include ReadablePartial, ReadableInstant, String, Calendar and Date. 269 * The String formats are described by {@link ISODateTimeFormat#localDateParser()}. 270 * The default String converter ignores the zone and only parses the field values. 271 * 272 * @param instant the datetime object 273 * @throws IllegalArgumentException if the instant is invalid 274 */ 275 public LocalDate(Object instant) { 276 this(instant, (Chronology) null); 277 } 278 279 /** 280 * Constructs an instance from an Object that represents a datetime, 281 * forcing the time zone to that specified. 282 * <p> 283 * If the object contains no chronology, <code>ISOChronology</code> is used. 284 * If the specified time zone is null, the default zone is used. 285 * Once the constructor is completed, the zone is no longer used. 286 * <p> 287 * The recognised object types are defined in 288 * {@link org.joda.time.convert.ConverterManager ConverterManager} and 289 * include ReadablePartial, ReadableInstant, String, Calendar and Date. 290 * The String formats are described by {@link ISODateTimeFormat#localDateParser()}. 291 * The default String converter ignores the zone and only parses the field values. 292 * 293 * @param instant the datetime object 294 * @param zone the time zone 295 * @throws IllegalArgumentException if the instant is invalid 296 */ 297 public LocalDate(Object instant, DateTimeZone zone) { 298 PartialConverter converter = ConverterManager.getInstance().getPartialConverter(instant); 299 Chronology chronology = converter.getChronology(instant, zone); 300 chronology = DateTimeUtils.getChronology(chronology); 301 iChronology = chronology.withUTC(); 302 int[] values = converter.getPartialValues(this, instant, chronology, ISODateTimeFormat.localDateParser()); 303 iLocalMillis = iChronology.getDateTimeMillis(values[0], values[1], values[2], 0); 304 } 305 306 /** 307 * Constructs an instance from an Object that represents a datetime, 308 * using the specified chronology. 309 * <p> 310 * If the chronology is null, ISO in the default time zone is used. 311 * Once the constructor is completed, the zone is no longer used. 312 * <p> 313 * The recognised object types are defined in 314 * {@link org.joda.time.convert.ConverterManager ConverterManager} and 315 * include ReadablePartial, ReadableInstant, String, Calendar and Date. 316 * The String formats are described by {@link ISODateTimeFormat#localDateParser()}. 317 * The default String converter ignores the zone and only parses the field values. 318 * 319 * @param instant the datetime object 320 * @param chronology the chronology 321 * @throws IllegalArgumentException if the instant is invalid 322 */ 323 public LocalDate(Object instant, Chronology chronology) { 324 PartialConverter converter = ConverterManager.getInstance().getPartialConverter(instant); 325 chronology = converter.getChronology(instant, chronology); 326 chronology = DateTimeUtils.getChronology(chronology); 327 iChronology = chronology.withUTC(); 328 int[] values = converter.getPartialValues(this, instant, chronology, ISODateTimeFormat.localDateParser()); 329 iLocalMillis = iChronology.getDateTimeMillis(values[0], values[1], values[2], 0); 330 } 331 332 //----------------------------------------------------------------------- 333 /** 334 * Constructs an instance set to the specified date and time 335 * using <code>ISOChronology</code>. 336 * 337 * @param year the year 338 * @param monthOfYear the month of the year 339 * @param dayOfMonth the day of the month 340 */ 341 public LocalDate( 342 int year, 343 int monthOfYear, 344 int dayOfMonth) { 345 this(year, monthOfYear, dayOfMonth, ISOChronology.getInstanceUTC()); 346 } 347 348 /** 349 * Constructs an instance set to the specified date and time 350 * using the specified chronology, whose zone is ignored. 351 * <p> 352 * If the chronology is null, <code>ISOChronology</code> is used. 353 * 354 * @param year the year 355 * @param monthOfYear the month of the year 356 * @param dayOfMonth the day of the month 357 * @param chronology the chronology, null means ISOChronology in default zone 358 */ 359 public LocalDate( 360 int year, 361 int monthOfYear, 362 int dayOfMonth, 363 Chronology chronology) { 364 super(); 365 chronology = DateTimeUtils.getChronology(chronology).withUTC(); 366 long instant = chronology.getDateTimeMillis(year, monthOfYear, dayOfMonth, 0); 367 iChronology = chronology; 368 iLocalMillis = instant; 369 } 370 371 //----------------------------------------------------------------------- 372 /** 373 * Gets the number of fields in this partial, which is three. 374 * The supported fields are Year, MonthOfYear and DayOfMonth. 375 * Note that all fields from day and above may in fact be queried via 376 * other methods. 377 * 378 * @return the field count, three 379 */ 380 public int size() { 381 return 3; 382 } 383 384 /** 385 * Gets the field for a specific index in the chronology specified. 386 * <p> 387 * This method must not use any instance variables. 388 * 389 * @param index the index to retrieve 390 * @param chrono the chronology to use 391 * @return the field 392 */ 393 protected DateTimeField getField(int index, Chronology chrono) { 394 switch (index) { 395 case YEAR: 396 return chrono.year(); 397 case MONTH_OF_YEAR: 398 return chrono.monthOfYear(); 399 case DAY_OF_MONTH: 400 return chrono.dayOfMonth(); 401 default: 402 throw new IndexOutOfBoundsException("Invalid index: " + index); 403 } 404 } 405 406 /** 407 * Gets the value of the field at the specifed index. 408 * <p> 409 * This method is required to support the <code>ReadablePartial</code> 410 * interface. The supported fields are Year, MonthOfYear and DayOfMonth. 411 * Note that all fields from day and above may in fact be queried via 412 * other methods. 413 * 414 * @param index the index, zero to two 415 * @return the value 416 * @throws IndexOutOfBoundsException if the index is invalid 417 */ 418 public int getValue(int index) { 419 switch (index) { 420 case YEAR: 421 return getChronology().year().get(getLocalMillis()); 422 case MONTH_OF_YEAR: 423 return getChronology().monthOfYear().get(getLocalMillis()); 424 case DAY_OF_MONTH: 425 return getChronology().dayOfMonth().get(getLocalMillis()); 426 default: 427 throw new IndexOutOfBoundsException("Invalid index: " + index); 428 } 429 } 430 431 //----------------------------------------------------------------------- 432 /** 433 * Get the value of one of the fields of a datetime. 434 * <p> 435 * This method gets the value of the specified field. 436 * For example: 437 * <pre> 438 * LocalDate dt = LocalDate.nowDefaultZone(); 439 * int year = dt.get(DateTimeFieldType.year()); 440 * </pre> 441 * 442 * @param fieldType a field type, usually obtained from DateTimeFieldType, not null 443 * @return the value of that field 444 * @throws IllegalArgumentException if the field type is null or unsupported 445 */ 446 public int get(DateTimeFieldType fieldType) { 447 if (fieldType == null) { 448 throw new IllegalArgumentException("The DateTimeFieldType must not be null"); 449 } 450 if (isSupported(fieldType) == false) { 451 throw new IllegalArgumentException("Field '" + fieldType + "' is not supported"); 452 } 453 return fieldType.getField(getChronology()).get(getLocalMillis()); 454 } 455 456 /** 457 * Checks if the field type specified is supported by this 458 * local date and chronology. 459 * This can be used to avoid exceptions in {@link #get(DateTimeFieldType)}. 460 * 461 * @param type a field type, usually obtained from DateTimeFieldType 462 * @return true if the field type is supported 463 */ 464 public boolean isSupported(DateTimeFieldType type) { 465 if (type == null) { 466 return false; 467 } 468 DurationFieldType durType = type.getDurationType(); 469 if (DATE_DURATION_TYPES.contains(durType) || 470 durType.getField(getChronology()).getUnitMillis() >= 471 getChronology().days().getUnitMillis()) { 472 return type.getField(getChronology()).isSupported(); 473 } 474 return false; 475 } 476 477 /** 478 * Checks if the duration type specified is supported by this 479 * local date and chronology. 480 * 481 * @param type a duration type, usually obtained from DurationFieldType 482 * @return true if the field type is supported 483 */ 484 public boolean isSupported(DurationFieldType type) { 485 if (type == null) { 486 return false; 487 } 488 DurationField field = type.getField(getChronology()); 489 if (DATE_DURATION_TYPES.contains(type) || 490 field.getUnitMillis() >= getChronology().days().getUnitMillis()) { 491 return field.isSupported(); 492 } 493 return false; 494 } 495 496 //----------------------------------------------------------------------- 497 /** 498 * Gets the local milliseconds from the Java epoch 499 * of 1970-01-01T00:00:00 (not fixed to any specific time zone). 500 * 501 * @return the number of milliseconds since 1970-01-01T00:00:00 502 * @since 1.5 (previously private) 503 */ 504 protected long getLocalMillis() { 505 return iLocalMillis; 506 } 507 508 /** 509 * Gets the chronology of the date. 510 * 511 * @return the Chronology that the date is using 512 */ 513 public Chronology getChronology() { 514 return iChronology; 515 } 516 517 //----------------------------------------------------------------------- 518 /** 519 * Compares this ReadablePartial with another returning true if the chronology, 520 * field types and values are equal. 521 * 522 * @param partial an object to check against 523 * @return true if fields and values are equal 524 */ 525 public boolean equals(Object partial) { 526 // override to perform faster 527 if (this == partial) { 528 return true; 529 } 530 if (partial instanceof LocalDate) { 531 LocalDate other = (LocalDate) partial; 532 if (iChronology.equals(other.iChronology)) { 533 return iLocalMillis == other.iLocalMillis; 534 } 535 } 536 return super.equals(partial); 537 } 538 539 /** 540 * Compares this partial with another returning an integer 541 * indicating the order. 542 * <p> 543 * The fields are compared in order, from largest to smallest. 544 * The first field that is non-equal is used to determine the result. 545 * <p> 546 * The specified object must be a partial instance whose field types 547 * match those of this partial. 548 * <p> 549 * NOTE: This implementation violates the Comparable contract. 550 * This method will accept any instance of ReadablePartial as input. 551 * However, it is possible that some implementations of ReadablePartial 552 * exist that do not extend AbstractPartial, and thus will throw a 553 * ClassCastException if compared in the opposite direction. 554 * The cause of this problem is that ReadablePartial doesn't define 555 * the compareTo() method, however we can't change that until v2.0. 556 * 557 * @param partial an object to check against 558 * @return negative if this is less, zero if equal, positive if greater 559 * @throws ClassCastException if the partial is the wrong class 560 * or if it has field types that don't match 561 * @throws NullPointerException if the partial is null 562 */ 563 public int compareTo(Object partial) { 564 // override to perform faster 565 if (this == partial) { 566 return 0; 567 } 568 if (partial instanceof LocalDate) { 569 LocalDate other = (LocalDate) partial; 570 if (iChronology.equals(other.iChronology)) { 571 return (iLocalMillis < other.iLocalMillis ? -1 : 572 (iLocalMillis == other.iLocalMillis ? 0 : 1)); 573 574 } 575 } 576 return super.compareTo(partial); 577 } 578 579 //----------------------------------------------------------------------- 580 /** 581 * Converts this LocalDate to a full datetime at the earliest valid time 582 * for the date using the default time zone. 583 * <p> 584 * The time will normally be midnight, as that is the earliest time on 585 * any given day. However, in some time zones when Daylight Savings Time 586 * starts, there is no midnight because time jumps from 11:59 to 01:00. 587 * This method handles that situation by returning 01:00 on that date. 588 * <p> 589 * This instance is immutable and unaffected by this method call. 590 * 591 * @return this date as a datetime at the start of the day 592 * @since 1.5 593 */ 594 public DateTime toDateTimeAtStartOfDay() { 595 return toDateTimeAtStartOfDay(null); 596 } 597 598 /** 599 * Converts this LocalDate to a full datetime at the earliest valid time 600 * for the date using the specified time zone. 601 * <p> 602 * The time will normally be midnight, as that is the earliest time on 603 * any given day. However, in some time zones when Daylight Savings Time 604 * starts, there is no midnight because time jumps from 11:59 to 01:00. 605 * This method handles that situation by returning 01:00 on that date. 606 * <p> 607 * This method uses the chronology from this instance plus the time zone 608 * specified. 609 * <p> 610 * This instance is immutable and unaffected by this method call. 611 * 612 * @param zone the zone to use, null means default zone 613 * @return this date as a datetime at the start of the day 614 * @since 1.5 615 */ 616 public DateTime toDateTimeAtStartOfDay(DateTimeZone zone) { 617 zone = DateTimeUtils.getZone(zone); 618 Chronology chrono = getChronology().withZone(zone); 619 long localMillis = getLocalMillis() + 6L * DateTimeConstants.MILLIS_PER_HOUR; 620 long instant = zone.convertLocalToUTC(localMillis, false); 621 instant = chrono.dayOfMonth().roundFloor(instant); 622 return new DateTime(instant, chrono); 623 } 624 625 //----------------------------------------------------------------------- 626 /** 627 * Converts this LocalDate to a full datetime at midnight using the default 628 * time zone. 629 * <p> 630 * This method will throw an exception if the default time zone switches 631 * to Daylight Savings Time at midnight and this LocalDate represents 632 * that switchover date. The problem is that there is no such time as 633 * midnight on the required date, and as such an exception is thrown. 634 * <p> 635 * This instance is immutable and unaffected by this method call. 636 * 637 * @return this date as a datetime at midnight 638 * @deprecated Use {@link #toDateTimeAtStartOfDay()} which won't throw an exception 639 */ 640 public DateTime toDateTimeAtMidnight() { 641 return toDateTimeAtMidnight(null); 642 } 643 644 /** 645 * Converts this LocalDate to a full datetime at midnight using the 646 * specified time zone. 647 * <p> 648 * This method will throw an exception if the time zone switches 649 * to Daylight Savings Time at midnight and this LocalDate represents 650 * that switchover date. The problem is that there is no such time as 651 * midnight on the required date, and as such an exception is thrown. 652 * <p> 653 * This method uses the chronology from this instance plus the time zone 654 * specified. 655 * <p> 656 * This instance is immutable and unaffected by this method call. 657 * 658 * @param zone the zone to use, null means default zone 659 * @return this date as a datetime at midnight 660 * @deprecated Use {@link #toDateTimeAtStartOfDay(DateTimeZone)} which won't throw an exception 661 */ 662 public DateTime toDateTimeAtMidnight(DateTimeZone zone) { 663 zone = DateTimeUtils.getZone(zone); 664 Chronology chrono = getChronology().withZone(zone); 665 return new DateTime(getYear(), getMonthOfYear(), getDayOfMonth(), 0, 0, 0, 0, chrono); 666 } 667 668 //----------------------------------------------------------------------- 669 /** 670 * Converts this LocalDate to a full datetime using the default time zone 671 * setting the date fields from this instance and the time fields from 672 * the current time. 673 * <p> 674 * This method will throw an exception if the datetime that would be 675 * created does not exist when the time zone is taken into account. 676 * <p> 677 * This instance is immutable and unaffected by this method call. 678 * 679 * @return this date as a datetime with the time as the current time 680 */ 681 public DateTime toDateTimeAtCurrentTime() { 682 return toDateTimeAtCurrentTime(null); 683 } 684 685 /** 686 * Converts this LocalDate to a full datetime using the specified time zone 687 * setting the date fields from this instance and the time fields from 688 * the current time. 689 * <p> 690 * This method uses the chronology from this instance plus the time zone 691 * specified. 692 * <p> 693 * This method will throw an exception if the datetime that would be 694 * created does not exist when the time zone is taken into account. 695 * <p> 696 * This instance is immutable and unaffected by this method call. 697 * 698 * @param zone the zone to use, null means default zone 699 * @return this date as a datetime with the time as the current time 700 */ 701 public DateTime toDateTimeAtCurrentTime(DateTimeZone zone) { 702 zone = DateTimeUtils.getZone(zone); 703 Chronology chrono = getChronology().withZone(zone); 704 long instantMillis = DateTimeUtils.currentTimeMillis(); 705 long resolved = chrono.set(this, instantMillis); 706 return new DateTime(resolved, chrono); 707 } 708 709 //----------------------------------------------------------------------- 710 /** 711 * Converts this LocalDate to a DateMidnight in the default time zone. 712 * <p> 713 * As from v1.5, you are recommended to avoid DateMidnight and use 714 * {@link #toDateTimeAtStartOfDay()} instead because of the exception 715 * detailed below. 716 * <p> 717 * This method will throw an exception if the default time zone switches 718 * to Daylight Savings Time at midnight and this LocalDate represents 719 * that switchover date. The problem is that there is no such time as 720 * midnight on the required date, and as such an exception is thrown. 721 * <p> 722 * This instance is immutable and unaffected by this method call. 723 * 724 * @return the DateMidnight instance in the default zone 725 */ 726 public DateMidnight toDateMidnight() { 727 return toDateMidnight(null); 728 } 729 730 /** 731 * Converts this LocalDate to a DateMidnight. 732 * <p> 733 * As from v1.5, you are recommended to avoid DateMidnight and use 734 * {@link #toDateTimeAtStartOfDay()} instead because of the exception 735 * detailed below. 736 * <p> 737 * This method will throw an exception if the time zone switches 738 * to Daylight Savings Time at midnight and this LocalDate represents 739 * that switchover date. The problem is that there is no such time as 740 * midnight on the required date, and as such an exception is thrown. 741 * <p> 742 * This instance is immutable and unaffected by this method call. 743 * 744 * @param zone the zone to get the DateMidnight in, null means default zone 745 * @return the DateMidnight instance 746 */ 747 public DateMidnight toDateMidnight(DateTimeZone zone) { 748 zone = DateTimeUtils.getZone(zone); 749 Chronology chrono = getChronology().withZone(zone); 750 return new DateMidnight(getYear(), getMonthOfYear(), getDayOfMonth(), chrono); 751 } 752 753 //----------------------------------------------------------------------- 754 /** 755 * Converts this object to a LocalDateTime using a LocalTime to fill in 756 * the missing fields. 757 * <p> 758 * The resulting chronology is determined by the chronology of this 759 * LocalDate. The chronology of the time must also match. 760 * If the time is null an exception is thrown. 761 * <p> 762 * This instance is immutable and unaffected by this method call. 763 * 764 * @param time the time of day to use, must not be null 765 * @return the LocalDateTime instance 766 * @throws IllegalArgumentException if the time is null 767 * @throws IllegalArgumentException if the chronology of the time does not match 768 * @since 1.5 769 */ 770 public LocalDateTime toLocalDateTime(LocalTime time) { 771 if (time == null) { 772 throw new IllegalArgumentException("The time must not be null"); 773 } 774 if (getChronology() != time.getChronology()) { 775 throw new IllegalArgumentException("The chronology of the time does not match"); 776 } 777 long localMillis = getLocalMillis() + time.getLocalMillis(); 778 return new LocalDateTime(localMillis, getChronology()); 779 } 780 781 //----------------------------------------------------------------------- 782 /** 783 * Converts this object to a DateTime using a LocalTime to fill in the 784 * missing fields and using the default time zone. 785 * <p> 786 * The resulting chronology is determined by the chronology of this 787 * LocalDate. The chronology of the time must match. 788 * If the time is null, the current time in the date's chronology is used. 789 * <p> 790 * This method will throw an exception if the datetime that would be 791 * created does not exist when the time zone is taken into account. 792 * <p> 793 * This instance is immutable and unaffected by this method call. 794 * 795 * @param time the time of day to use, null means current time 796 * @return the DateTime instance 797 * @throws IllegalArgumentException if the chronology of the time does not match 798 */ 799 public DateTime toDateTime(LocalTime time) { 800 return toDateTime(time, null); 801 } 802 803 /** 804 * Converts this object to a DateTime using a LocalTime to fill in the 805 * missing fields. 806 * <p> 807 * The resulting chronology is determined by the chronology of this 808 * LocalDate plus the time zone. The chronology of the time must match. 809 * If the time is null, the current time in the date's chronology is used. 810 * <p> 811 * This method will throw an exception if the datetime that would be 812 * created does not exist when the time zone is taken into account. 813 * <p> 814 * This instance is immutable and unaffected by this method call. 815 * 816 * @param time the time of day to use, null means current time 817 * @param zone the zone to get the DateTime in, null means default 818 * @return the DateTime instance 819 * @throws IllegalArgumentException if the chronology of the time does not match 820 */ 821 public DateTime toDateTime(LocalTime time, DateTimeZone zone) { 822 if (time != null && getChronology() != time.getChronology()) { 823 throw new IllegalArgumentException("The chronology of the time does not match"); 824 } 825 Chronology chrono = getChronology().withZone(zone); 826 long instant = DateTimeUtils.currentTimeMillis(); 827 instant = chrono.set(this, instant); 828 if (time != null) { 829 instant = chrono.set(time, instant); 830 } 831 return new DateTime(instant, chrono); 832 } 833 834 //----------------------------------------------------------------------- 835 /** 836 * Converts this object to an Interval representing the whole day 837 * in the default time zone. 838 * <p> 839 * The interval may have more or less than 24 hours if this is a daylight 840 * savings cutover date. 841 * <p> 842 * This instance is immutable and unaffected by this method call. 843 * 844 * @return a interval over the day 845 */ 846 public Interval toInterval() { 847 return toInterval(null); 848 } 849 850 /** 851 * Converts this object to an Interval representing the whole day. 852 * <p> 853 * The interval may have more or less than 24 hours if this is a daylight 854 * savings cutover date. 855 * <p> 856 * This instance is immutable and unaffected by this method call. 857 * 858 * @param zone the zone to get the Interval in, null means default 859 * @return a interval over the day 860 */ 861 public Interval toInterval(DateTimeZone zone) { 862 zone = DateTimeUtils.getZone(zone); 863 DateTime start = toDateTimeAtStartOfDay(zone); 864 DateTime end = plusDays(1).toDateTimeAtStartOfDay(zone); 865 return new Interval(start, end); 866 } 867 868 //----------------------------------------------------------------------- 869 /** 870 * Returns a copy of this date with different local millis. 871 * <p> 872 * The returned object will be a new instance of the same type. 873 * Only the millis will change, the chronology is kept. 874 * The returned object will be either be a new instance or <code>this</code>. 875 * 876 * @param newMillis the new millis, from 1970-01-01T00:00:00 877 * @return a copy of this date with different millis 878 */ 879 LocalDate withLocalMillis(long newMillis) { 880 newMillis = iChronology.dayOfMonth().roundFloor(newMillis); 881 return (newMillis == getLocalMillis() ? this : new LocalDate(newMillis, getChronology())); 882 } 883 884 //----------------------------------------------------------------------- 885 /** 886 * Returns a copy of this date with the partial set of fields replacing 887 * those from this instance. 888 * <p> 889 * For example, if the partial contains a year and a month then those two 890 * fields will be changed in the returned instance. 891 * Unsupported fields are ignored. 892 * If the partial is null, then <code>this</code> is returned. 893 * 894 * @param partial the partial set of fields to apply to this date, null ignored 895 * @return a copy of this date with a different set of fields 896 * @throws IllegalArgumentException if any value is invalid 897 */ 898 public LocalDate withFields(ReadablePartial partial) { 899 if (partial == null) { 900 return this; 901 } 902 return withLocalMillis(getChronology().set(partial, getLocalMillis())); 903 } 904 905 /** 906 * Returns a copy of this date with the specified field set to a new value. 907 * <p> 908 * For example, if the field type is <code>monthOfYear</code> then the 909 * month of year field will be changed in the returned instance. 910 * If the field type is null, then <code>this</code> is returned. 911 * <p> 912 * These two lines are equivalent: 913 * <pre> 914 * LocalDate updated = dt.withDayOfMonth(6); 915 * LocalDate updated = dt.withField(DateTimeFieldType.dayOfMonth(), 6); 916 * </pre> 917 * 918 * @param fieldType the field type to set, not null 919 * @param value the value to set 920 * @return a copy of this date with the field set 921 * @throws IllegalArgumentException if the field is null or unsupported 922 */ 923 public LocalDate withField(DateTimeFieldType fieldType, int value) { 924 if (fieldType == null) { 925 throw new IllegalArgumentException("Field must not be null"); 926 } 927 if (isSupported(fieldType) == false) { 928 throw new IllegalArgumentException("Field '" + fieldType + "' is not supported"); 929 } 930 long instant = fieldType.getField(getChronology()).set(getLocalMillis(), value); 931 return withLocalMillis(instant); 932 } 933 934 /** 935 * Returns a copy of this date with the value of the specified field increased. 936 * <p> 937 * If the addition is zero or the field is null, then <code>this</code> is returned. 938 * <p> 939 * These three lines are equivalent: 940 * <pre> 941 * LocalDate added = dt.withFieldAdded(DurationFieldType.years(), 6); 942 * LocalDate added = dt.plusYears(6); 943 * LocalDate added = dt.plus(Period.years(6)); 944 * </pre> 945 * 946 * @param fieldType the field type to add to, not null 947 * @param amount the amount to add 948 * @return a copy of this date with the field updated 949 * @throws IllegalArgumentException if the field is null or unsupported 950 * @throws ArithmeticException if the result exceeds the internal capacity 951 */ 952 public LocalDate withFieldAdded(DurationFieldType fieldType, int amount) { 953 if (fieldType == null) { 954 throw new IllegalArgumentException("Field must not be null"); 955 } 956 if (isSupported(fieldType) == false) { 957 throw new IllegalArgumentException("Field '" + fieldType + "' is not supported"); 958 } 959 if (amount == 0) { 960 return this; 961 } 962 long instant = fieldType.getField(getChronology()).add(getLocalMillis(), amount); 963 return withLocalMillis(instant); 964 } 965 966 //----------------------------------------------------------------------- 967 /** 968 * Returns a copy of this date with the specified period added. 969 * <p> 970 * If the addition is zero, then <code>this</code> is returned. 971 * <p> 972 * This method is typically used to add multiple copies of complex 973 * period instances. Adding one field is best achieved using methods 974 * like {@link #withFieldAdded(DurationFieldType, int)} 975 * or {@link #plusYears(int)}. 976 * <p> 977 * Unsupported time fields are ignored, thus adding a period of 24 hours 978 * will not have any effect. 979 * 980 * @param period the period to add to this one, null means zero 981 * @param scalar the amount of times to add, such as -1 to subtract once 982 * @return a copy of this date with the period added 983 * @throws ArithmeticException if the result exceeds the internal capacity 984 */ 985 public LocalDate withPeriodAdded(ReadablePeriod period, int scalar) { 986 if (period == null || scalar == 0) { 987 return this; 988 } 989 long instant = getLocalMillis(); 990 Chronology chrono = getChronology(); 991 for (int i = 0; i < period.size(); i++) { 992 long value = FieldUtils.safeMultiply(period.getValue(i), scalar); 993 DurationFieldType type = period.getFieldType(i); 994 if (isSupported(type)) { 995 instant = type.getField(chrono).add(instant, value); 996 } 997 } 998 return withLocalMillis(instant); 999 } 1000 1001 //----------------------------------------------------------------------- 1002 /** 1003 * Returns a copy of this date with the specified period added. 1004 * <p> 1005 * If the amount is zero or null, then <code>this</code> is returned. 1006 * <p> 1007 * This method is typically used to add complex period instances. 1008 * Adding one field is best achieved using methods 1009 * like {@link #plusYears(int)}. 1010 * <p> 1011 * Unsupported time fields are ignored, thus adding a period of 24 hours 1012 * will not have any effect. 1013 * 1014 * @param period the period to add to this one, null means zero 1015 * @return a copy of this date with the period added 1016 * @throws ArithmeticException if the result exceeds the internal capacity 1017 */ 1018 public LocalDate plus(ReadablePeriod period) { 1019 return withPeriodAdded(period, 1); 1020 } 1021 1022 //----------------------------------------------------------------------- 1023 /** 1024 * Returns a copy of this date plus the specified number of years. 1025 * <p> 1026 * This LocalDate instance is immutable and unaffected by this method call. 1027 * <p> 1028 * The following three lines are identical in effect: 1029 * <pre> 1030 * LocalDate added = dt.plusYears(6); 1031 * LocalDate added = dt.plus(Period.years(6)); 1032 * LocalDate added = dt.withFieldAdded(DurationFieldType.years(), 6); 1033 * </pre> 1034 * 1035 * @param years the amount of years to add, may be negative 1036 * @return the new LocalDate plus the increased years 1037 */ 1038 public LocalDate plusYears(int years) { 1039 if (years == 0) { 1040 return this; 1041 } 1042 long instant = getChronology().years().add(getLocalMillis(), years); 1043 return withLocalMillis(instant); 1044 } 1045 1046 /** 1047 * Returns a copy of this date plus the specified number of months. 1048 * <p> 1049 * This LocalDate instance is immutable and unaffected by this method call. 1050 * <p> 1051 * The following three lines are identical in effect: 1052 * <pre> 1053 * LocalDate added = dt.plusMonths(6); 1054 * LocalDate added = dt.plus(Period.months(6)); 1055 * LocalDate added = dt.withFieldAdded(DurationFieldType.months(), 6); 1056 * </pre> 1057 * 1058 * @param months the amount of months to add, may be negative 1059 * @return the new LocalDate plus the increased months 1060 */ 1061 public LocalDate plusMonths(int months) { 1062 if (months == 0) { 1063 return this; 1064 } 1065 long instant = getChronology().months().add(getLocalMillis(), months); 1066 return withLocalMillis(instant); 1067 } 1068 1069 /** 1070 * Returns a copy of this date plus the specified number of weeks. 1071 * <p> 1072 * This LocalDate instance is immutable and unaffected by this method call. 1073 * <p> 1074 * The following three lines are identical in effect: 1075 * <pre> 1076 * LocalDate added = dt.plusWeeks(6); 1077 * LocalDate added = dt.plus(Period.weeks(6)); 1078 * LocalDate added = dt.withFieldAdded(DurationFieldType.weeks(), 6); 1079 * </pre> 1080 * 1081 * @param weeks the amount of weeks to add, may be negative 1082 * @return the new LocalDate plus the increased weeks 1083 */ 1084 public LocalDate plusWeeks(int weeks) { 1085 if (weeks == 0) { 1086 return this; 1087 } 1088 long instant = getChronology().weeks().add(getLocalMillis(), weeks); 1089 return withLocalMillis(instant); 1090 } 1091 1092 /** 1093 * Returns a copy of this date plus the specified number of days. 1094 * <p> 1095 * This LocalDate instance is immutable and unaffected by this method call. 1096 * <p> 1097 * The following three lines are identical in effect: 1098 * <pre> 1099 * LocalDate added = dt.plusDays(6); 1100 * LocalDate added = dt.plus(Period.days(6)); 1101 * LocalDate added = dt.withFieldAdded(DurationFieldType.days(), 6); 1102 * </pre> 1103 * 1104 * @param days the amount of days to add, may be negative 1105 * @return the new LocalDate plus the increased days 1106 */ 1107 public LocalDate plusDays(int days) { 1108 if (days == 0) { 1109 return this; 1110 } 1111 long instant = getChronology().days().add(getLocalMillis(), days); 1112 return withLocalMillis(instant); 1113 } 1114 1115 //----------------------------------------------------------------------- 1116 /** 1117 * Returns a copy of this date with the specified period taken away. 1118 * <p> 1119 * If the amount is zero or null, then <code>this</code> is returned. 1120 * <p> 1121 * This method is typically used to subtract complex period instances. 1122 * Subtracting one field is best achieved using methods 1123 * like {@link #minusYears(int)}. 1124 * <p> 1125 * Unsupported time fields are ignored, thus subtracting a period of 24 hours 1126 * will not have any effect. 1127 * 1128 * @param period the period to reduce this instant by 1129 * @return a copy of this LocalDate with the period taken away 1130 * @throws ArithmeticException if the result exceeds the internal capacity 1131 */ 1132 public LocalDate minus(ReadablePeriod period) { 1133 return withPeriodAdded(period, -1); 1134 } 1135 1136 //----------------------------------------------------------------------- 1137 /** 1138 * Returns a copy of this date minus the specified number of years. 1139 * <p> 1140 * This LocalDate instance is immutable and unaffected by this method call. 1141 * <p> 1142 * The following three lines are identical in effect: 1143 * <pre> 1144 * LocalDate subtracted = dt.minusYears(6); 1145 * LocalDate subtracted = dt.minus(Period.years(6)); 1146 * LocalDate subtracted = dt.withFieldAdded(DurationFieldType.years(), -6); 1147 * </pre> 1148 * 1149 * @param years the amount of years to subtract, may be negative 1150 * @return the new LocalDate minus the increased years 1151 */ 1152 public LocalDate minusYears(int years) { 1153 if (years == 0) { 1154 return this; 1155 } 1156 long instant = getChronology().years().subtract(getLocalMillis(), years); 1157 return withLocalMillis(instant); 1158 } 1159 1160 /** 1161 * Returns a copy of this date minus the specified number of months. 1162 * <p> 1163 * This LocalDate instance is immutable and unaffected by this method call. 1164 * <p> 1165 * The following three lines are identical in effect: 1166 * <pre> 1167 * LocalDate subtracted = dt.minusMonths(6); 1168 * LocalDate subtracted = dt.minus(Period.months(6)); 1169 * LocalDate subtracted = dt.withFieldAdded(DurationFieldType.months(), -6); 1170 * </pre> 1171 * 1172 * @param months the amount of months to subtract, may be negative 1173 * @return the new LocalDate minus the increased months 1174 */ 1175 public LocalDate minusMonths(int months) { 1176 if (months == 0) { 1177 return this; 1178 } 1179 long instant = getChronology().months().subtract(getLocalMillis(), months); 1180 return withLocalMillis(instant); 1181 } 1182 1183 /** 1184 * Returns a copy of this date minus the specified number of weeks. 1185 * <p> 1186 * This LocalDate instance is immutable and unaffected by this method call. 1187 * <p> 1188 * The following three lines are identical in effect: 1189 * <pre> 1190 * LocalDate subtracted = dt.minusWeeks(6); 1191 * LocalDate subtracted = dt.minus(Period.weeks(6)); 1192 * LocalDate subtracted = dt.withFieldAdded(DurationFieldType.weeks(), -6); 1193 * </pre> 1194 * 1195 * @param weeks the amount of weeks to subtract, may be negative 1196 * @return the new LocalDate minus the increased weeks 1197 */ 1198 public LocalDate minusWeeks(int weeks) { 1199 if (weeks == 0) { 1200 return this; 1201 } 1202 long instant = getChronology().weeks().subtract(getLocalMillis(), weeks); 1203 return withLocalMillis(instant); 1204 } 1205 1206 /** 1207 * Returns a copy of this date minus the specified number of days. 1208 * <p> 1209 * This LocalDate instance is immutable and unaffected by this method call. 1210 * <p> 1211 * The following three lines are identical in effect: 1212 * <pre> 1213 * LocalDate subtracted = dt.minusDays(6); 1214 * LocalDate subtracted = dt.minus(Period.days(6)); 1215 * LocalDate subtracted = dt.withFieldAdded(DurationFieldType.days(), -6); 1216 * </pre> 1217 * 1218 * @param days the amount of days to subtract, may be negative 1219 * @return the new LocalDate minus the increased days 1220 */ 1221 public LocalDate minusDays(int days) { 1222 if (days == 0) { 1223 return this; 1224 } 1225 long instant = getChronology().days().subtract(getLocalMillis(), days); 1226 return withLocalMillis(instant); 1227 } 1228 1229 //----------------------------------------------------------------------- 1230 /** 1231 * Gets the property object for the specified type, which contains many 1232 * useful methods. 1233 * 1234 * @param fieldType the field type to get the chronology for 1235 * @return the property object 1236 * @throws IllegalArgumentException if the field is null or unsupported 1237 */ 1238 public Property property(DateTimeFieldType fieldType) { 1239 if (fieldType == null) { 1240 throw new IllegalArgumentException("The DateTimeFieldType must not be null"); 1241 } 1242 if (isSupported(fieldType) == false) { 1243 throw new IllegalArgumentException("Field '" + fieldType + "' is not supported"); 1244 } 1245 return new Property(this, fieldType.getField(getChronology())); 1246 } 1247 1248 //----------------------------------------------------------------------- 1249 /** 1250 * Get the era field value. 1251 * 1252 * @return the era 1253 */ 1254 public int getEra() { 1255 return getChronology().era().get(getLocalMillis()); 1256 } 1257 1258 /** 1259 * Get the year of era field value. 1260 * 1261 * @return the year of era 1262 */ 1263 public int getCenturyOfEra() { 1264 return getChronology().centuryOfEra().get(getLocalMillis()); 1265 } 1266 1267 /** 1268 * Get the year of era field value. 1269 * 1270 * @return the year of era 1271 */ 1272 public int getYearOfEra() { 1273 return getChronology().yearOfEra().get(getLocalMillis()); 1274 } 1275 1276 /** 1277 * Get the year of century field value. 1278 * 1279 * @return the year of century 1280 */ 1281 public int getYearOfCentury() { 1282 return getChronology().yearOfCentury().get(getLocalMillis()); 1283 } 1284 1285 /** 1286 * Get the year field value. 1287 * 1288 * @return the year 1289 */ 1290 public int getYear() { 1291 return getChronology().year().get(getLocalMillis()); 1292 } 1293 1294 /** 1295 * Get the weekyear field value. 1296 * <p> 1297 * The weekyear is the year that matches with the weekOfWeekyear field. 1298 * In the standard ISO8601 week algorithm, the first week of the year 1299 * is that in which at least 4 days are in the year. As a result of this 1300 * definition, day 1 of the first week may be in the previous year. 1301 * The weekyear allows you to query the effective year for that day. 1302 * 1303 * @return the weekyear 1304 */ 1305 public int getWeekyear() { 1306 return getChronology().weekyear().get(getLocalMillis()); 1307 } 1308 1309 /** 1310 * Get the month of year field value. 1311 * 1312 * @return the month of year 1313 */ 1314 public int getMonthOfYear() { 1315 return getChronology().monthOfYear().get(getLocalMillis()); 1316 } 1317 1318 /** 1319 * Get the week of weekyear field value. 1320 * 1321 * @return the week of a week based year 1322 */ 1323 public int getWeekOfWeekyear() { 1324 return getChronology().weekOfWeekyear().get(getLocalMillis()); 1325 } 1326 1327 /** 1328 * Get the day of year field value. 1329 * 1330 * @return the day of year 1331 */ 1332 public int getDayOfYear() { 1333 return getChronology().dayOfYear().get(getLocalMillis()); 1334 } 1335 1336 /** 1337 * Get the day of month field value. 1338 * <p> 1339 * The values for the day of month are defined in {@link org.joda.time.DateTimeConstants}. 1340 * 1341 * @return the day of month 1342 */ 1343 public int getDayOfMonth() { 1344 return getChronology().dayOfMonth().get(getLocalMillis()); 1345 } 1346 1347 /** 1348 * Get the day of week field value. 1349 * <p> 1350 * The values for the day of week are defined in {@link org.joda.time.DateTimeConstants}. 1351 * 1352 * @return the day of week 1353 */ 1354 public int getDayOfWeek() { 1355 return getChronology().dayOfWeek().get(getLocalMillis()); 1356 } 1357 1358 //----------------------------------------------------------------------- 1359 /** 1360 * Returns a copy of this date with the era field updated. 1361 * <p> 1362 * LocalDate is immutable, so there are no set methods. 1363 * Instead, this method returns a new instance with the value of 1364 * era changed. 1365 * 1366 * @param era the era to set 1367 * @return a copy of this object with the field set 1368 * @throws IllegalArgumentException if the value is invalid 1369 */ 1370 public LocalDate withEra(int era) { 1371 return withLocalMillis(getChronology().era().set(getLocalMillis(), era)); 1372 } 1373 1374 /** 1375 * Returns a copy of this date with the century of era field updated. 1376 * <p> 1377 * LocalDate is immutable, so there are no set methods. 1378 * Instead, this method returns a new instance with the value of 1379 * century of era changed. 1380 * 1381 * @param centuryOfEra the centurey of era to set 1382 * @return a copy of this object with the field set 1383 * @throws IllegalArgumentException if the value is invalid 1384 */ 1385 public LocalDate withCenturyOfEra(int centuryOfEra) { 1386 return withLocalMillis(getChronology().centuryOfEra().set(getLocalMillis(), centuryOfEra)); 1387 } 1388 1389 /** 1390 * Returns a copy of this date with the year of era field updated. 1391 * <p> 1392 * LocalDate is immutable, so there are no set methods. 1393 * Instead, this method returns a new instance with the value of 1394 * year of era changed. 1395 * 1396 * @param yearOfEra the year of era to set 1397 * @return a copy of this object with the field set 1398 * @throws IllegalArgumentException if the value is invalid 1399 */ 1400 public LocalDate withYearOfEra(int yearOfEra) { 1401 return withLocalMillis(getChronology().yearOfEra().set(getLocalMillis(), yearOfEra)); 1402 } 1403 1404 /** 1405 * Returns a copy of this date with the year of century field updated. 1406 * <p> 1407 * LocalDate is immutable, so there are no set methods. 1408 * Instead, this method returns a new instance with the value of 1409 * year of century changed. 1410 * 1411 * @param yearOfCentury the year of century to set 1412 * @return a copy of this object with the field set 1413 * @throws IllegalArgumentException if the value is invalid 1414 */ 1415 public LocalDate withYearOfCentury(int yearOfCentury) { 1416 return withLocalMillis(getChronology().yearOfCentury().set(getLocalMillis(), yearOfCentury)); 1417 } 1418 1419 /** 1420 * Returns a copy of this date with the year field updated. 1421 * <p> 1422 * LocalDate is immutable, so there are no set methods. 1423 * Instead, this method returns a new instance with the value of 1424 * year changed. 1425 * 1426 * @param year the year to set 1427 * @return a copy of this object with the field set 1428 * @throws IllegalArgumentException if the value is invalid 1429 */ 1430 public LocalDate withYear(int year) { 1431 return withLocalMillis(getChronology().year().set(getLocalMillis(), year)); 1432 } 1433 1434 /** 1435 * Returns a copy of this date with the weekyear field updated. 1436 * <p> 1437 * LocalDate is immutable, so there are no set methods. 1438 * Instead, this method returns a new instance with the value of 1439 * weekyear changed. 1440 * 1441 * @param weekyear the weekyear to set 1442 * @return a copy of this object with the field set 1443 * @throws IllegalArgumentException if the value is invalid 1444 */ 1445 public LocalDate withWeekyear(int weekyear) { 1446 return withLocalMillis(getChronology().weekyear().set(getLocalMillis(), weekyear)); 1447 } 1448 1449 /** 1450 * Returns a copy of this date with the month of year field updated. 1451 * <p> 1452 * LocalDate is immutable, so there are no set methods. 1453 * Instead, this method returns a new instance with the value of 1454 * month of year changed. 1455 * 1456 * @param monthOfYear the month of year to set 1457 * @return a copy of this object with the field set 1458 * @throws IllegalArgumentException if the value is invalid 1459 */ 1460 public LocalDate withMonthOfYear(int monthOfYear) { 1461 return withLocalMillis(getChronology().monthOfYear().set(getLocalMillis(), monthOfYear)); 1462 } 1463 1464 /** 1465 * Returns a copy of this date with the week of weekyear field updated. 1466 * <p> 1467 * LocalDate is immutable, so there are no set methods. 1468 * Instead, this method returns a new instance with the value of 1469 * week of weekyear changed. 1470 * 1471 * @param weekOfWeekyear the week of weekyear to set 1472 * @return a copy of this object with the field set 1473 * @throws IllegalArgumentException if the value is invalid 1474 */ 1475 public LocalDate withWeekOfWeekyear(int weekOfWeekyear) { 1476 return withLocalMillis(getChronology().weekOfWeekyear().set(getLocalMillis(), weekOfWeekyear)); 1477 } 1478 1479 /** 1480 * Returns a copy of this date with the day of year field updated. 1481 * <p> 1482 * LocalDate is immutable, so there are no set methods. 1483 * Instead, this method returns a new instance with the value of 1484 * day of year changed. 1485 * 1486 * @param dayOfYear the day of year to set 1487 * @return a copy of this object with the field set 1488 * @throws IllegalArgumentException if the value is invalid 1489 */ 1490 public LocalDate withDayOfYear(int dayOfYear) { 1491 return withLocalMillis(getChronology().dayOfYear().set(getLocalMillis(), dayOfYear)); 1492 } 1493 1494 /** 1495 * Returns a copy of this date with the day of month field updated. 1496 * <p> 1497 * LocalDate is immutable, so there are no set methods. 1498 * Instead, this method returns a new instance with the value of 1499 * day of month changed. 1500 * 1501 * @param dayOfMonth the day of month to set 1502 * @return a copy of this object with the field set 1503 * @throws IllegalArgumentException if the value is invalid 1504 */ 1505 public LocalDate withDayOfMonth(int dayOfMonth) { 1506 return withLocalMillis(getChronology().dayOfMonth().set(getLocalMillis(), dayOfMonth)); 1507 } 1508 1509 /** 1510 * Returns a copy of this date with the day of week field updated. 1511 * <p> 1512 * LocalDate is immutable, so there are no set methods. 1513 * Instead, this method returns a new instance with the value of 1514 * day of week changed. 1515 * 1516 * @param dayOfWeek the day of week to set 1517 * @return a copy of this object with the field set 1518 * @throws IllegalArgumentException if the value is invalid 1519 */ 1520 public LocalDate withDayOfWeek(int dayOfWeek) { 1521 return withLocalMillis(getChronology().dayOfWeek().set(getLocalMillis(), dayOfWeek)); 1522 } 1523 1524 //----------------------------------------------------------------------- 1525 /** 1526 * Get the era property which provides access to advanced functionality. 1527 * 1528 * @return the era property 1529 */ 1530 public Property era() { 1531 return new Property(this, getChronology().era()); 1532 } 1533 1534 /** 1535 * Get the century of era property which provides access to advanced functionality. 1536 * 1537 * @return the year of era property 1538 */ 1539 public Property centuryOfEra() { 1540 return new Property(this, getChronology().centuryOfEra()); 1541 } 1542 1543 /** 1544 * Get the year of century property which provides access to advanced functionality. 1545 * 1546 * @return the year of era property 1547 */ 1548 public Property yearOfCentury() { 1549 return new Property(this, getChronology().yearOfCentury()); 1550 } 1551 1552 /** 1553 * Get the year of era property which provides access to advanced functionality. 1554 * 1555 * @return the year of era property 1556 */ 1557 public Property yearOfEra() { 1558 return new Property(this, getChronology().yearOfEra()); 1559 } 1560 1561 /** 1562 * Get the year property which provides access to advanced functionality. 1563 * 1564 * @return the year property 1565 */ 1566 public Property year() { 1567 return new Property(this, getChronology().year()); 1568 } 1569 1570 /** 1571 * Get the weekyear property which provides access to advanced functionality. 1572 * 1573 * @return the weekyear property 1574 */ 1575 public Property weekyear() { 1576 return new Property(this, getChronology().weekyear()); 1577 } 1578 1579 /** 1580 * Get the month of year property which provides access to advanced functionality. 1581 * 1582 * @return the month of year property 1583 */ 1584 public Property monthOfYear() { 1585 return new Property(this, getChronology().monthOfYear()); 1586 } 1587 1588 /** 1589 * Get the week of a week based year property which provides access to advanced functionality. 1590 * 1591 * @return the week of a week based year property 1592 */ 1593 public Property weekOfWeekyear() { 1594 return new Property(this, getChronology().weekOfWeekyear()); 1595 } 1596 1597 /** 1598 * Get the day of year property which provides access to advanced functionality. 1599 * 1600 * @return the day of year property 1601 */ 1602 public Property dayOfYear() { 1603 return new Property(this, getChronology().dayOfYear()); 1604 } 1605 1606 /** 1607 * Get the day of month property which provides access to advanced functionality. 1608 * 1609 * @return the day of month property 1610 */ 1611 public Property dayOfMonth() { 1612 return new Property(this, getChronology().dayOfMonth()); 1613 } 1614 1615 /** 1616 * Get the day of week property which provides access to advanced functionality. 1617 * 1618 * @return the day of week property 1619 */ 1620 public Property dayOfWeek() { 1621 return new Property(this, getChronology().dayOfWeek()); 1622 } 1623 1624 //----------------------------------------------------------------------- 1625 /** 1626 * Output the date time in ISO8601 format (yyyy-MM-dd). 1627 * 1628 * @return ISO8601 time formatted string. 1629 */ 1630 public String toString() { 1631 return ISODateTimeFormat.date().print(this); 1632 } 1633 1634 /** 1635 * Output the date using the specified format pattern. 1636 * 1637 * @param pattern the pattern specification, null means use <code>toString</code> 1638 * @see org.joda.time.format.DateTimeFormat 1639 */ 1640 public String toString(String pattern) { 1641 if (pattern == null) { 1642 return toString(); 1643 } 1644 return DateTimeFormat.forPattern(pattern).print(this); 1645 } 1646 1647 /** 1648 * Output the date using the specified format pattern. 1649 * 1650 * @param pattern the pattern specification, null means use <code>toString</code> 1651 * @param locale Locale to use, null means default 1652 * @see org.joda.time.format.DateTimeFormat 1653 */ 1654 public String toString(String pattern, Locale locale) throws IllegalArgumentException { 1655 if (pattern == null) { 1656 return toString(); 1657 } 1658 return DateTimeFormat.forPattern(pattern).withLocale(locale).print(this); 1659 } 1660 1661 //----------------------------------------------------------------------- 1662 /** 1663 * LocalDate.Property binds a LocalDate to a DateTimeField allowing 1664 * powerful datetime functionality to be easily accessed. 1665 * <p> 1666 * The simplest use of this class is as an alternative get method, here used to 1667 * get the year '1972' (as an int) and the month 'December' (as a String). 1668 * <pre> 1669 * LocalDate dt = new LocalDate(1972, 12, 3, 0, 0); 1670 * int year = dt.year().get(); 1671 * String monthStr = dt.month().getAsText(); 1672 * </pre> 1673 * <p> 1674 * Methods are also provided that allow date modification. These return 1675 * new instances of LocalDate - they do not modify the original. The example 1676 * below yields two independent immutable date objects 20 years apart. 1677 * <pre> 1678 * LocalDate dt = new LocalDate(1972, 12, 3); 1679 * LocalDate dt1920 = dt.year().setCopy(1920); 1680 * </pre> 1681 * <p> 1682 * LocalDate.Property itself is thread-safe and immutable, as well as the 1683 * LocalDate being operated on. 1684 * 1685 * @author Stephen Colebourne 1686 * @author Brian S O'Neill 1687 * @since 1.3 1688 */ 1689 public static final class Property extends AbstractReadableInstantFieldProperty { 1690 1691 /** Serialization version */ 1692 private static final long serialVersionUID = -3193829732634L; 1693 1694 /** The instant this property is working against */ 1695 private transient LocalDate iInstant; 1696 /** The field this property is working against */ 1697 private transient DateTimeField iField; 1698 1699 /** 1700 * Constructor. 1701 * 1702 * @param instant the instant to set 1703 * @param field the field to use 1704 */ 1705 Property(LocalDate instant, DateTimeField field) { 1706 super(); 1707 iInstant = instant; 1708 iField = field; 1709 } 1710 1711 /** 1712 * Writes the property in a safe serialization format. 1713 */ 1714 private void writeObject(ObjectOutputStream oos) throws IOException { 1715 oos.writeObject(iInstant); 1716 oos.writeObject(iField.getType()); 1717 } 1718 1719 /** 1720 * Reads the property from a safe serialization format. 1721 */ 1722 private void readObject(ObjectInputStream oos) throws IOException, ClassNotFoundException { 1723 iInstant = (LocalDate) oos.readObject(); 1724 DateTimeFieldType type = (DateTimeFieldType) oos.readObject(); 1725 iField = type.getField(iInstant.getChronology()); 1726 } 1727 1728 //----------------------------------------------------------------------- 1729 /** 1730 * Gets the field being used. 1731 * 1732 * @return the field 1733 */ 1734 public DateTimeField getField() { 1735 return iField; 1736 } 1737 1738 /** 1739 * Gets the milliseconds of the date that this property is linked to. 1740 * 1741 * @return the milliseconds 1742 */ 1743 protected long getMillis() { 1744 return iInstant.getLocalMillis(); 1745 } 1746 1747 /** 1748 * Gets the chronology of the datetime that this property is linked to. 1749 * 1750 * @return the chronology 1751 * @since 1.4 1752 */ 1753 protected Chronology getChronology() { 1754 return iInstant.getChronology(); 1755 } 1756 1757 /** 1758 * Gets the LocalDate object linked to this property. 1759 * 1760 * @return the linked LocalDate 1761 */ 1762 public LocalDate getLocalDate() { 1763 return iInstant; 1764 } 1765 1766 //----------------------------------------------------------------------- 1767 /** 1768 * Adds to this field in a copy of this LocalDate. 1769 * <p> 1770 * The LocalDate attached to this property is unchanged by this call. 1771 * 1772 * @param value the value to add to the field in the copy 1773 * @return a copy of the LocalDate with the field value changed 1774 * @throws IllegalArgumentException if the value isn't valid 1775 */ 1776 public LocalDate addToCopy(int value) { 1777 return iInstant.withLocalMillis(iField.add(iInstant.getLocalMillis(), value)); 1778 } 1779 1780 /** 1781 * Adds to this field, possibly wrapped, in a copy of this LocalDate. 1782 * A field wrapped operation only changes this field. 1783 * Thus 31st January addWrapField one day goes to the 1st January. 1784 * <p> 1785 * The LocalDate attached to this property is unchanged by this call. 1786 * 1787 * @param value the value to add to the field in the copy 1788 * @return a copy of the LocalDate with the field value changed 1789 * @throws IllegalArgumentException if the value isn't valid 1790 */ 1791 public LocalDate addWrapFieldToCopy(int value) { 1792 return iInstant.withLocalMillis(iField.addWrapField(iInstant.getLocalMillis(), value)); 1793 } 1794 1795 //----------------------------------------------------------------------- 1796 /** 1797 * Sets this field in a copy of the LocalDate. 1798 * <p> 1799 * The LocalDate attached to this property is unchanged by this call. 1800 * 1801 * @param value the value to set the field in the copy to 1802 * @return a copy of the LocalDate with the field value changed 1803 * @throws IllegalArgumentException if the value isn't valid 1804 */ 1805 public LocalDate setCopy(int value) { 1806 return iInstant.withLocalMillis(iField.set(iInstant.getLocalMillis(), value)); 1807 } 1808 1809 /** 1810 * Sets this field in a copy of the LocalDate to a parsed text value. 1811 * <p> 1812 * The LocalDate attached to this property is unchanged by this call. 1813 * 1814 * @param text the text value to set 1815 * @param locale optional locale to use for selecting a text symbol 1816 * @return a copy of the LocalDate with the field value changed 1817 * @throws IllegalArgumentException if the text value isn't valid 1818 */ 1819 public LocalDate setCopy(String text, Locale locale) { 1820 return iInstant.withLocalMillis(iField.set(iInstant.getLocalMillis(), text, locale)); 1821 } 1822 1823 /** 1824 * Sets this field in a copy of the LocalDate to a parsed text value. 1825 * <p> 1826 * The LocalDate attached to this property is unchanged by this call. 1827 * 1828 * @param text the text value to set 1829 * @return a copy of the LocalDate with the field value changed 1830 * @throws IllegalArgumentException if the text value isn't valid 1831 */ 1832 public LocalDate setCopy(String text) { 1833 return setCopy(text, null); 1834 } 1835 1836 //----------------------------------------------------------------------- 1837 /** 1838 * Returns a new LocalDate with this field set to the maximum value 1839 * for this field. 1840 * <p> 1841 * This operation is useful for obtaining a LocalDate on the last day 1842 * of the month, as month lengths vary. 1843 * <pre> 1844 * LocalDate lastDayOfMonth = dt.dayOfMonth().withMaximumValue(); 1845 * </pre> 1846 * <p> 1847 * The LocalDate attached to this property is unchanged by this call. 1848 * 1849 * @return a copy of the LocalDate with this field set to its maximum 1850 */ 1851 public LocalDate withMaximumValue() { 1852 return setCopy(getMaximumValue()); 1853 } 1854 1855 /** 1856 * Returns a new LocalDate with this field set to the minimum value 1857 * for this field. 1858 * <p> 1859 * The LocalDate attached to this property is unchanged by this call. 1860 * 1861 * @return a copy of the LocalDate with this field set to its minimum 1862 */ 1863 public LocalDate withMinimumValue() { 1864 return setCopy(getMinimumValue()); 1865 } 1866 1867 //----------------------------------------------------------------------- 1868 /** 1869 * Rounds to the lowest whole unit of this field on a copy of this 1870 * LocalDate. 1871 * <p> 1872 * For example, rounding floor on the hourOfDay field of a LocalDate 1873 * where the time is 10:30 would result in new LocalDate with the 1874 * time of 10:00. 1875 * 1876 * @return a copy of the LocalDate with the field value changed 1877 */ 1878 public LocalDate roundFloorCopy() { 1879 return iInstant.withLocalMillis(iField.roundFloor(iInstant.getLocalMillis())); 1880 } 1881 1882 /** 1883 * Rounds to the highest whole unit of this field on a copy of this 1884 * LocalDate. 1885 * <p> 1886 * For example, rounding floor on the hourOfDay field of a LocalDate 1887 * where the time is 10:30 would result in new LocalDate with the 1888 * time of 11:00. 1889 * 1890 * @return a copy of the LocalDate with the field value changed 1891 */ 1892 public LocalDate roundCeilingCopy() { 1893 return iInstant.withLocalMillis(iField.roundCeiling(iInstant.getLocalMillis())); 1894 } 1895 1896 /** 1897 * Rounds to the nearest whole unit of this field on a copy of this 1898 * LocalDate, favoring the floor if halfway. 1899 * 1900 * @return a copy of the LocalDate with the field value changed 1901 */ 1902 public LocalDate roundHalfFloorCopy() { 1903 return iInstant.withLocalMillis(iField.roundHalfFloor(iInstant.getLocalMillis())); 1904 } 1905 1906 /** 1907 * Rounds to the nearest whole unit of this field on a copy of this 1908 * LocalDate, favoring the ceiling if halfway. 1909 * 1910 * @return a copy of the LocalDate with the field value changed 1911 */ 1912 public LocalDate roundHalfCeilingCopy() { 1913 return iInstant.withLocalMillis(iField.roundHalfCeiling(iInstant.getLocalMillis())); 1914 } 1915 1916 /** 1917 * Rounds to the nearest whole unit of this field on a copy of this 1918 * LocalDate. If halfway, the ceiling is favored over the floor 1919 * only if it makes this field's value even. 1920 * 1921 * @return a copy of the LocalDate with the field value changed 1922 */ 1923 public LocalDate roundHalfEvenCopy() { 1924 return iInstant.withLocalMillis(iField.roundHalfEven(iInstant.getLocalMillis())); 1925 } 1926 } 1927 1928 }