001    /*
002     *  Copyright 2001-2006 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.Locale;
023    
024    import org.joda.time.base.BaseDateTime;
025    import org.joda.time.field.AbstractReadableInstantFieldProperty;
026    import org.joda.time.format.ISODateTimeFormat;
027    
028    /**
029     * DateMidnight defines a date where the time component is fixed at midnight.
030     * The class uses a time zone, thus midnight is local unless a UTC time zone is used.
031     * <p>
032     * It is important to emphasise that this class represents the time of midnight on
033     * any given day.
034     * Note that midnight is defined as 00:00, which is at the very start of a day.
035     * <p>
036     * This class does not represent a day, but the millisecond instant at midnight.
037     * If you need a class that represents the whole day, then an {@link Interval} or
038     * a {@link LocalDate} may be more suitable.
039     * <p>
040     * This class uses a Chronology internally. The Chronology determines how the
041     * millisecond instant value is converted into the date time fields.
042     * The default Chronology is <code>ISOChronology</code> which is the agreed
043     * international standard and compatable with the modern Gregorian calendar.
044     *
045     * <p>Each individual field can be queried in two ways:
046     * <ul>
047     * <li><code>getDayOfMonth()</code>
048     * <li><code>dayOfMonth().get()</code>
049     * </ul>
050     * The second technique also provides access to other useful methods on the
051     * field:
052     * <ul>
053     * <li>numeric value
054     * <li>text value
055     * <li>short text value
056     * <li>maximum/minimum values
057     * <li>add/subtract
058     * <li>set
059     * <li>rounding
060     * </ul>
061     *
062     * <p>
063     * DateMidnight is thread-safe and immutable, provided that the Chronology is as well.
064     * All standard Chronology classes supplied are thread-safe and immutable.
065     *
066     * @author Stephen Colebourne
067     * @since 1.0
068     */
069    public final class DateMidnight
070            extends BaseDateTime
071            implements ReadableDateTime, Serializable {
072        
073        /** Serialization lock */
074        private static final long serialVersionUID = 156371964018738L;
075    
076        // Constructors
077        //-----------------------------------------------------------------------
078        /**
079         * Constructs an instance set to the current system millisecond time
080         * using <code>ISOChronology</code> in the default time zone.
081         * The constructed object will have a local time of midnight.
082         */
083        public DateMidnight() {
084            super();
085        }
086    
087        /**
088         * Constructs an instance set to the current system millisecond time
089         * using <code>ISOChronology</code> in the specified time zone.
090         * The constructed object will have a local time of midnight.
091         * <p>
092         * If the specified time zone is null, the default zone is used.
093         *
094         * @param zone  the time zone, null means default zone
095         */
096        public DateMidnight(DateTimeZone zone) {
097            super(zone);
098        }
099    
100        /**
101         * Constructs an instance set to the current system millisecond time
102         * using the specified chronology.
103         * The constructed object will have a local time of midnight.
104         * <p>
105         * If the chronology is null, <code>ISOChronology</code>
106         * in the default time zone is used.
107         *
108         * @param chronology  the chronology, null means ISOChronology in default zone
109         */
110        public DateMidnight(Chronology chronology) {
111            super(chronology);
112        }
113    
114        //-----------------------------------------------------------------------
115        /**
116         * Constructs an instance set to the milliseconds from 1970-01-01T00:00:00Z
117         * using <code>ISOChronology</code> in the default time zone.
118         * The constructed object will have a local time of midnight.
119         *
120         * @param instant  the milliseconds from 1970-01-01T00:00:00Z
121         */
122        public DateMidnight(long instant) {
123            super(instant);
124        }
125    
126        /**
127         * Constructs an instance set to the milliseconds from 1970-01-01T00:00:00Z
128         * using <code>ISOChronology</code> in the specified time zone.
129         * The constructed object will have a local time of midnight.
130         * <p>
131         * If the specified time zone is null, the default zone is used.
132         *
133         * @param instant  the milliseconds from 1970-01-01T00:00:00Z
134         * @param zone  the time zone, null means default zone
135         */
136        public DateMidnight(long instant, DateTimeZone zone) {
137            super(instant, zone);
138        }
139    
140        /**
141         * Constructs an instance set to the milliseconds from 1970-01-01T00:00:00Z
142         * using the specified chronology.
143         * The constructed object will have a local time of midnight.
144         * <p>
145         * If the chronology is null, <code>ISOChronology</code>
146         * in the default time zone is used.
147         *
148         * @param instant  the milliseconds from 1970-01-01T00:00:00Z
149         * @param chronology  the chronology, null means ISOChronology in default zone
150         */
151        public DateMidnight(long instant, Chronology chronology) {
152            super(instant, chronology);
153        }
154    
155        //-----------------------------------------------------------------------
156        /**
157         * Constructs an instance from an Object that represents a datetime.
158         * The constructed object will have a local time of midnight.
159         * <p>
160         * If the object implies a chronology (such as GregorianCalendar does),
161         * then that chronology will be used. Otherwise, ISO default is used.
162         * Thus if a GregorianCalendar is passed in, the chronology used will
163         * be GJ, but if a Date is passed in the chronology will be ISO.
164         * <p>
165         * The recognised object types are defined in
166         * {@link org.joda.time.convert.ConverterManager ConverterManager} and
167         * include ReadableInstant, String, Calendar and Date.
168         * The String formats are described by {@link ISODateTimeFormat#dateTimeParser()}.
169         *
170         * @param instant  the datetime object, null means now
171         * @throws IllegalArgumentException if the instant is invalid
172         */
173        public DateMidnight(Object instant) {
174            super(instant, (Chronology) null);
175        }
176    
177        /**
178         * Constructs an instance from an Object that represents a datetime,
179         * forcing the time zone to that specified.
180         * The constructed object will have a local time of midnight.
181         * <p>
182         * If the object implies a chronology (such as GregorianCalendar does),
183         * then that chronology will be used, but with the time zone adjusted.
184         * Otherwise, ISO is used in the specified time zone.
185         * If the specified time zone is null, the default zone is used.
186         * Thus if a GregorianCalendar is passed in, the chronology used will
187         * be GJ, but if a Date is passed in the chronology will be ISO.
188         * <p>
189         * The recognised object types are defined in
190         * {@link org.joda.time.convert.ConverterManager ConverterManager} and
191         * include ReadableInstant, String, Calendar and Date.
192         * The String formats are described by {@link ISODateTimeFormat#dateTimeParser()}.
193         *
194         * @param instant  the datetime object, null means now
195         * @param zone  the time zone, null means default time zone
196         * @throws IllegalArgumentException if the instant is invalid
197         */
198        public DateMidnight(Object instant, DateTimeZone zone) {
199            super(instant, zone);
200        }
201    
202        /**
203         * Constructs an instance from an Object that represents a datetime,
204         * using the specified chronology.
205         * The constructed object will have a local time of midnight.
206         * <p>
207         * If the chronology is null, ISO in the default time zone is used.
208         * Any chronology implied by the object (such as GregorianCalendar does)
209         * is ignored.
210         * <p>
211         * The recognised object types are defined in
212         * {@link org.joda.time.convert.ConverterManager ConverterManager} and
213         * include ReadableInstant, String, Calendar and Date.
214         * The String formats are described by {@link ISODateTimeFormat#dateTimeParser()}.
215         *
216         * @param instant  the datetime object, null means now
217         * @param chronology  the chronology, null means ISOChronology in default zone
218         * @throws IllegalArgumentException if the instant is invalid
219         */
220        public DateMidnight(Object instant, Chronology chronology) {
221            super(instant, DateTimeUtils.getChronology(chronology));
222        }
223    
224        //-----------------------------------------------------------------------
225        /**
226         * Constructs an instance from datetime field values
227         * using <code>ISOChronology</code> in the default time zone.
228         * The constructed object will have a local time of midnight.
229         *
230         * @param year  the year
231         * @param monthOfYear  the month of the year
232         * @param dayOfMonth  the day of the month
233         */
234        public DateMidnight(int year, int monthOfYear, int dayOfMonth) {
235            super(year, monthOfYear, dayOfMonth, 0, 0, 0, 0);
236        }
237    
238        /**
239         * Constructs an instance from datetime field values
240         * using <code>ISOChronology</code> in the specified time zone.
241         * The constructed object will have a local time of midnight.
242         * <p>
243         * If the specified time zone is null, the default zone is used.
244         *
245         * @param year  the year
246         * @param monthOfYear  the month of the year
247         * @param dayOfMonth  the day of the month
248         * @param zone  the time zone, null means default time zone
249         */
250        public DateMidnight(int year, int monthOfYear, int dayOfMonth, DateTimeZone zone) {
251            super(year, monthOfYear, dayOfMonth, 0, 0, 0, 0, zone);
252        }
253    
254        /**
255         * Constructs an instance from datetime field values
256         * using the specified chronology.
257         * The constructed object will have a local time of midnight.
258         * <p>
259         * If the chronology is null, <code>ISOChronology</code>
260         * in the default time zone is used.
261         *
262         * @param year  the year
263         * @param monthOfYear  the month of the year
264         * @param dayOfMonth  the day of the month
265         * @param chronology  the chronology, null means ISOChronology in default zone
266         */
267        public DateMidnight(int year, int monthOfYear, int dayOfMonth, Chronology chronology) {
268            super(year, monthOfYear, dayOfMonth, 0, 0, 0, 0, chronology);
269        }
270    
271        /**
272         * Rounds the specified instant to midnight.
273         *
274         * @param instant  the milliseconds from 1970-01-01T00:00:00Z to round
275         * @param chronology  the chronology to use, not null
276         * @return the updated instant, rounded to midnight
277         */
278        protected long checkInstant(long instant, Chronology chronology) {
279            return chronology.dayOfMonth().roundFloor(instant);
280        }
281    
282        //-----------------------------------------------------------------------
283        /**
284         * Returns a copy of this date with a different millisecond instant.
285         * The returned object will have a local time of midnight.
286         * <p>
287         * Only the millis will change, the chronology and time zone are kept.
288         * The returned object will be either be a new instance or <code>this</code>.
289         *
290         * @param newMillis  the new millis, from 1970-01-01T00:00:00Z
291         * @return a copy of this instant with different millis
292         */
293        public DateMidnight withMillis(long newMillis) {
294            Chronology chrono = getChronology();
295            newMillis = checkInstant(newMillis, chrono);
296            return (newMillis == getMillis() ? this : new DateMidnight(newMillis, chrono));
297        }
298    
299        /**
300         * Returns a copy of this date with a different chronology, potentially
301         * changing the day in unexpected ways.
302         * <p>
303         * This method creates a new DateMidnight using the midnight millisecond value
304         * and the new chronology. If the same or similar chronology is specified, but
305         * with a different time zone, the day may change. This occurs because the new
306         * DateMidnight rounds down the millisecond value to get to midnight, and the
307         * time zone change may result in a rounding down to a different day.
308         * <p>
309         * For example, changing time zone from London (+00:00) to Paris (+01:00) will
310         * retain the same day, but changing from Paris to London will change the day.
311         * (When its midnight in London its the same day in Paris, but when its midnight
312         * in Paris its still the previous day in London)
313         * <p>
314         * To avoid these unusual effects, use {@link #withZoneRetainFields(DateTimeZone)}
315         * to change time zones.
316         *
317         * @param newChronology  the new chronology
318         * @return a copy of this instant with a different chronology
319         */
320        public DateMidnight withChronology(Chronology newChronology) {
321            return (newChronology == getChronology() ? this : new DateMidnight(getMillis(), newChronology));
322        }
323    
324        /**
325         * Returns a copy of this date with a different time zone, preserving the day
326         * The returned object will have a local time of midnight in the new zone on
327         * the same day as the original instant.
328         *
329         * @param newZone  the new time zone, null means default
330         * @return a copy of this instant with a different time zone
331         */
332        public DateMidnight withZoneRetainFields(DateTimeZone newZone) {
333            newZone = DateTimeUtils.getZone(newZone);
334            DateTimeZone originalZone = DateTimeUtils.getZone(getZone());
335            if (newZone == originalZone) {
336                return this;
337            }
338            
339            long millis = originalZone.getMillisKeepLocal(newZone, getMillis());
340            return new DateMidnight(millis, getChronology().withZone(newZone));
341        }
342    
343        //-----------------------------------------------------------------------
344        /**
345         * Returns a copy of this date with the partial set of fields replacing those
346         * from this instance.
347         * <p>
348         * For example, if the partial is a <code>LocalDate</code> then the date fields
349         * would be changed in the returned instance.
350         * If the partial is null, then <code>this</code> is returned.
351         *
352         * @param partial  the partial set of fields to apply to this datetime, null ignored
353         * @return a copy of this datetime with a different set of fields
354         * @throws IllegalArgumentException if any value is invalid
355         */
356        public DateMidnight withFields(ReadablePartial partial) {
357            if (partial == null) {
358                return this;
359            }
360            return withMillis(getChronology().set(partial, getMillis()));
361        }
362    
363        /**
364         * Returns a copy of this date with the specified field set to a new value.
365         * <p>
366         * For example, if the field type is <code>dayOfMonth</code> then the day of month
367         * field would be changed in the returned instance.
368         * If the field type is null, then <code>this</code> is returned.
369         * <p>
370         * These three lines are equivalent:
371         * <pre>
372         * DateTime updated = dt.withField(DateTimeFieldType.dayOfMonth(), 6);
373         * DateTime updated = dt.dayOfMonth().setCopy(6);
374         * DateTime updated = dt.property(DateTimeFieldType.dayOfMonth()).setCopy(6);
375         * </pre>
376         *
377         * @param fieldType  the field type to set, not null
378         * @param value  the value to set
379         * @return a copy of this datetime with the field set
380         * @throws IllegalArgumentException if the value is null or invalid
381         */
382        public DateMidnight withField(DateTimeFieldType fieldType, int value) {
383            if (fieldType == null) {
384                throw new IllegalArgumentException("Field must not be null");
385            }
386            long instant = fieldType.getField(getChronology()).set(getMillis(), value);
387            return withMillis(instant);
388        }
389    
390        /**
391         * Returns a copy of this date with the value of the specified field increased.
392         * <p>
393         * If the addition is zero or the field is null, then <code>this</code> is returned.
394         * <p>
395         * These three lines are equivalent:
396         * <pre>
397         * DateMidnight added = dt.withFieldAdded(DateTimeFieldType.year(), 6);
398         * DateMidnight added = dt.plusYears(6);
399         * DateMidnight added = dt.year().addToCopy(6);
400         * </pre>
401         * 
402         * @param fieldType  the field type to add to, not null
403         * @param amount  the amount to add
404         * @return a copy of this datetime with the field updated
405         * @throws IllegalArgumentException if the value is null or invalid
406         * @throws ArithmeticException if the new datetime exceeds the capacity of a long
407         */
408        public DateMidnight withFieldAdded(DurationFieldType fieldType, int amount) {
409            if (fieldType == null) {
410                throw new IllegalArgumentException("Field must not be null");
411            }
412            if (amount == 0) {
413                return this;
414            }
415            long instant = fieldType.getField(getChronology()).add(getMillis(), amount);
416            return withMillis(instant);
417        }
418    
419        //-----------------------------------------------------------------------
420        /**
421         * Returns a copy of this date with the specified duration added.
422         * <p>
423         * If the addition is zero, then <code>this</code> is returned.
424         * 
425         * @param durationToAdd  the duration to add to this one
426         * @param scalar  the amount of times to add, such as -1 to subtract once
427         * @return a copy of this datetime with the duration added
428         * @throws ArithmeticException if the new datetime exceeds the capacity of a long
429         */
430        public DateMidnight withDurationAdded(long durationToAdd, int scalar) {
431            if (durationToAdd == 0 || scalar == 0) {
432                return this;
433            }
434            long instant = getChronology().add(getMillis(), durationToAdd, scalar);
435            return withMillis(instant);
436        }
437    
438        /**
439         * Returns a copy of this date with the specified duration added.
440         * <p>
441         * If the addition is zero, then <code>this</code> is returned.
442         * 
443         * @param durationToAdd  the duration to add to this one, null means zero
444         * @param scalar  the amount of times to add, such as -1 to subtract once
445         * @return a copy of this datetime with the duration added
446         * @throws ArithmeticException if the new datetime exceeds the capacity of a long
447         */
448        public DateMidnight withDurationAdded(ReadableDuration durationToAdd, int scalar) {
449            if (durationToAdd == null || scalar == 0) {
450                return this;
451            }
452            return withDurationAdded(durationToAdd.getMillis(), scalar);
453        }
454    
455        /**
456         * Returns a copy of this date with the specified period added.
457         * <p>
458         * If the addition is zero, then <code>this</code> is returned.
459         * <p>
460         * This method is typically used to add multiple copies of complex
461         * period instances. Adding one field is best achieved using methods
462         * like {@link #withFieldAdded(DurationFieldType, int)}
463         * or {@link #plusYears(int)}.
464         * 
465         * @param period  the period to add to this one, null means zero
466         * @param scalar  the amount of times to add, such as -1 to subtract once
467         * @return a copy of this datetime with the period added
468         * @throws ArithmeticException if the new datetime exceeds the capacity of a long
469         */
470        public DateMidnight withPeriodAdded(ReadablePeriod period, int scalar) {
471            if (period == null || scalar == 0) {
472                return this;
473            }
474            long instant = getChronology().add(period, getMillis(), scalar);
475            return withMillis(instant);
476        }
477    
478        //-----------------------------------------------------------------------
479        /**
480         * Returns a copy of this date with the specified duration added.
481         * <p>
482         * If the amount is zero, then <code>this</code> is returned.
483         * 
484         * @param duration  the duration, in millis, to add to this one
485         * @return a copy of this datetime with the duration added
486         * @throws ArithmeticException if the new datetime exceeds the capacity of a long
487         */
488        public DateMidnight plus(long duration) {
489            return withDurationAdded(duration, 1);
490        }
491    
492        /**
493         * Returns a copy of this date with the specified duration added.
494         * <p>
495         * If the amount is zero or null, then <code>this</code> is returned.
496         * 
497         * @param duration  the duration to add to this one, null means zero
498         * @return a copy of this datetime with the duration added
499         * @throws ArithmeticException if the new datetime exceeds the capacity of a long
500         */
501        public DateMidnight plus(ReadableDuration duration) {
502            return withDurationAdded(duration, 1);
503        }
504    
505        /**
506         * Returns a copy of this date with the specified period added.
507         * <p>
508         * If the amount is zero or null, then <code>this</code> is returned.
509         * <p>
510         * This method is typically used to add complex period instances.
511         * Adding one field is best achieved using methods
512         * like {@link #plusYears(int)}.
513         * 
514         * @param period  the duration to add to this one, null means zero
515         * @return a copy of this datetime with the period added
516         * @throws ArithmeticException if the new datetime exceeds the capacity of a long
517         */
518        public DateMidnight plus(ReadablePeriod period) {
519            return withPeriodAdded(period, 1);
520        }
521    
522        //-----------------------------------------------------------------------
523        /**
524         * Returns a copy of this date plus the specified number of years.
525         * <p>
526         * This datetime instance is immutable and unaffected by this method call.
527         * <p>
528         * The following three lines are identical in effect:
529         * <pre>
530         * DateMidnight added = dt.plusYears(6);
531         * DateMidnight added = dt.plus(Period.years(6));
532         * DateMidnight added = dt.withFieldAdded(DurationFieldType.years(), 6);
533         * </pre>
534         *
535         * @param years  the amount of years to add, may be negative
536         * @return the new datetime plus the increased years
537         * @since 1.1
538         */
539        public DateMidnight plusYears(int years) {
540            if (years == 0) {
541                return this;
542            }
543            long instant = getChronology().years().add(getMillis(), years);
544            return withMillis(instant);
545        }
546    
547        /**
548         * Returns a copy of this date plus the specified number of months.
549         * <p>
550         * This datetime instance is immutable and unaffected by this method call.
551         * <p>
552         * The following three lines are identical in effect:
553         * <pre>
554         * DateMidnight added = dt.plusMonths(6);
555         * DateMidnight added = dt.plus(Period.months(6));
556         * DateMidnight added = dt.withFieldAdded(DurationFieldType.months(), 6);
557         * </pre>
558         *
559         * @param months  the amount of months to add, may be negative
560         * @return the new datetime plus the increased months
561         * @since 1.1
562         */
563        public DateMidnight plusMonths(int months) {
564            if (months == 0) {
565                return this;
566            }
567            long instant = getChronology().months().add(getMillis(), months);
568            return withMillis(instant);
569        }
570    
571        /**
572         * Returns a copy of this date plus the specified number of weeks.
573         * <p>
574         * This datetime instance is immutable and unaffected by this method call.
575         * <p>
576         * The following three lines are identical in effect:
577         * <pre>
578         * DateMidnight added = dt.plusWeeks(6);
579         * DateMidnight added = dt.plus(Period.weeks(6));
580         * DateMidnight added = dt.withFieldAdded(DurationFieldType.weeks(), 6);
581         * </pre>
582         *
583         * @param weeks  the amount of weeks to add, may be negative
584         * @return the new datetime plus the increased weeks
585         * @since 1.1
586         */
587        public DateMidnight plusWeeks(int weeks) {
588            if (weeks == 0) {
589                return this;
590            }
591            long instant = getChronology().weeks().add(getMillis(), weeks);
592            return withMillis(instant);
593        }
594    
595        /**
596         * Returns a copy of this date plus the specified number of days.
597         * <p>
598         * This datetime instance is immutable and unaffected by this method call.
599         * <p>
600         * The following three lines are identical in effect:
601         * <pre>
602         * DateMidnight added = dt.plusDays(6);
603         * DateMidnight added = dt.plus(Period.days(6));
604         * DateMidnight added = dt.withFieldAdded(DurationFieldType.days(), 6);
605         * </pre>
606         *
607         * @param days  the amount of days to add, may be negative
608         * @return the new datetime plus the increased days
609         * @since 1.1
610         */
611        public DateMidnight plusDays(int days) {
612            if (days == 0) {
613                return this;
614            }
615            long instant = getChronology().days().add(getMillis(), days);
616            return withMillis(instant);
617        }
618    
619        //-----------------------------------------------------------------------
620        /**
621         * Returns a copy of this date with the specified duration taken away.
622         * <p>
623         * If the amount is zero or null, then <code>this</code> is returned.
624         * 
625         * @param duration  the duration, in millis, to reduce this instant by
626         * @return a copy of this datetime with the duration taken away
627         * @throws ArithmeticException if the new datetime exceeds the capacity of a long
628         */
629        public DateMidnight minus(long duration) {
630            return withDurationAdded(duration, -1);
631        }
632    
633        /**
634         * Returns a copy of this date with the specified duration taken away.
635         * <p>
636         * If the amount is zero or null, then <code>this</code> is returned.
637         * 
638         * @param duration  the duration to reduce this instant by
639         * @return a copy of this datetime with the duration taken away
640         * @throws ArithmeticException if the new datetime exceeds the capacity of a long
641         */
642        public DateMidnight minus(ReadableDuration duration) {
643            return withDurationAdded(duration, -1);
644        }
645    
646        /**
647         * Returns a copy of this date with the specified period taken away.
648         * <p>
649         * If the amount is zero or null, then <code>this</code> is returned.
650         * <p>
651         * This method is typically used to subtract complex period instances.
652         * Subtracting one field is best achieved using methods
653         * like {@link #minusYears(int)}.
654         * 
655         * @param period  the period to reduce this instant by
656         * @return a copy of this datetime with the period taken away
657         * @throws ArithmeticException if the new datetime exceeds the capacity of a long
658         */
659        public DateMidnight minus(ReadablePeriod period) {
660            return withPeriodAdded(period, -1);
661        }
662    
663        //-----------------------------------------------------------------------
664        /**
665         * Returns a copy of this date minus the specified number of years.
666         * <p>
667         * This datetime instance is immutable and unaffected by this method call.
668         * <p>
669         * The following three lines are identical in effect:
670         * <pre>
671         * DateTime subtracted = dt.minusYears(6);
672         * DateTime subtracted = dt.minus(Period.years(6));
673         * DateTime subtracted = dt.withFieldAdded(DurationFieldType.years(), -6);
674         * </pre>
675         *
676         * @param years  the amount of years to subtract, may be negative
677         * @return the new datetime minus the increased years
678         * @since 1.1
679         */
680        public DateMidnight minusYears(int years) {
681            if (years == 0) {
682                return this;
683            }
684            long instant = getChronology().years().subtract(getMillis(), years);
685            return withMillis(instant);
686        }
687    
688        /**
689         * Returns a copy of this date minus the specified number of months.
690         * <p>
691         * This datetime instance is immutable and unaffected by this method call.
692         * <p>
693         * The following three lines are identical in effect:
694         * <pre>
695         * DateMidnight subtracted = dt.minusMonths(6);
696         * DateMidnight subtracted = dt.minus(Period.months(6));
697         * DateMidnight subtracted = dt.withFieldAdded(DurationFieldType.months(), -6);
698         * </pre>
699         *
700         * @param months  the amount of months to subtract, may be negative
701         * @return the new datetime minus the increased months
702         * @since 1.1
703         */
704        public DateMidnight minusMonths(int months) {
705            if (months == 0) {
706                return this;
707            }
708            long instant = getChronology().months().subtract(getMillis(), months);
709            return withMillis(instant);
710        }
711    
712        /**
713         * Returns a copy of this date minus the specified number of weeks.
714         * <p>
715         * This datetime instance is immutable and unaffected by this method call.
716         * <p>
717         * The following three lines are identical in effect:
718         * <pre>
719         * DateMidnight subtracted = dt.minusWeeks(6);
720         * DateMidnight subtracted = dt.minus(Period.weeks(6));
721         * DateMidnight subtracted = dt.withFieldAdded(DurationFieldType.weeks(), -6);
722         * </pre>
723         *
724         * @param weeks  the amount of weeks to subtract, may be negative
725         * @return the new datetime minus the increased weeks
726         * @since 1.1
727         */
728        public DateMidnight minusWeeks(int weeks) {
729            if (weeks == 0) {
730                return this;
731            }
732            long instant = getChronology().weeks().subtract(getMillis(), weeks);
733            return withMillis(instant);
734        }
735    
736        /**
737         * Returns a copy of this date minus the specified number of days.
738         * <p>
739         * This datetime instance is immutable and unaffected by this method call.
740         * <p>
741         * The following three lines are identical in effect:
742         * <pre>
743         * DateMidnight subtracted = dt.minusDays(6);
744         * DateMidnight subtracted = dt.minus(Period.days(6));
745         * DateMidnight subtracted = dt.withFieldAdded(DurationFieldType.days(), -6);
746         * </pre>
747         *
748         * @param days  the amount of days to subtract, may be negative
749         * @return the new datetime minus the increased days
750         * @since 1.1
751         */
752        public DateMidnight minusDays(int days) {
753            if (days == 0) {
754                return this;
755            }
756            long instant = getChronology().days().subtract(getMillis(), days);
757            return withMillis(instant);
758        }
759    
760        //-----------------------------------------------------------------------
761        /**
762         * Gets the property object for the specified type, which contains many useful methods.
763         *
764         * @param type  the field type to get the chronology for
765         * @return the property object
766         * @throws IllegalArgumentException if the field is null or unsupported
767         */
768        public Property property(DateTimeFieldType type) {
769            if (type == null) {
770                throw new IllegalArgumentException("The DateTimeFieldType must not be null");
771            }
772            DateTimeField field = type.getField(getChronology());
773            if (field.isSupported() == false) {
774                throw new IllegalArgumentException("Field '" + type + "' is not supported");
775            }
776            return new Property(this, field);
777        }
778    
779        //-----------------------------------------------------------------------
780        /**
781         * Converts this object to a <code>YearMonthDay</code> using the
782         * same date and chronology.
783         * 
784         * @return a YearMonthDay using the same millis and chronology
785         * @deprecated Use LocalDate instead of YearMonthDay
786         */
787        public YearMonthDay toYearMonthDay() {
788            return new YearMonthDay(getMillis(), getChronology());
789        }
790    
791        /**
792         * Converts this object to a <code>LocalDate</code> with the
793         * same date and chronology.
794         *
795         * @return a LocalDate with the same date and chronology
796         * @since 1.3
797         */
798        public LocalDate toLocalDate() {
799            return new LocalDate(getMillis(), getChronology());
800        }
801    
802        /**
803         * Converts this object to an <code>Interval</code> encompassing
804         * the whole of this day.
805         * <p>
806         * The interval starts at midnight 00:00 and ends at 00:00 the following day,
807         * (which is not included in the interval, as intervals are half-open).
808         * 
809         * @return an interval over the day
810         */
811        public Interval toInterval() {
812            Chronology chrono = getChronology();
813            long start = getMillis();
814            long end = DurationFieldType.days().getField(chrono).add(start, 1);
815            return new Interval(start, end, chrono);
816        }
817    
818        //-----------------------------------------------------------------------
819        /**
820         * Returns a copy of this date with the era field updated.
821         * <p>
822         * DateMidnight is immutable, so there are no set methods.
823         * Instead, this method returns a new instance with the value of
824         * era changed.
825         *
826         * @param era  the era to set
827         * @return a copy of this object with the field set
828         * @throws IllegalArgumentException if the value is invalid
829         * @since 1.3
830         */
831        public DateMidnight withEra(int era) {
832            return withMillis(getChronology().era().set(getMillis(), era));
833        }
834    
835        /**
836         * Returns a copy of this date with the century of era field updated.
837         * <p>
838         * DateMidnight is immutable, so there are no set methods.
839         * Instead, this method returns a new instance with the value of
840         * century of era changed.
841         *
842         * @param centuryOfEra  the centurey of era to set
843         * @return a copy of this object with the field set
844         * @throws IllegalArgumentException if the value is invalid
845         * @since 1.3
846         */
847        public DateMidnight withCenturyOfEra(int centuryOfEra) {
848            return withMillis(getChronology().centuryOfEra().set(getMillis(), centuryOfEra));
849        }
850    
851        /**
852         * Returns a copy of this date with the year of era field updated.
853         * <p>
854         * DateMidnight is immutable, so there are no set methods.
855         * Instead, this method returns a new instance with the value of
856         * year of era changed.
857         *
858         * @param yearOfEra  the year of era to set
859         * @return a copy of this object with the field set
860         * @throws IllegalArgumentException if the value is invalid
861         * @since 1.3
862         */
863        public DateMidnight withYearOfEra(int yearOfEra) {
864            return withMillis(getChronology().yearOfEra().set(getMillis(), yearOfEra));
865        }
866    
867        /**
868         * Returns a copy of this date with the year of century field updated.
869         * <p>
870         * DateMidnight is immutable, so there are no set methods.
871         * Instead, this method returns a new instance with the value of
872         * year of century changed.
873         *
874         * @param yearOfCentury  the year of century to set
875         * @return a copy of this object with the field set
876         * @throws IllegalArgumentException if the value is invalid
877         * @since 1.3
878         */
879        public DateMidnight withYearOfCentury(int yearOfCentury) {
880            return withMillis(getChronology().yearOfCentury().set(getMillis(), yearOfCentury));
881        }
882    
883        /**
884         * Returns a copy of this date with the year field updated.
885         * <p>
886         * DateMidnight is immutable, so there are no set methods.
887         * Instead, this method returns a new instance with the value of
888         * year changed.
889         *
890         * @param year  the year to set
891         * @return a copy of this object with the field set
892         * @throws IllegalArgumentException if the value is invalid
893         * @since 1.3
894         */
895        public DateMidnight withYear(int year) {
896            return withMillis(getChronology().year().set(getMillis(), year));
897        }
898    
899        /**
900         * Returns a copy of this date with the weekyear field updated.
901         * <p>
902         * DateMidnight is immutable, so there are no set methods.
903         * Instead, this method returns a new instance with the value of
904         * weekyear changed.
905         *
906         * @param weekyear  the weekyear to set
907         * @return a copy of this object with the field set
908         * @throws IllegalArgumentException if the value is invalid
909         * @since 1.3
910         */
911        public DateMidnight withWeekyear(int weekyear) {
912            return withMillis(getChronology().weekyear().set(getMillis(), weekyear));
913        }
914    
915        /**
916         * Returns a copy of this date with the month of year field updated.
917         * <p>
918         * DateMidnight is immutable, so there are no set methods.
919         * Instead, this method returns a new instance with the value of
920         * month of year changed.
921         *
922         * @param monthOfYear  the month of year to set
923         * @return a copy of this object with the field set
924         * @throws IllegalArgumentException if the value is invalid
925         * @since 1.3
926         */
927        public DateMidnight withMonthOfYear(int monthOfYear) {
928            return withMillis(getChronology().monthOfYear().set(getMillis(), monthOfYear));
929        }
930    
931        /**
932         * Returns a copy of this date with the week of weekyear field updated.
933         * <p>
934         * DateMidnight is immutable, so there are no set methods.
935         * Instead, this method returns a new instance with the value of
936         * week of weekyear changed.
937         *
938         * @param weekOfWeekyear  the week of weekyear to set
939         * @return a copy of this object with the field set
940         * @throws IllegalArgumentException if the value is invalid
941         * @since 1.3
942         */
943        public DateMidnight withWeekOfWeekyear(int weekOfWeekyear) {
944            return withMillis(getChronology().weekOfWeekyear().set(getMillis(), weekOfWeekyear));
945        }
946    
947        /**
948         * Returns a copy of this date with the day of year field updated.
949         * <p>
950         * DateMidnight is immutable, so there are no set methods.
951         * Instead, this method returns a new instance with the value of
952         * day of year changed.
953         *
954         * @param dayOfYear  the day of year to set
955         * @return a copy of this object with the field set
956         * @throws IllegalArgumentException if the value is invalid
957         * @since 1.3
958         */
959        public DateMidnight withDayOfYear(int dayOfYear) {
960            return withMillis(getChronology().dayOfYear().set(getMillis(), dayOfYear));
961        }
962    
963        /**
964         * Returns a copy of this date with the day of month field updated.
965         * <p>
966         * DateMidnight is immutable, so there are no set methods.
967         * Instead, this method returns a new instance with the value of
968         * day of month changed.
969         *
970         * @param dayOfMonth  the day of month to set
971         * @return a copy of this object with the field set
972         * @throws IllegalArgumentException if the value is invalid
973         * @since 1.3
974         */
975        public DateMidnight withDayOfMonth(int dayOfMonth) {
976            return withMillis(getChronology().dayOfMonth().set(getMillis(), dayOfMonth));
977        }
978    
979        /**
980         * Returns a copy of this date with the day of week field updated.
981         * <p>
982         * DateMidnight is immutable, so there are no set methods.
983         * Instead, this method returns a new instance with the value of
984         * day of week changed.
985         *
986         * @param dayOfWeek  the day of week to set
987         * @return a copy of this object with the field set
988         * @throws IllegalArgumentException if the value is invalid
989         * @since 1.3
990         */
991        public DateMidnight withDayOfWeek(int dayOfWeek) {
992            return withMillis(getChronology().dayOfWeek().set(getMillis(), dayOfWeek));
993        }
994    
995        // Date properties
996        //-----------------------------------------------------------------------
997        /**
998         * Get the era property which provides access to advanced functionality.
999         * 
1000         * @return the era property
1001         */
1002        public Property era() {
1003            return new Property(this, getChronology().era());
1004        }
1005    
1006        /**
1007         * Get the century of era property which provides access to advanced functionality.
1008         * 
1009         * @return the year of era property
1010         */
1011        public Property centuryOfEra() {
1012            return new Property(this, getChronology().centuryOfEra());
1013        }
1014    
1015        /**
1016         * Get the year of century property which provides access to advanced functionality.
1017         * 
1018         * @return the year of era property
1019         */
1020        public Property yearOfCentury() {
1021            return new Property(this, getChronology().yearOfCentury());
1022        }
1023    
1024        /**
1025         * Get the year of era property which provides access to advanced functionality.
1026         * 
1027         * @return the year of era property
1028         */
1029        public Property yearOfEra() {
1030            return new Property(this, getChronology().yearOfEra());
1031        }
1032    
1033        /**
1034         * Get the year property which provides access to advanced functionality.
1035         * 
1036         * @return the year property
1037         */
1038        public Property year() {
1039            return new Property(this, getChronology().year());
1040        }
1041    
1042        /**
1043         * Get the year of a week based year property which provides access to advanced functionality.
1044         * 
1045         * @return the year of a week based year property
1046         */
1047        public Property weekyear() {
1048            return new Property(this, getChronology().weekyear());
1049        }
1050    
1051        /**
1052         * Get the month of year property which provides access to advanced functionality.
1053         * 
1054         * @return the month of year property
1055         */
1056        public Property monthOfYear() {
1057            return new Property(this, getChronology().monthOfYear());
1058        }
1059    
1060        /**
1061         * Get the week of a week based year property which provides access to advanced functionality.
1062         * 
1063         * @return the week of a week based year property
1064         */
1065        public Property weekOfWeekyear() {
1066            return new Property(this, getChronology().weekOfWeekyear());
1067        }
1068    
1069        /**
1070         * Get the day of year property which provides access to advanced functionality.
1071         * 
1072         * @return the day of year property
1073         */
1074        public Property dayOfYear() {
1075            return new Property(this, getChronology().dayOfYear());
1076        }
1077    
1078        /**
1079         * Get the day of month property which provides access to advanced functionality.
1080         * 
1081         * @return the day of month property
1082         */
1083        public Property dayOfMonth() {
1084            return new Property(this, getChronology().dayOfMonth());
1085        }
1086    
1087        /**
1088         * Get the day of week property which provides access to advanced functionality.
1089         * 
1090         * @return the day of week property
1091         */
1092        public Property dayOfWeek() {
1093            return new Property(this, getChronology().dayOfWeek());
1094        }
1095    
1096        //-----------------------------------------------------------------------
1097        /**
1098         * DateMidnight.Property binds a DateMidnight to a DateTimeField allowing powerful
1099         * datetime functionality to be easily accessed.
1100         * <p>
1101         * The simplest use of this class is as an alternative get method, here used to
1102         * get the year '1972' (as an int) and the month 'December' (as a String).
1103         * <pre>
1104         * DateMidnight dt = new DateMidnight(1972, 12, 3);
1105         * int year = dt.year().get();
1106         * String monthStr = dt.monthOfYear().getAsText();
1107         * </pre>
1108         * <p>
1109         * Methods are also provided that allow date modification. These return new instances
1110         * of DateMidnight - they do not modify the original. The example below yields two
1111         * independent immutable date objects 20 years apart.
1112         * <pre>
1113         * DateMidnight dt = new DateMidnight(1972, 12, 3);
1114         * DateMidnight dt20 = dt.year().addToCopy(20);
1115         * </pre>
1116         * Serious modification of dates (ie. more than just changing one or two fields)
1117         * should use the {@link org.joda.time.MutableDateTime MutableDateTime} class.
1118         * <p>
1119         * DateMidnight.Property itself is thread-safe and immutable.
1120         *
1121         * @author Stephen Colebourne
1122         * @author Brian S O'Neill
1123         * @since 1.0
1124         */
1125        public static final class Property extends AbstractReadableInstantFieldProperty {
1126        
1127            /** Serialization lock */
1128            private static final long serialVersionUID = 257629620L;
1129            
1130            /** The instant this property is working against */
1131            private DateMidnight iInstant;
1132            /** The field this property is working against */
1133            private DateTimeField iField;
1134            
1135            /**
1136             * Constructor.
1137             * 
1138             * @param instant  the instant to set
1139             * @param field  the field to use
1140             */
1141            Property(DateMidnight instant, DateTimeField field) {
1142                super();
1143                iInstant = instant;
1144                iField = field;
1145            }
1146    
1147            /**
1148             * Writes the property in a safe serialization format.
1149             */
1150            private void writeObject(ObjectOutputStream oos) throws IOException {
1151                oos.writeObject(iInstant);
1152                oos.writeObject(iField.getType());
1153            }
1154    
1155            /**
1156             * Reads the property from a safe serialization format.
1157             */
1158            private void readObject(ObjectInputStream oos) throws IOException, ClassNotFoundException {
1159                iInstant = (DateMidnight) oos.readObject();
1160                DateTimeFieldType type = (DateTimeFieldType) oos.readObject();
1161                iField = type.getField(iInstant.getChronology());
1162            }
1163    
1164            //-----------------------------------------------------------------------
1165            /**
1166             * Gets the field being used.
1167             * 
1168             * @return the field
1169             */
1170            public DateTimeField getField() {
1171                return iField;
1172            }
1173    
1174            /**
1175             * Gets the milliseconds of the datetime that this property is linked to.
1176             * 
1177             * @return the milliseconds
1178             */
1179            protected long getMillis() {
1180                return iInstant.getMillis();
1181            }
1182    
1183            /**
1184             * Gets the chronology of the datetime that this property is linked to.
1185             * 
1186             * @return the chronology
1187             * @since 1.4
1188             */
1189            protected Chronology getChronology() {
1190                return iInstant.getChronology();
1191            }
1192    
1193            /**
1194             * Gets the datetime being used.
1195             * 
1196             * @return the datetime
1197             */
1198            public DateMidnight getDateMidnight() {
1199                return iInstant;
1200            }
1201    
1202            //-----------------------------------------------------------------------
1203            /**
1204             * Adds to this field in a copy of this DateMidnight.
1205             * <p>
1206             * The DateMidnight attached to this property is unchanged by this call.
1207             * This operation is faster than converting a DateMidnight to a MutableDateTime
1208             * and back again when setting one field. When setting multiple fields,
1209             * it is generally quicker to make the conversion to MutableDateTime.
1210             * 
1211             * @param value  the value to add to the field in the copy
1212             * @return a copy of the DateMidnight with the field value changed
1213             * @throws IllegalArgumentException if the value isn't valid
1214             */
1215            public DateMidnight addToCopy(int value) {
1216                return iInstant.withMillis(iField.add(iInstant.getMillis(), value));
1217            }
1218    
1219            /**
1220             * Adds to this field in a copy of this DateMidnight.
1221             * <p>
1222             * The DateMidnight attached to this property is unchanged by this call.
1223             * This operation is faster than converting a DateMidnight to a MutableDateTime
1224             * and back again when setting one field. When setting multiple fields,
1225             * it is generally quicker to make the conversion to MutableDateTime.
1226             * 
1227             * @param value  the value to add to the field in the copy
1228             * @return a copy of the DateMidnight with the field value changed
1229             * @throws IllegalArgumentException if the value isn't valid
1230             */
1231            public DateMidnight addToCopy(long value) {
1232                return iInstant.withMillis(iField.add(iInstant.getMillis(), value));
1233            }
1234    
1235            /**
1236             * Adds to this field, possibly wrapped, in a copy of this DateMidnight.
1237             * A wrapped operation only changes this field.
1238             * Thus 31st January addWrapField one day goes to the 1st January.
1239             * <p>
1240             * The DateMidnight attached to this property is unchanged by this call.
1241             * This operation is faster than converting a DateMidnight to a MutableDateTime
1242             * and back again when setting one field. When setting multiple fields,
1243             * it is generally quicker to make the conversion to MutableDateTime.
1244             * 
1245             * @param value  the value to add to the field in the copy
1246             * @return a copy of the DateMidnight with the field value changed
1247             * @throws IllegalArgumentException if the value isn't valid
1248             */
1249            public DateMidnight addWrapFieldToCopy(int value) {
1250                return iInstant.withMillis(iField.addWrapField(iInstant.getMillis(), value));
1251            }
1252    
1253            //-----------------------------------------------------------------------
1254            /**
1255             * Sets this field in a copy of the DateMidnight.
1256             * <p>
1257             * The DateMidnight attached to this property is unchanged by this call.
1258             * This operation is faster than converting a DateMidnight to a MutableDateTime
1259             * and back again when setting one field. When setting multiple fields,
1260             * it is generally quicker to make the conversion to MutableDateTime.
1261             * 
1262             * @param value  the value to set the field in the copy to
1263             * @return a copy of the DateMidnight with the field value changed
1264             * @throws IllegalArgumentException if the value isn't valid
1265             */
1266            public DateMidnight setCopy(int value) {
1267                return iInstant.withMillis(iField.set(iInstant.getMillis(), value));
1268            }
1269        
1270            /**
1271             * Sets this field in a copy of the DateMidnight to a parsed text value.
1272             * <p>
1273             * The DateMidnight attached to this property is unchanged by this call.
1274             * This operation is faster than converting a DateMidnight to a MutableDateTime
1275             * and back again when setting one field. When setting multiple fields,
1276             * it is generally quicker to make the conversion to MutableDateTime.
1277             * 
1278             * @param text  the text value to set
1279             * @param locale  optional locale to use for selecting a text symbol
1280             * @return a copy of the DateMidnight with the field value changed
1281             * @throws IllegalArgumentException if the text value isn't valid
1282             */
1283            public DateMidnight setCopy(String text, Locale locale) {
1284                return iInstant.withMillis(iField.set(iInstant.getMillis(), text, locale));
1285            }
1286    
1287            /**
1288             * Sets this field in a copy of the DateMidnight to a parsed text value.
1289             * <p>
1290             * The DateMidnight attached to this property is unchanged by this call.
1291             * This operation is faster than converting a DateMidnight to a MutableDateTime
1292             * and back again when setting one field. When setting multiple fields,
1293             * it is generally quicker to make the conversion to MutableDateTime.
1294             * 
1295             * @param text  the text value to set
1296             * @return a copy of the DateMidnight with the field value changed
1297             * @throws IllegalArgumentException if the text value isn't valid
1298             */
1299            public DateMidnight setCopy(String text) {
1300                return setCopy(text, null);
1301            }
1302    
1303            //-----------------------------------------------------------------------
1304            /**
1305             * Returns a new DateMidnight with this field set to the maximum value
1306             * for this field.
1307             * <p>
1308             * This operation is useful for obtaining a DateTime on the last day
1309             * of the month, as month lengths vary.
1310             * <pre>
1311             * DateMidnight lastDayOfMonth = dt.dayOfMonth().withMaximumValue();
1312             * </pre>
1313             * <p>
1314             * The DateMidnight attached to this property is unchanged by this call.
1315             *
1316             * @return a copy of the DateMidnight with this field set to its maximum
1317             * @since 1.2
1318             */
1319            public DateMidnight withMaximumValue() {
1320                return setCopy(getMaximumValue());
1321            }
1322            
1323            /**
1324             * Returns a new DateMidnight with this field set to the minimum value
1325             * for this field.
1326             * <p>
1327             * The DateMidnight attached to this property is unchanged by this call.
1328             *
1329             * @return a copy of the DateMidnight with this field set to its minimum
1330             * @since 1.2
1331             */
1332            public DateMidnight withMinimumValue() {
1333                return setCopy(getMinimumValue());
1334            }
1335            
1336            //-----------------------------------------------------------------------
1337            /**
1338             * Rounds to the lowest whole unit of this field on a copy of this DateMidnight.
1339             *
1340             * @return a copy of the DateMidnight with the field value changed
1341             */
1342            public DateMidnight roundFloorCopy() {
1343                return iInstant.withMillis(iField.roundFloor(iInstant.getMillis()));
1344            }
1345    
1346            /**
1347             * Rounds to the highest whole unit of this field on a copy of this DateMidnight.
1348             *
1349             * @return a copy of the DateMidnight with the field value changed
1350             */
1351            public DateMidnight roundCeilingCopy() {
1352                return iInstant.withMillis(iField.roundCeiling(iInstant.getMillis()));
1353            }
1354    
1355            /**
1356             * Rounds to the nearest whole unit of this field on a copy of this DateMidnight,
1357             * favoring the floor if halfway.
1358             *
1359             * @return a copy of the DateMidnight with the field value changed
1360             */
1361            public DateMidnight roundHalfFloorCopy() {
1362                return iInstant.withMillis(iField.roundHalfFloor(iInstant.getMillis()));
1363            }
1364    
1365            /**
1366             * Rounds to the nearest whole unit of this field on a copy of this DateMidnight,
1367             * favoring the ceiling if halfway.
1368             *
1369             * @return a copy of the DateMidnight with the field value changed
1370             */
1371            public DateMidnight roundHalfCeilingCopy() {
1372                return iInstant.withMillis(iField.roundHalfCeiling(iInstant.getMillis()));
1373            }
1374    
1375            /**
1376             * Rounds to the nearest whole unit of this field on a copy of this DateMidnight.
1377             * If halfway, the ceiling is favored over the floor only if it makes this field's value even.
1378             *
1379             * @return a copy of the DateMidnight with the field value changed
1380             */
1381            public DateMidnight roundHalfEvenCopy() {
1382                return iInstant.withMillis(iField.roundHalfEven(iInstant.getMillis()));
1383            }
1384    
1385        }
1386    }