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 }