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