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