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.Serializable;
19  import java.util.Calendar;
20  import java.util.Date;
21  import java.util.Locale;
22  
23  import org.joda.time.base.BasePartial;
24  import org.joda.time.chrono.ISOChronology;
25  import org.joda.time.field.AbstractPartialFieldProperty;
26  import org.joda.time.field.FieldUtils;
27  import org.joda.time.format.ISODateTimeFormat;
28  
29  /**
30   * YearMonthDay is an immutable partial supporting the year, monthOfYear
31   * and dayOfMonth fields.
32   * <p>
33   * NOTE: This class only supports the three fields listed above. Thus, you
34   * cannot query the dayOfWeek or centuryOfEra fields for example.
35   * The new <code>LocalDate</code> class removes this restriction.
36   * <p>
37   * Calculations on YearMonthDay are performed using a {@link Chronology}.
38   * This chronology is set to be in the UTC time zone for all calculations.
39   * <p>
40   * Each individual field can be queried in two ways:
41   * <ul>
42   * <li><code>getMonthOfYear()</code>
43   * <li><code>monthOfYear().get()</code>
44   * </ul>
45   * The second technique also provides access to other useful methods on the
46   * field:
47   * <ul>
48   * <li>numeric value - <code>monthOfYear().get()</code>
49   * <li>text value - <code>monthOfYear().getAsText()</code>
50   * <li>short text value - <code>monthOfYear().getAsShortText()</code>
51   * <li>maximum/minimum values - <code>monthOfYear().getMaximumValue()</code>
52   * <li>add/subtract - <code>monthOfYear().addToCopy()</code>
53   * <li>set - <code>monthOfYear().setCopy()</code>
54   * </ul>
55   * <p>
56   * YearMonthDay is thread-safe and immutable, provided that the Chronology is as well.
57   * All standard Chronology classes supplied are thread-safe and immutable.
58   *
59   * @author Stephen Colebourne
60   * @since 1.0
61   * @deprecated Use LocalDate which has a much better internal implementation and
62   *  has been available since 1.3
63   */
64  @Deprecated
65  public final class YearMonthDay
66          extends BasePartial
67          implements ReadablePartial, Serializable {
68  
69      /** Serialization version */
70      private static final long serialVersionUID = 797544782896179L;
71      /** The singleton set of field types */
72      private static final DateTimeFieldType[] FIELD_TYPES = new DateTimeFieldType[] {
73          DateTimeFieldType.year(),
74          DateTimeFieldType.monthOfYear(),
75          DateTimeFieldType.dayOfMonth(),
76      };
77  
78      /** The index of the year field in the field array */
79      public static final int YEAR = 0;
80      /** The index of the monthOfYear field in the field array */
81      public static final int MONTH_OF_YEAR = 1;
82      /** The index of the dayOfMonth field in the field array */
83      public static final int DAY_OF_MONTH = 2;
84  
85      //-----------------------------------------------------------------------
86      /**
87       * Constructs a YearMonthDay from a <code>java.util.Calendar</code>
88       * using exactly the same field values avoiding any time zone effects.
89       * <p>
90       * Each field is queried from the Calendar and assigned to the YearMonthDay.
91       * This is useful if you have been using the Calendar as a local date,
92       * ignoing the zone.
93       * <p>
94       * This factory method ignores the type of the calendar and always
95       * creates a YearMonthDay with ISO chronology. It is expected that you
96       * will only pass in instances of <code>GregorianCalendar</code> however
97       * this is not validated.
98       *
99       * @param calendar  the Calendar to extract fields from
100      * @return the created YearMonthDay
101      * @throws IllegalArgumentException if the calendar is null
102      * @throws IllegalArgumentException if the date is invalid for the ISO chronology
103      * @since 1.2
104      */
105     public static YearMonthDay fromCalendarFields(Calendar calendar) {
106         if (calendar == null) {
107             throw new IllegalArgumentException("The calendar must not be null");
108         }
109         return new YearMonthDay(
110             calendar.get(Calendar.YEAR),
111             calendar.get(Calendar.MONTH) + 1,
112             calendar.get(Calendar.DAY_OF_MONTH)
113         );
114     }
115 
116     /**
117      * Constructs a YearMonthDay from a <code>java.util.Date</code>
118      * using exactly the same field values avoiding any time zone effects.
119      * <p>
120      * Each field is queried from the Date and assigned to the YearMonthDay.
121      * This is useful if you have been using the Date as a local date,
122      * ignoing the zone.
123      * <p>
124      * This factory method always creates a YearMonthDay with ISO chronology.
125      *
126      * @param date  the Date to extract fields from
127      * @return the created YearMonthDay
128      * @throws IllegalArgumentException if the calendar is null
129      * @throws IllegalArgumentException if the date is invalid for the ISO chronology
130      * @since 1.2
131      */
132     public static YearMonthDay fromDateFields(Date date) {
133         if (date == null) {
134             throw new IllegalArgumentException("The date must not be null");
135         }
136         return new YearMonthDay(
137             date.getYear() + 1900,
138             date.getMonth() + 1,
139             date.getDate()
140         );
141     }
142 
143     //-----------------------------------------------------------------------
144     /**
145      * Constructs a YearMonthDay with the current date, using ISOChronology in
146      * the default zone to extract the fields.
147      * <p>
148      * The constructor uses the default time zone, resulting in the local time
149      * being initialised. Once the constructor is complete, all further calculations
150      * are performed without reference to a timezone (by switching to UTC).
151      */
152     public YearMonthDay() {
153         super();
154     }
155 
156     /**
157      * Constructs a YearMonthDay with the current date, using ISOChronology in
158      * the specified zone to extract the fields.
159      * <p>
160      * The constructor uses the specified time zone to obtain the current date.
161      * Once the constructor is complete, all further calculations
162      * are performed without reference to a timezone (by switching to UTC).
163      * 
164      * @param zone  the zone to use, null means default zone
165      * @since 1.1
166      */
167     public YearMonthDay(DateTimeZone zone) {
168         super(ISOChronology.getInstance(zone));
169     }
170 
171     /**
172      * Constructs a YearMonthDay with the current date, using the specified chronology
173      * and zone to extract the fields.
174      * <p>
175      * The constructor uses the time zone of the chronology specified.
176      * Once the constructor is complete, all further calculations are performed
177      * without reference to a timezone (by switching to UTC).
178      *
179      * @param chronology  the chronology, null means ISOChronology in the default zone
180      */
181     public YearMonthDay(Chronology chronology) {
182         super(chronology);
183     }
184 
185     /**
186      * Constructs a YearMonthDay extracting the partial fields from the specified
187      * milliseconds using the ISOChronology in the default zone.
188      * <p>
189      * The constructor uses the default time zone, resulting in the local time
190      * being initialised. Once the constructor is complete, all further calculations
191      * are performed without reference to a timezone (by switching to UTC).
192      *
193      * @param instant  the milliseconds from 1970-01-01T00:00:00Z
194      */
195     public YearMonthDay(long instant) {
196         super(instant);
197     }
198 
199     /**
200      * Constructs a YearMonthDay extracting the partial fields from the specified
201      * milliseconds using the chronology provided.
202      * <p>
203      * The constructor uses the time zone of the chronology specified.
204      * Once the constructor is complete, all further calculations are performed
205      * without reference to a timezone (by switching to UTC).
206      *
207      * @param instant  the milliseconds from 1970-01-01T00:00:00Z
208      * @param chronology  the chronology, null means ISOChronology in the default zone
209      */
210     public YearMonthDay(long instant, Chronology chronology) {
211         super(instant, chronology);
212     }
213 
214     /**
215      * Constructs a YearMonthDay from an Object that represents a time.
216      * <p>
217      * The recognised object types are defined in
218      * {@link org.joda.time.convert.ConverterManager ConverterManager} and
219      * include ReadableInstant, String, Calendar and Date.
220      * The String formats are described by {@link ISODateTimeFormat#dateOptionalTimeParser()}.
221      * <p>
222      * The chronology used will be derived from the object, defaulting to ISO.
223      * <p>
224      * NOTE: Prior to v1.3 the string format was described by
225      * {@link ISODateTimeFormat#dateTimeParser()}. Time ony strings are now rejected.
226      *
227      * @param instant  the datetime object, null means now
228      * @throws IllegalArgumentException if the instant is invalid
229      */
230     public YearMonthDay(Object instant) {
231         super(instant, null, ISODateTimeFormat.dateOptionalTimeParser());
232     }
233 
234     /**
235      * Constructs a YearMonthDay from an Object that represents a time, using the
236      * specified chronology.
237      * <p>
238      * The recognised object types are defined in
239      * {@link org.joda.time.convert.ConverterManager ConverterManager} and
240      * include ReadableInstant, String, Calendar and Date.
241      * The String formats are described by {@link ISODateTimeFormat#dateOptionalTimeParser()}.
242      * <p>
243      * The constructor uses the time zone of the chronology specified.
244      * Once the constructor is complete, all further calculations are performed
245      * without reference to a timezone (by switching to UTC).
246      * The specified chronology overrides that of the object.
247      * <p>
248      * NOTE: Prior to v1.3 the string format was described by
249      * {@link ISODateTimeFormat#dateTimeParser()}. Time only strings are now rejected.
250      *
251      * @param instant  the datetime object, null means now
252      * @param chronology  the chronology, null means ISO default
253      * @throws IllegalArgumentException if the instant is invalid
254      */
255     public YearMonthDay(Object instant, Chronology chronology) {
256         super(instant, DateTimeUtils.getChronology(chronology), ISODateTimeFormat.dateOptionalTimeParser());
257     }
258 
259     /**
260      * Constructs a YearMonthDay with specified time field values
261      * using <code>ISOChronology</code> in the default zone.
262      * <p>
263      * The constructor uses the no time zone initialising the fields as provided.
264      * Once the constructor is complete, all further calculations
265      * are performed without reference to a timezone (by switching to UTC).
266      *
267      * @param year  the year
268      * @param monthOfYear  the month of the year
269      * @param dayOfMonth  the day of the month
270      */
271     public YearMonthDay(int year, int monthOfYear, int dayOfMonth) {
272         this(year, monthOfYear, dayOfMonth, null);
273     }
274 
275     /**
276      * Constructs a YearMonthDay with specified time field values.
277      * <p>
278      * The constructor uses the time zone of the chronology specified.
279      * Once the constructor is complete, all further calculations are performed
280      * without reference to a timezone (by switching to UTC).
281      *
282      * @param year  the year
283      * @param monthOfYear  the month of the year
284      * @param dayOfMonth  the day of the month
285      * @param chronology  the chronology, null means ISOChronology in the default zone
286      */
287     public YearMonthDay(int year, int monthOfYear, int dayOfMonth, Chronology chronology) {
288         super(new int[] {year, monthOfYear, dayOfMonth}, chronology);
289     }
290 
291     /**
292      * Constructs a YearMonthDay with chronology from this instance and new values.
293      *
294      * @param partial  the partial to base this new instance on
295      * @param values  the new set of values
296      */
297     YearMonthDay(YearMonthDay partial, int[] values) {
298         super(partial, values);
299     }
300 
301     /**
302      * Constructs a YearMonthDay with values from this instance and a new chronology.
303      *
304      * @param partial  the partial to base this new instance on
305      * @param chrono  the new chronology
306      */
307     YearMonthDay(YearMonthDay partial, Chronology chrono) {
308         super(partial, chrono);
309     }
310 
311     //-----------------------------------------------------------------------
312     /**
313      * Gets the number of fields in this partial.
314      * 
315      * @return the field count
316      */
317     public int size() {
318         return 3;
319     }
320 
321     /**
322      * Gets the field for a specific index in the chronology specified.
323      * <p>
324      * This method must not use any instance variables.
325      * 
326      * @param index  the index to retrieve
327      * @param chrono  the chronology to use
328      * @return the field
329      */
330     protected DateTimeField getField(int index, Chronology chrono) {
331         switch (index) {
332             case YEAR:
333                 return chrono.year();
334             case MONTH_OF_YEAR:
335                 return chrono.monthOfYear();
336             case DAY_OF_MONTH:
337                 return chrono.dayOfMonth();
338             default:
339                 throw new IndexOutOfBoundsException("Invalid index: " + index);
340         }
341     }
342 
343     /**
344      * Gets the field type at the specified index.
345      *
346      * @param index  the index to retrieve
347      * @return the field at the specified index
348      * @throws IndexOutOfBoundsException if the index is invalid
349      */
350     public DateTimeFieldType getFieldType(int index) {
351         return FIELD_TYPES[index];
352     }
353 
354     /**
355      * Gets an array of the field type of each of the fields that this partial supports.
356      * <p>
357      * The fields are returned largest to smallest, Year, Month, Day
358      *
359      * @return the array of field types (cloned), largest to smallest
360      */
361     public DateTimeFieldType[] getFieldTypes() {
362         return (DateTimeFieldType[]) FIELD_TYPES.clone();
363     }
364 
365     //-----------------------------------------------------------------------
366     /**
367      * Returns a copy of this date with the specified chronology.
368      * This instance is immutable and unaffected by this method call.
369      * <p>
370      * This method retains the values of the fields, thus the result will
371      * typically refer to a different instant.
372      * <p>
373      * The time zone of the specified chronology is ignored, as YearMonthDay
374      * operates without a time zone.
375      *
376      * @param newChronology  the new chronology, null means ISO
377      * @return a copy of this datetime with a different chronology
378      * @throws IllegalArgumentException if the values are invalid for the new chronology
379      */
380     public YearMonthDay withChronologyRetainFields(Chronology newChronology) {
381         newChronology = DateTimeUtils.getChronology(newChronology);
382         newChronology = newChronology.withUTC();
383         if (newChronology == getChronology()) {
384             return this;
385         } else {
386             YearMonthDay newYearMonthDay = new YearMonthDay(this, newChronology);
387             newChronology.validate(newYearMonthDay, getValues());
388             return newYearMonthDay;
389         }
390     }
391 
392     /**
393      * Returns a copy of this date with the specified field set to a new value.
394      * <p>
395      * For example, if the field type is <code>dayOfMonth</code> then the day
396      * would be changed in the returned instance.
397      * <p>
398      * These three lines are equivalent:
399      * <pre>
400      * YearMonthDay updated = ymd.withField(DateTimeFieldType.dayOfMonth(), 6);
401      * YearMonthDay updated = ymd.dayOfMonth().setCopy(6);
402      * YearMonthDay updated = ymd.property(DateTimeFieldType.dayOfMonth()).setCopy(6);
403      * </pre>
404      *
405      * @param fieldType  the field type to set, not null
406      * @param value  the value to set
407      * @return a copy of this instance with the field set
408      * @throws IllegalArgumentException if the value is null or invalid
409      */
410     public YearMonthDay withField(DateTimeFieldType fieldType, int value) {
411         int index = indexOfSupported(fieldType);
412         if (value == getValue(index)) {
413             return this;
414         }
415         int[] newValues = getValues();
416         newValues = getField(index).set(this, index, newValues, value);
417         return new YearMonthDay(this, newValues);
418     }
419 
420     /**
421      * Returns a copy of this date with the value of the specified field increased.
422      * <p>
423      * If the addition is zero, then <code>this</code> is returned.
424      * <p>
425      * These three lines are equivalent:
426      * <pre>
427      * YearMonthDay added = ymd.withFieldAdded(DurationFieldType.days(), 6);
428      * YearMonthDay added = ymd.plusDays(6);
429      * YearMonthDay added = ymd.dayOfMonth().addToCopy(6);
430      * </pre>
431      * 
432      * @param fieldType  the field type to add to, not null
433      * @param amount  the amount to add
434      * @return a copy of this instance with the field updated
435      * @throws IllegalArgumentException if the value is null or invalid
436      * @throws ArithmeticException if the new datetime exceeds the capacity
437      */
438     public YearMonthDay withFieldAdded(DurationFieldType fieldType, int amount) {
439         int index = indexOfSupported(fieldType);
440         if (amount == 0) {
441             return this;
442         }
443         int[] newValues = getValues();
444         newValues = getField(index).add(this, index, newValues, amount);
445         return new YearMonthDay(this, newValues);
446     }
447 
448     /**
449      * Returns a copy of this date with the specified period added.
450      * <p>
451      * If the addition is zero, then <code>this</code> is returned.
452      * Fields in the period that aren't present in the partial are ignored.
453      * <p>
454      * This method is typically used to add multiple copies of complex
455      * period instances. Adding one field is best achieved using methods
456      * like {@link #withFieldAdded(DurationFieldType, int)}
457      * or {@link #plusYears(int)}.
458      * 
459      * @param period  the period to add to this one, null means zero
460      * @param scalar  the amount of times to add, such as -1 to subtract once
461      * @return a copy of this instance with the period added
462      * @throws ArithmeticException if the new datetime exceeds the capacity
463      */
464     public YearMonthDay withPeriodAdded(ReadablePeriod period, int scalar) {
465         if (period == null || scalar == 0) {
466             return this;
467         }
468         int[] newValues = getValues();
469         for (int i = 0; i < period.size(); i++) {
470             DurationFieldType fieldType = period.getFieldType(i);
471             int index = indexOf(fieldType);
472             if (index >= 0) {
473                 newValues = getField(index).add(this, index, newValues,
474                         FieldUtils.safeMultiply(period.getValue(i), scalar));
475             }
476         }
477         return new YearMonthDay(this, newValues);
478     }
479 
480     //-----------------------------------------------------------------------
481     /**
482      * Returns a copy of this date with the specified period added.
483      * <p>
484      * If the amount is zero or null, then <code>this</code> is returned.
485      * <p>
486      * This method is typically used to add complex period instances.
487      * Adding one field is best achieved using methods
488      * like {@link #plusYears(int)}.
489      * 
490      * @param period  the duration to add to this one, null means zero
491      * @return a copy of this instance with the period added
492      * @throws ArithmeticException if the new datetime exceeds the capacity of a long
493      */
494     public YearMonthDay plus(ReadablePeriod period) {
495         return withPeriodAdded(period, 1);
496     }
497 
498     //-----------------------------------------------------------------------
499     /**
500      * Returns a copy of this date plus the specified number of years.
501      * <p>
502      * This date instance is immutable and unaffected by this method call.
503      * <p>
504      * The following three lines are identical in effect:
505      * <pre>
506      * YearMonthDay added = dt.plusYears(6);
507      * YearMonthDay added = dt.plus(Period.years(6));
508      * YearMonthDay added = dt.withFieldAdded(DurationFieldType.years(), 6);
509      * </pre>
510      *
511      * @param years  the amount of years to add, may be negative
512      * @return the new date plus the increased years
513      * @since 1.1
514      */
515     public YearMonthDay plusYears(int years) {
516         return withFieldAdded(DurationFieldType.years(), years);
517     }
518 
519     /**
520      * Returns a copy of this date plus the specified number of months.
521      * <p>
522      * This date instance is immutable and unaffected by this method call.
523      * <p>
524      * The following three lines are identical in effect:
525      * <pre>
526      * YearMonthDay added = dt.plusMonths(6);
527      * YearMonthDay added = dt.plus(Period.months(6));
528      * YearMonthDay added = dt.withFieldAdded(DurationFieldType.months(), 6);
529      * </pre>
530      *
531      * @param months  the amount of months to add, may be negative
532      * @return the new date plus the increased months
533      * @since 1.1
534      */
535     public YearMonthDay plusMonths(int months) {
536         return withFieldAdded(DurationFieldType.months(), months);
537     }
538 
539     /**
540      * Returns a copy of this date plus the specified number of days.
541      * <p>
542      * This date instance is immutable and unaffected by this method call.
543      * <p>
544      * The following three lines are identical in effect:
545      * <pre>
546      * YearMonthDay added = dt.plusDays(6);
547      * YearMonthDay added = dt.plus(Period.days(6));
548      * YearMonthDay added = dt.withFieldAdded(DurationFieldType.days(), 6);
549      * </pre>
550      *
551      * @param days  the amount of days to add, may be negative
552      * @return the new date plus the increased days
553      * @since 1.1
554      */
555     public YearMonthDay plusDays(int days) {
556         return withFieldAdded(DurationFieldType.days(), days);
557     }
558 
559     //-----------------------------------------------------------------------
560     /**
561      * Returns a copy of this date with the specified period taken away.
562      * <p>
563      * If the amount is zero or null, then <code>this</code> is returned.
564      * <p>
565      * This method is typically used to subtract complex period instances.
566      * Subtracting one field is best achieved using methods
567      * like {@link #minusYears(int)}.
568      * 
569      * @param period  the period to reduce this instant by
570      * @return a copy of this instance with the period taken away
571      * @throws ArithmeticException if the new datetime exceeds the capacity of a long
572      */
573     public YearMonthDay minus(ReadablePeriod period) {
574         return withPeriodAdded(period, -1);
575     }
576 
577     //-----------------------------------------------------------------------
578     /**
579      * Returns a copy of this date minus the specified number of years.
580      * <p>
581      * This datetime instance is immutable and unaffected by this method call.
582      * <p>
583      * The following three lines are identical in effect:
584      * <pre>
585      * YearMonthDay subtracted = dt.minusYears(6);
586      * YearMonthDay subtracted = dt.minus(Period.years(6));
587      * YearMonthDay subtracted = dt.withFieldAdded(DurationFieldType.years(), -6);
588      * </pre>
589      *
590      * @param years  the amount of years to subtract, may be negative
591      * @return the new datetime minus the increased years
592      * @since 1.1
593      */
594     public YearMonthDay minusYears(int years) {
595         return withFieldAdded(DurationFieldType.years(), FieldUtils.safeNegate(years));
596     }
597 
598     /**
599      * Returns a copy of this date minus the specified number of months.
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      * YearMonthDay subtracted = dt.minusMonths(6);
606      * YearMonthDay subtracted = dt.minus(Period.months(6));
607      * YearMonthDay subtracted = dt.withFieldAdded(DurationFieldType.months(), -6);
608      * </pre>
609      *
610      * @param months  the amount of months to subtract, may be negative
611      * @return the new datetime minus the increased months
612      * @since 1.1
613      */
614     public YearMonthDay minusMonths(int months) {
615         return withFieldAdded(DurationFieldType.months(), FieldUtils.safeNegate(months));
616     }
617 
618     /**
619      * Returns a copy of this date minus the specified number of days.
620      * <p>
621      * This datetime instance is immutable and unaffected by this method call.
622      * <p>
623      * The following three lines are identical in effect:
624      * <pre>
625      * YearMonthDay subtracted = dt.minusDays(6);
626      * YearMonthDay subtracted = dt.minus(Period.days(6));
627      * YearMonthDay subtracted = dt.withFieldAdded(DurationFieldType.days(), -6);
628      * </pre>
629      *
630      * @param days  the amount of days to subtract, may be negative
631      * @return the new datetime minus the increased days
632      * @since 1.1
633      */
634     public YearMonthDay minusDays(int days) {
635         return withFieldAdded(DurationFieldType.days(), FieldUtils.safeNegate(days));
636     }
637 
638     //-----------------------------------------------------------------------
639     /**
640      * Gets the property object for the specified type, which contains
641      * many useful methods.
642      *
643      * @param type  the field type to get the property for
644      * @return the property object
645      * @throws IllegalArgumentException if the field is null or unsupported
646      */
647     public Property property(DateTimeFieldType type) {
648         return new Property(this, indexOfSupported(type));
649     }
650 
651     //-----------------------------------------------------------------------
652     /**
653      * Converts this object to a LocalDate with the same date and chronology.
654      *
655      * @return a LocalDate with the same date and chronology
656      * @since 1.3
657      */
658     public LocalDate toLocalDate() {
659         return new LocalDate(getYear(), getMonthOfYear(), getDayOfMonth(), getChronology());
660     }
661 
662     //-----------------------------------------------------------------------
663     /**
664      * Converts this YearMonthDay to a full datetime at midnight using the
665      * default time zone.
666      *
667      * @return this date as a datetime at midnight
668      */
669     public DateTime toDateTimeAtMidnight() {
670         return toDateTimeAtMidnight(null);
671     }
672 
673     /**
674      * Converts this YearMonthDay to a full datetime at midnight using the
675      * specified time zone.
676      * <p>
677      * This method uses the chronology from this instance plus the time zone
678      * specified.
679      *
680      * @param zone  the zone to use, null means default
681      * @return this date as a datetime at midnight
682      */
683     public DateTime toDateTimeAtMidnight(DateTimeZone zone) {
684         Chronology chrono = getChronology().withZone(zone);
685         return new DateTime(getYear(), getMonthOfYear(), getDayOfMonth(), 0, 0, 0, 0, chrono);
686     }
687 
688     //-----------------------------------------------------------------------
689     /**
690      * Converts this partial to a full datetime using the default time zone
691      * setting the date fields from this instance and the time fields from
692      * the current time.
693      *
694      * @return this date as a datetime with the time as the current time
695      */
696     public DateTime toDateTimeAtCurrentTime() {
697         return toDateTimeAtCurrentTime(null);
698     }
699 
700     /**
701      * Converts this partial to a full datetime using the specified time zone
702      * setting the date fields from this instance and the time fields from
703      * the current time.
704      * <p>
705      * This method uses the chronology from this instance plus the time zone
706      * specified.
707      *
708      * @param zone  the zone to use, null means default
709      * @return this date as a datetime with the time as the current time
710      */
711     public DateTime toDateTimeAtCurrentTime(DateTimeZone zone) {
712         Chronology chrono = getChronology().withZone(zone);
713         long instantMillis = DateTimeUtils.currentTimeMillis();
714         long resolved = chrono.set(this, instantMillis);
715         return new DateTime(resolved, chrono);
716     }
717 
718     //-----------------------------------------------------------------------
719     /**
720      * Converts this object to a DateMidnight in the default time zone.
721      *
722      * @return the DateMidnight instance in the default zone
723      */
724     public DateMidnight toDateMidnight() {
725         return toDateMidnight(null);
726     }
727 
728     /**
729      * Converts this object to a DateMidnight.
730      *
731      * @param zone  the zone to get the DateMidnight in, null means default
732      * @return the DateMidnight instance
733      */
734     public DateMidnight toDateMidnight(DateTimeZone zone) {
735         Chronology chrono = getChronology().withZone(zone);
736         return new DateMidnight(getYear(), getMonthOfYear(), getDayOfMonth(), chrono);
737     }
738 
739     //-----------------------------------------------------------------------
740     /**
741      * Converts this object to a DateTime using a TimeOfDay to fill in the
742      * missing fields and using the default time zone.
743      * This instance is immutable and unaffected by this method call.
744      * <p>
745      * The resulting chronology is determined by the chronology of this
746      * YearMonthDay plus the time zone.
747      * The chronology of the time is ignored - only the field values are used.
748      *
749      * @param time  the time of day to use, null means current time
750      * @return the DateTime instance
751      */
752     public DateTime toDateTime(TimeOfDay time) {
753         return toDateTime(time, null);
754     }
755 
756     /**
757      * Converts this object to a DateTime using a TimeOfDay to fill in the
758      * missing fields.
759      * This instance is immutable and unaffected by this method call.
760      * <p>
761      * The resulting chronology is determined by the chronology of this
762      * YearMonthDay plus the time zone.
763      * The chronology of the time is ignored - only the field values are used.
764      *
765      * @param time  the time of day to use, null means current time
766      * @param zone  the zone to get the DateTime in, null means default
767      * @return the DateTime instance
768      */
769     public DateTime toDateTime(TimeOfDay time, DateTimeZone zone) {
770         Chronology chrono = getChronology().withZone(zone);
771         long instant = DateTimeUtils.currentTimeMillis();
772         instant = chrono.set(this, instant);
773         if (time != null) {
774             instant = chrono.set(time, instant);
775         }
776         return new DateTime(instant, chrono);
777     }
778 
779     //-----------------------------------------------------------------------
780     /**
781      * Converts this object to an Interval representing the whole day
782      * in the default time zone.
783      *
784      * @return a interval over the day
785      */
786     public Interval toInterval() {
787         return toInterval(null);
788     }
789 
790     /**
791      * Converts this object to an Interval representing the whole day.
792      *
793      * @param zone  the zone to get the Interval in, null means default
794      * @return a interval over the day
795      */
796     public Interval toInterval(DateTimeZone zone) {
797         zone = DateTimeUtils.getZone(zone);
798         return toDateMidnight(zone).toInterval();
799     }
800 
801     //-----------------------------------------------------------------------
802     /**
803      * Get the year field value.
804      *
805      * @return the year
806      */
807     public int getYear() {
808         return getValue(YEAR);
809     }
810 
811     /**
812      * Get the month of year field value.
813      *
814      * @return the month of year
815      */
816     public int getMonthOfYear() {
817         return getValue(MONTH_OF_YEAR);
818     }
819 
820     /**
821      * Get the day of month field value.
822      *
823      * @return the day of month
824      */
825     public int getDayOfMonth() {
826         return getValue(DAY_OF_MONTH);
827     }
828 
829     //-----------------------------------------------------------------------
830     /**
831      * Returns a copy of this date with the year field updated.
832      * <p>
833      * YearMonthDay is immutable, so there are no set methods.
834      * Instead, this method returns a new instance with the value of
835      * year changed.
836      *
837      * @param year  the year to set
838      * @return a copy of this object with the field set
839      * @throws IllegalArgumentException if the value is invalid
840      * @since 1.3
841      */
842     public YearMonthDay withYear(int year) {
843         int[] newValues = getValues();
844         newValues = getChronology().year().set(this, YEAR, newValues, year);
845         return new YearMonthDay(this, newValues);
846     }
847 
848     /**
849      * Returns a copy of this date with the month of year field updated.
850      * <p>
851      * YearMonthDay is immutable, so there are no set methods.
852      * Instead, this method returns a new instance with the value of
853      * month of year changed.
854      *
855      * @param monthOfYear  the month of year to set
856      * @return a copy of this object with the field set
857      * @throws IllegalArgumentException if the value is invalid
858      * @since 1.3
859      */
860     public YearMonthDay withMonthOfYear(int monthOfYear) {
861         int[] newValues = getValues();
862         newValues = getChronology().monthOfYear().set(this, MONTH_OF_YEAR, newValues, monthOfYear);
863         return new YearMonthDay(this, newValues);
864     }
865 
866     /**
867      * Returns a copy of this date with the day of month field updated.
868      * <p>
869      * YearMonthDay is immutable, so there are no set methods.
870      * Instead, this method returns a new instance with the value of
871      * day of month changed.
872      *
873      * @param dayOfMonth  the day of month to set
874      * @return a copy of this object with the field set
875      * @throws IllegalArgumentException if the value is invalid
876      * @since 1.3
877      */
878     public YearMonthDay withDayOfMonth(int dayOfMonth) {
879         int[] newValues = getValues();
880         newValues = getChronology().dayOfMonth().set(this, DAY_OF_MONTH, newValues, dayOfMonth);
881         return new YearMonthDay(this, newValues);
882     }
883 
884     //-----------------------------------------------------------------------
885     /**
886      * Get the year field property which provides access to advanced functionality.
887      * 
888      * @return the year property
889      */
890     public Property year() {
891         return new Property(this, YEAR);
892     }
893 
894     /**
895      * Get the month of year field property which provides access to advanced functionality.
896      * 
897      * @return the month of year property
898      */
899     public Property monthOfYear() {
900         return new Property(this, MONTH_OF_YEAR);
901     }
902 
903     /**
904      * Get the day of month field property which provides access to advanced functionality.
905      * 
906      * @return the day of month property
907      */
908     public Property dayOfMonth() {
909         return new Property(this, DAY_OF_MONTH);
910     }
911 
912     //-----------------------------------------------------------------------
913     /**
914      * Output the date in the ISO8601 format YYYY-MM-DD.
915      * 
916      * @return ISO8601 formatted string
917      */
918     public String toString() {
919         return ISODateTimeFormat.yearMonthDay().print(this);
920     }
921 
922     //-----------------------------------------------------------------------
923     /**
924      * The property class for <code>YearMonthDay</code>.
925      * <p>
926      * This class binds a <code>YearMonthDay</code> to a <code>DateTimeField</code>.
927      * 
928      * @author Stephen Colebourne
929      * @since 1.0
930      * @deprecated Use LocalDate which has a much better internal implementation
931      */
932     @Deprecated
933     public static class Property extends AbstractPartialFieldProperty implements Serializable {
934 
935         /** Serialization version */
936         private static final long serialVersionUID = 5727734012190224363L;
937 
938         /** The partial */
939         private final YearMonthDay iYearMonthDay;
940         /** The field index */
941         private final int iFieldIndex;
942 
943         /**
944          * Constructs a property.
945          * 
946          * @param partial  the partial instance
947          * @param fieldIndex  the index in the partial
948          */
949         Property(YearMonthDay partial, int fieldIndex) {
950             super();
951             iYearMonthDay = partial;
952             iFieldIndex = fieldIndex;
953         }
954 
955         /**
956          * Gets the field that this property uses.
957          * 
958          * @return the field
959          */
960         public DateTimeField getField() {
961             return iYearMonthDay.getField(iFieldIndex);
962         }
963 
964         /**
965          * Gets the partial that this property belongs to.
966          * 
967          * @return the partial
968          */
969         protected ReadablePartial getReadablePartial() {
970             return iYearMonthDay;
971         }
972 
973         /**
974          * Gets the partial that this property belongs to.
975          * 
976          * @return the partial
977          */
978         public YearMonthDay getYearMonthDay() {
979             return iYearMonthDay;
980         }
981 
982         /**
983          * Gets the value of this field.
984          * 
985          * @return the field value
986          */
987         public int get() {
988             return iYearMonthDay.getValue(iFieldIndex);
989         }
990 
991         //-----------------------------------------------------------------------
992         /**
993          * Adds to the value of this field in a copy of this YearMonthDay.
994          * <p>
995          * The value will be added to this field. If the value is too large to be
996          * added solely to this field then it will affect larger fields.
997          * Smaller fields are unaffected.
998          * <p>
999          * If the result would be too large, beyond the maximum year, then an
1000          * IllegalArgumentException is thrown.
1001          * <p>
1002          * The YearMonthDay attached to this property is unchanged by this call.
1003          * Instead, a new instance is returned.
1004          * 
1005          * @param valueToAdd  the value to add to the field in the copy
1006          * @return a copy of the YearMonthDay with the field value changed
1007          * @throws IllegalArgumentException if the value isn't valid
1008          */
1009         public YearMonthDay addToCopy(int valueToAdd) {
1010             int[] newValues = iYearMonthDay.getValues();
1011             newValues = getField().add(iYearMonthDay, iFieldIndex, newValues, valueToAdd);
1012             return new YearMonthDay(iYearMonthDay, newValues);
1013         }
1014 
1015         /**
1016          * Adds to the value of this field in a copy of this YearMonthDay wrapping
1017          * within this field if the maximum value is reached.
1018          * <p>
1019          * The value will be added to this field. If the value is too large to be
1020          * added solely to this field then it wraps within this field.
1021          * Other fields are unaffected.
1022          * <p>
1023          * For example,
1024          * <code>2004-12-20</code> addWrapField one month returns <code>2004-01-20</code>.
1025          * <p>
1026          * The YearMonthDay attached to this property is unchanged by this call.
1027          * Instead, a new instance is returned.
1028          * 
1029          * @param valueToAdd  the value to add to the field in the copy
1030          * @return a copy of the YearMonthDay with the field value changed
1031          * @throws IllegalArgumentException if the value isn't valid
1032          */
1033         public YearMonthDay addWrapFieldToCopy(int valueToAdd) {
1034             int[] newValues = iYearMonthDay.getValues();
1035             newValues = getField().addWrapField(iYearMonthDay, iFieldIndex, newValues, valueToAdd);
1036             return new YearMonthDay(iYearMonthDay, newValues);
1037         }
1038 
1039         //-----------------------------------------------------------------------
1040         /**
1041          * Sets this field in a copy of the YearMonthDay.
1042          * <p>
1043          * The YearMonthDay attached to this property is unchanged by this call.
1044          * Instead, a new instance is returned.
1045          * 
1046          * @param value  the value to set the field in the copy to
1047          * @return a copy of the YearMonthDay with the field value changed
1048          * @throws IllegalArgumentException if the value isn't valid
1049          */
1050         public YearMonthDay setCopy(int value) {
1051             int[] newValues = iYearMonthDay.getValues();
1052             newValues = getField().set(iYearMonthDay, iFieldIndex, newValues, value);
1053             return new YearMonthDay(iYearMonthDay, newValues);
1054         }
1055 
1056         /**
1057          * Sets this field in a copy of the YearMonthDay to a parsed text value.
1058          * <p>
1059          * The YearMonthDay attached to this property is unchanged by this call.
1060          * Instead, a new instance is returned.
1061          * 
1062          * @param text  the text value to set
1063          * @param locale  optional locale to use for selecting a text symbol
1064          * @return a copy of the YearMonthDay with the field value changed
1065          * @throws IllegalArgumentException if the text value isn't valid
1066          */
1067         public YearMonthDay setCopy(String text, Locale locale) {
1068             int[] newValues = iYearMonthDay.getValues();
1069             newValues = getField().set(iYearMonthDay, iFieldIndex, newValues, text, locale);
1070             return new YearMonthDay(iYearMonthDay, newValues);
1071         }
1072 
1073         /**
1074          * Sets this field in a copy of the YearMonthDay to a parsed text value.
1075          * <p>
1076          * The YearMonthDay attached to this property is unchanged by this call.
1077          * Instead, a new instance is returned.
1078          * 
1079          * @param text  the text value to set
1080          * @return a copy of the YearMonthDay with the field value changed
1081          * @throws IllegalArgumentException if the text value isn't valid
1082          */
1083         public YearMonthDay setCopy(String text) {
1084             return setCopy(text, null);
1085         }
1086 
1087         //-----------------------------------------------------------------------
1088         /**
1089          * Returns a new YearMonthDay with this field set to the maximum value
1090          * for this field.
1091          * <p>
1092          * This operation is useful for obtaining a DateTime on the last day
1093          * of the month, as month lengths vary.
1094          * <pre>
1095          * YearMonthDay lastDayOfMonth = dt.dayOfMonth().withMaximumValue();
1096          * </pre>
1097          * <p>
1098          * The YearMonthDay attached to this property is unchanged by this call.
1099          *
1100          * @return a copy of the YearMonthDay with this field set to its maximum
1101          * @since 1.2
1102          */
1103         public YearMonthDay withMaximumValue() {
1104             return setCopy(getMaximumValue());
1105         }
1106 
1107         /**
1108          * Returns a new YearMonthDay with this field set to the minimum value
1109          * for this field.
1110          * <p>
1111          * The YearMonthDay attached to this property is unchanged by this call.
1112          *
1113          * @return a copy of the YearMonthDay with this field set to its minimum
1114          * @since 1.2
1115          */
1116         public YearMonthDay withMinimumValue() {
1117             return setCopy(getMinimumValue());
1118         }
1119     }
1120 
1121 }