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 */
016package org.joda.time;
017
018import java.io.IOException;
019import java.io.ObjectInputStream;
020import java.io.ObjectOutputStream;
021import java.io.Serializable;
022import java.util.Calendar;
023import java.util.Date;
024import java.util.HashSet;
025import java.util.Locale;
026import java.util.Set;
027
028import org.joda.time.base.BaseLocal;
029import org.joda.time.chrono.ISOChronology;
030import org.joda.time.convert.ConverterManager;
031import org.joda.time.convert.PartialConverter;
032import org.joda.time.field.AbstractReadableInstantFieldProperty;
033import org.joda.time.field.FieldUtils;
034import org.joda.time.format.DateTimeFormat;
035import 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 */
077public 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}