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