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 }