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