View Javadoc

1   /*
2    *  Copyright 2001-2011 Stephen Colebourne
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  package org.joda.time;
17  
18  import java.io.IOException;
19  import java.io.ObjectInputStream;
20  import java.io.ObjectOutputStream;
21  import java.io.Serializable;
22  import java.util.Locale;
23  
24  import org.joda.convert.FromString;
25  import org.joda.time.base.BaseDateTime;
26  import org.joda.time.field.AbstractReadableInstantFieldProperty;
27  import org.joda.time.format.DateTimeFormatter;
28  import org.joda.time.format.ISODateTimeFormat;
29  
30  /**
31   * DateMidnight defines a date where the time component is fixed at midnight.
32   * The class uses a time zone, thus midnight is local unless a UTC time zone is used.
33   * <p>
34   * It is important to emphasise that this class represents the time of midnight on
35   * any given day.
36   * Note that midnight is defined as 00:00, which is at the very start of a day.
37   * <p>
38   * This class does not represent a day, but the millisecond instant at midnight.
39   * If you need a class that represents the whole day, then an {@link Interval} or
40   * a {@link LocalDate} may be more suitable.
41   * <p>
42   * This class uses a Chronology internally. The Chronology determines how the
43   * millisecond instant value is converted into the date time fields.
44   * The default Chronology is <code>ISOChronology</code> which is the agreed
45   * international standard and compatable with the modern Gregorian calendar.
46   *
47   * <p>Each individual field can be queried in two ways:
48   * <ul>
49   * <li><code>getDayOfMonth()</code>
50   * <li><code>dayOfMonth().get()</code>
51   * </ul>
52   * The second technique also provides access to other useful methods on the
53   * field:
54   * <ul>
55   * <li>numeric value
56   * <li>text value
57   * <li>short text value
58   * <li>maximum/minimum values
59   * <li>add/subtract
60   * <li>set
61   * <li>rounding
62   * </ul>
63   *
64   * <p>
65   * DateMidnight is thread-safe and immutable, provided that the Chronology is as well.
66   * All standard Chronology classes supplied are thread-safe and immutable.
67   *
68   * @author Stephen Colebourne
69   * @since 1.0
70   */
71  public final class DateMidnight
72          extends BaseDateTime
73          implements ReadableDateTime, Serializable {
74      
75      /** Serialization lock */
76      private static final long serialVersionUID = 156371964018738L;
77  
78      //-----------------------------------------------------------------------
79      /**
80       * Obtains a {@code DateMidnight} set to the current system millisecond time
81       * using <code>ISOChronology</code> in the default time zone.
82       * The constructed object will have a local time of midnight.
83       * 
84       * @return the current date, not null
85       * @since 2.0
86       */
87      public static DateMidnight now() {
88          return new DateMidnight();
89      }
90  
91      /**
92       * Obtains a {@code DateMidnight} set to the current system millisecond time
93       * using <code>ISOChronology</code> in the specified time zone.
94       * The constructed object will have a local time of midnight.
95       *
96       * @param zone  the time zone, not null
97       * @return the current date, not null
98       * @since 2.0
99       */
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 }