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    }