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 */
016package org.joda.time;
017
018import java.io.IOException;
019import java.io.ObjectInputStream;
020import java.io.ObjectOutputStream;
021import java.io.Serializable;
022import java.util.Locale;
023
024import org.joda.convert.FromString;
025import org.joda.time.base.BaseDateTime;
026import org.joda.time.field.AbstractReadableInstantFieldProperty;
027import org.joda.time.format.DateTimeFormatter;
028import 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 */
071public 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}