0001: /*
0002: * Copyright 2001-2006 Stephen Colebourne
0003: *
0004: * Licensed under the Apache License, Version 2.0 (the "License");
0005: * you may not use this file except in compliance with the License.
0006: * You may obtain a copy of the License at
0007: *
0008: * http://www.apache.org/licenses/LICENSE-2.0
0009: *
0010: * Unless required by applicable law or agreed to in writing, software
0011: * distributed under the License is distributed on an "AS IS" BASIS,
0012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013: * See the License for the specific language governing permissions and
0014: * limitations under the License.
0015: */
0016: package org.joda.time;
0017:
0018: import java.io.Serializable;
0019: import java.util.Calendar;
0020: import java.util.Date;
0021: import java.util.Locale;
0022:
0023: import org.joda.time.base.BasePartial;
0024: import org.joda.time.chrono.ISOChronology;
0025: import org.joda.time.field.AbstractPartialFieldProperty;
0026: import org.joda.time.field.FieldUtils;
0027: import org.joda.time.format.ISODateTimeFormat;
0028:
0029: /**
0030: * YearMonthDay is an immutable partial supporting the year, monthOfYear
0031: * and dayOfMonth fields.
0032: * <p>
0033: * NOTE: This class only supports the three fields listed above. Thus, you
0034: * cannot query the dayOfWeek or centuryOfEra fields for example.
0035: * The new <code>LocalDate</code> class removes this restriction.
0036: * <p>
0037: * Calculations on YearMonthDay are performed using a {@link Chronology}.
0038: * This chronology is set to be in the UTC time zone for all calculations.
0039: * <p>
0040: * Each individual field can be queried in two ways:
0041: * <ul>
0042: * <li><code>getMonthOfYear()</code>
0043: * <li><code>monthOfYear().get()</code>
0044: * </ul>
0045: * The second technique also provides access to other useful methods on the
0046: * field:
0047: * <ul>
0048: * <li>numeric value - <code>monthOfYear().get()</code>
0049: * <li>text value - <code>monthOfYear().getAsText()</code>
0050: * <li>short text value - <code>monthOfYear().getAsShortText()</code>
0051: * <li>maximum/minimum values - <code>monthOfYear().getMaximumValue()</code>
0052: * <li>add/subtract - <code>monthOfYear().addToCopy()</code>
0053: * <li>set - <code>monthOfYear().setCopy()</code>
0054: * </ul>
0055: * <p>
0056: * YearMonthDay is thread-safe and immutable, provided that the Chronology is as well.
0057: * All standard Chronology classes supplied are thread-safe and immutable.
0058: *
0059: * @author Stephen Colebourne
0060: * @since 1.0
0061: * @deprecated Use LocalDate which has a much better internal implementation and
0062: * has been available since 1.3
0063: */
0064: public final class YearMonthDay extends BasePartial implements
0065: ReadablePartial, Serializable {
0066:
0067: /** Serialization version */
0068: private static final long serialVersionUID = 797544782896179L;
0069: /** The singleton set of field types */
0070: private static final DateTimeFieldType[] FIELD_TYPES = new DateTimeFieldType[] {
0071: DateTimeFieldType.year(), DateTimeFieldType.monthOfYear(),
0072: DateTimeFieldType.dayOfMonth(), };
0073:
0074: /** The index of the year field in the field array */
0075: public static final int YEAR = 0;
0076: /** The index of the monthOfYear field in the field array */
0077: public static final int MONTH_OF_YEAR = 1;
0078: /** The index of the dayOfMonth field in the field array */
0079: public static final int DAY_OF_MONTH = 2;
0080:
0081: //-----------------------------------------------------------------------
0082: /**
0083: * Constructs a YearMonthDay from a <code>java.util.Calendar</code>
0084: * using exactly the same field values avoiding any time zone effects.
0085: * <p>
0086: * Each field is queried from the Calendar and assigned to the YearMonthDay.
0087: * This is useful if you have been using the Calendar as a local date,
0088: * ignoing the zone.
0089: * <p>
0090: * This factory method ignores the type of the calendar and always
0091: * creates a YearMonthDay with ISO chronology. It is expected that you
0092: * will only pass in instances of <code>GregorianCalendar</code> however
0093: * this is not validated.
0094: *
0095: * @param calendar the Calendar to extract fields from
0096: * @return the created YearMonthDay
0097: * @throws IllegalArgumentException if the calendar is null
0098: * @throws IllegalArgumentException if the date is invalid for the ISO chronology
0099: * @since 1.2
0100: */
0101: public static YearMonthDay fromCalendarFields(Calendar calendar) {
0102: if (calendar == null) {
0103: throw new IllegalArgumentException(
0104: "The calendar must not be null");
0105: }
0106: return new YearMonthDay(calendar.get(Calendar.YEAR), calendar
0107: .get(Calendar.MONTH) + 1, calendar
0108: .get(Calendar.DAY_OF_MONTH));
0109: }
0110:
0111: /**
0112: * Constructs a YearMonthDay from a <code>java.util.Date</code>
0113: * using exactly the same field values avoiding any time zone effects.
0114: * <p>
0115: * Each field is queried from the Date and assigned to the YearMonthDay.
0116: * This is useful if you have been using the Date as a local date,
0117: * ignoing the zone.
0118: * <p>
0119: * This factory method always creates a YearMonthDay with ISO chronology.
0120: *
0121: * @param date the Date to extract fields from
0122: * @return the created YearMonthDay
0123: * @throws IllegalArgumentException if the calendar is null
0124: * @throws IllegalArgumentException if the date is invalid for the ISO chronology
0125: * @since 1.2
0126: */
0127: public static YearMonthDay fromDateFields(Date date) {
0128: if (date == null) {
0129: throw new IllegalArgumentException(
0130: "The date must not be null");
0131: }
0132: return new YearMonthDay(date.getYear() + 1900,
0133: date.getMonth() + 1, date.getDate());
0134: }
0135:
0136: //-----------------------------------------------------------------------
0137: /**
0138: * Constructs a YearMonthDay with the current date, using ISOChronology in
0139: * the default zone to extract the fields.
0140: * <p>
0141: * The constructor uses the default time zone, resulting in the local time
0142: * being initialised. Once the constructor is complete, all further calculations
0143: * are performed without reference to a timezone (by switching to UTC).
0144: */
0145: public YearMonthDay() {
0146: super ();
0147: }
0148:
0149: /**
0150: * Constructs a YearMonthDay with the current date, using ISOChronology in
0151: * the specified zone to extract the fields.
0152: * <p>
0153: * The constructor uses the specified time zone to obtain the current date.
0154: * Once the constructor is complete, all further calculations
0155: * are performed without reference to a timezone (by switching to UTC).
0156: *
0157: * @param zone the zone to use, null means default zone
0158: * @since 1.1
0159: */
0160: public YearMonthDay(DateTimeZone zone) {
0161: super (ISOChronology.getInstance(zone));
0162: }
0163:
0164: /**
0165: * Constructs a YearMonthDay with the current date, using the specified chronology
0166: * and zone to extract the fields.
0167: * <p>
0168: * The constructor uses the time zone of the chronology specified.
0169: * Once the constructor is complete, all further calculations are performed
0170: * without reference to a timezone (by switching to UTC).
0171: *
0172: * @param chronology the chronology, null means ISOChronology in the default zone
0173: */
0174: public YearMonthDay(Chronology chronology) {
0175: super (chronology);
0176: }
0177:
0178: /**
0179: * Constructs a YearMonthDay extracting the partial fields from the specified
0180: * milliseconds using the ISOChronology in the default zone.
0181: * <p>
0182: * The constructor uses the default time zone, resulting in the local time
0183: * being initialised. Once the constructor is complete, all further calculations
0184: * are performed without reference to a timezone (by switching to UTC).
0185: *
0186: * @param instant the milliseconds from 1970-01-01T00:00:00Z
0187: */
0188: public YearMonthDay(long instant) {
0189: super (instant);
0190: }
0191:
0192: /**
0193: * Constructs a YearMonthDay extracting the partial fields from the specified
0194: * milliseconds using the chronology provided.
0195: * <p>
0196: * The constructor uses the time zone of the chronology specified.
0197: * Once the constructor is complete, all further calculations are performed
0198: * without reference to a timezone (by switching to UTC).
0199: *
0200: * @param instant the milliseconds from 1970-01-01T00:00:00Z
0201: * @param chronology the chronology, null means ISOChronology in the default zone
0202: */
0203: public YearMonthDay(long instant, Chronology chronology) {
0204: super (instant, chronology);
0205: }
0206:
0207: /**
0208: * Constructs a YearMonthDay from an Object that represents a time.
0209: * <p>
0210: * The recognised object types are defined in
0211: * {@link org.joda.time.convert.ConverterManager ConverterManager} and
0212: * include ReadableInstant, String, Calendar and Date.
0213: * The String formats are described by {@link ISODateTimeFormat#dateOptionalTimeParser()}.
0214: * <p>
0215: * The chronology used will be derived from the object, defaulting to ISO.
0216: * <p>
0217: * NOTE: Prior to v1.3 the string format was described by
0218: * {@link ISODateTimeFormat#dateTimeParser()}. Time ony strings are now rejected.
0219: *
0220: * @param instant the datetime object, null means now
0221: * @throws IllegalArgumentException if the instant is invalid
0222: */
0223: public YearMonthDay(Object instant) {
0224: super (instant, null, ISODateTimeFormat.dateOptionalTimeParser());
0225: }
0226:
0227: /**
0228: * Constructs a YearMonthDay from an Object that represents a time, using the
0229: * specified chronology.
0230: * <p>
0231: * The recognised object types are defined in
0232: * {@link org.joda.time.convert.ConverterManager ConverterManager} and
0233: * include ReadableInstant, String, Calendar and Date.
0234: * The String formats are described by {@link ISODateTimeFormat#dateOptionalTimeParser()}.
0235: * <p>
0236: * The constructor uses the time zone of the chronology specified.
0237: * Once the constructor is complete, all further calculations are performed
0238: * without reference to a timezone (by switching to UTC).
0239: * The specified chronology overrides that of the object.
0240: * <p>
0241: * NOTE: Prior to v1.3 the string format was described by
0242: * {@link ISODateTimeFormat#dateTimeParser()}. Time only strings are now rejected.
0243: *
0244: * @param instant the datetime object, null means now
0245: * @param chronology the chronology, null means ISO default
0246: * @throws IllegalArgumentException if the instant is invalid
0247: */
0248: public YearMonthDay(Object instant, Chronology chronology) {
0249: super (instant, DateTimeUtils.getChronology(chronology),
0250: ISODateTimeFormat.dateOptionalTimeParser());
0251: }
0252:
0253: /**
0254: * Constructs a YearMonthDay with specified time field values
0255: * using <code>ISOChronology</code> in the default zone.
0256: * <p>
0257: * The constructor uses the no time zone initialising the fields as provided.
0258: * Once the constructor is complete, all further calculations
0259: * are performed without reference to a timezone (by switching to UTC).
0260: *
0261: * @param year the year
0262: * @param monthOfYear the month of the year
0263: * @param dayOfMonth the day of the month
0264: */
0265: public YearMonthDay(int year, int monthOfYear, int dayOfMonth) {
0266: this (year, monthOfYear, dayOfMonth, null);
0267: }
0268:
0269: /**
0270: * Constructs a YearMonthDay with specified time field values.
0271: * <p>
0272: * The constructor uses the time zone of the chronology specified.
0273: * Once the constructor is complete, all further calculations are performed
0274: * without reference to a timezone (by switching to UTC).
0275: *
0276: * @param year the year
0277: * @param monthOfYear the month of the year
0278: * @param dayOfMonth the day of the month
0279: * @param chronology the chronology, null means ISOChronology in the default zone
0280: */
0281: public YearMonthDay(int year, int monthOfYear, int dayOfMonth,
0282: Chronology chronology) {
0283: super (new int[] { year, monthOfYear, dayOfMonth }, chronology);
0284: }
0285:
0286: /**
0287: * Constructs a YearMonthDay with chronology from this instance and new values.
0288: *
0289: * @param partial the partial to base this new instance on
0290: * @param values the new set of values
0291: */
0292: YearMonthDay(YearMonthDay partial, int[] values) {
0293: super (partial, values);
0294: }
0295:
0296: /**
0297: * Constructs a YearMonthDay with values from this instance and a new chronology.
0298: *
0299: * @param partial the partial to base this new instance on
0300: * @param chrono the new chronology
0301: */
0302: YearMonthDay(YearMonthDay partial, Chronology chrono) {
0303: super (partial, chrono);
0304: }
0305:
0306: //-----------------------------------------------------------------------
0307: /**
0308: * Gets the number of fields in this partial.
0309: *
0310: * @return the field count
0311: */
0312: public int size() {
0313: return 3;
0314: }
0315:
0316: /**
0317: * Gets the field for a specific index in the chronology specified.
0318: * <p>
0319: * This method must not use any instance variables.
0320: *
0321: * @param index the index to retrieve
0322: * @param chrono the chronology to use
0323: * @return the field
0324: */
0325: protected DateTimeField getField(int index, Chronology chrono) {
0326: switch (index) {
0327: case YEAR:
0328: return chrono.year();
0329: case MONTH_OF_YEAR:
0330: return chrono.monthOfYear();
0331: case DAY_OF_MONTH:
0332: return chrono.dayOfMonth();
0333: default:
0334: throw new IndexOutOfBoundsException("Invalid index: "
0335: + index);
0336: }
0337: }
0338:
0339: /**
0340: * Gets the field type at the specified index.
0341: *
0342: * @param index the index to retrieve
0343: * @return the field at the specified index
0344: * @throws IndexOutOfBoundsException if the index is invalid
0345: */
0346: public DateTimeFieldType getFieldType(int index) {
0347: return FIELD_TYPES[index];
0348: }
0349:
0350: /**
0351: * Gets an array of the field type of each of the fields that this partial supports.
0352: * <p>
0353: * The fields are returned largest to smallest, Year, Month, Day
0354: *
0355: * @return the array of field types (cloned), largest to smallest
0356: */
0357: public DateTimeFieldType[] getFieldTypes() {
0358: return (DateTimeFieldType[]) FIELD_TYPES.clone();
0359: }
0360:
0361: //-----------------------------------------------------------------------
0362: /**
0363: * Returns a copy of this date with the specified chronology.
0364: * This instance is immutable and unaffected by this method call.
0365: * <p>
0366: * This method retains the values of the fields, thus the result will
0367: * typically refer to a different instant.
0368: * <p>
0369: * The time zone of the specified chronology is ignored, as YearMonthDay
0370: * operates without a time zone.
0371: *
0372: * @param newChronology the new chronology, null means ISO
0373: * @return a copy of this datetime with a different chronology
0374: * @throws IllegalArgumentException if the values are invalid for the new chronology
0375: */
0376: public YearMonthDay withChronologyRetainFields(
0377: Chronology newChronology) {
0378: newChronology = DateTimeUtils.getChronology(newChronology);
0379: newChronology = newChronology.withUTC();
0380: if (newChronology == getChronology()) {
0381: return this ;
0382: } else {
0383: YearMonthDay newYearMonthDay = new YearMonthDay(this ,
0384: newChronology);
0385: newChronology.validate(newYearMonthDay, getValues());
0386: return newYearMonthDay;
0387: }
0388: }
0389:
0390: /**
0391: * Returns a copy of this date with the specified field set to a new value.
0392: * <p>
0393: * For example, if the field type is <code>dayOfMonth</code> then the day
0394: * would be changed in the returned instance.
0395: * <p>
0396: * These three lines are equivalent:
0397: * <pre>
0398: * YearMonthDay updated = ymd.withField(DateTimeFieldType.dayOfMonth(), 6);
0399: * YearMonthDay updated = ymd.dayOfMonth().setCopy(6);
0400: * YearMonthDay updated = ymd.property(DateTimeFieldType.dayOfMonth()).setCopy(6);
0401: * </pre>
0402: *
0403: * @param fieldType the field type to set, not null
0404: * @param value the value to set
0405: * @return a copy of this instance with the field set
0406: * @throws IllegalArgumentException if the value is null or invalid
0407: */
0408: public YearMonthDay withField(DateTimeFieldType fieldType, int value) {
0409: int index = indexOfSupported(fieldType);
0410: if (value == getValue(index)) {
0411: return this ;
0412: }
0413: int[] newValues = getValues();
0414: newValues = getField(index).set(this , index, newValues, value);
0415: return new YearMonthDay(this , newValues);
0416: }
0417:
0418: /**
0419: * Returns a copy of this date with the value of the specified field increased.
0420: * <p>
0421: * If the addition is zero, then <code>this</code> is returned.
0422: * <p>
0423: * These three lines are equivalent:
0424: * <pre>
0425: * YearMonthDay added = ymd.withFieldAdded(DurationFieldType.days(), 6);
0426: * YearMonthDay added = ymd.plusDays(6);
0427: * YearMonthDay added = ymd.dayOfMonth().addToCopy(6);
0428: * </pre>
0429: *
0430: * @param fieldType the field type to add to, not null
0431: * @param amount the amount to add
0432: * @return a copy of this instance with the field updated
0433: * @throws IllegalArgumentException if the value is null or invalid
0434: * @throws ArithmeticException if the new datetime exceeds the capacity
0435: */
0436: public YearMonthDay withFieldAdded(DurationFieldType fieldType,
0437: int amount) {
0438: int index = indexOfSupported(fieldType);
0439: if (amount == 0) {
0440: return this ;
0441: }
0442: int[] newValues = getValues();
0443: newValues = getField(index).add(this , index, newValues, amount);
0444: return new YearMonthDay(this , newValues);
0445: }
0446:
0447: /**
0448: * Returns a copy of this date with the specified period added.
0449: * <p>
0450: * If the addition is zero, then <code>this</code> is returned.
0451: * Fields in the period that aren't present in the partial are ignored.
0452: * <p>
0453: * This method is typically used to add multiple copies of complex
0454: * period instances. Adding one field is best achieved using methods
0455: * like {@link #withFieldAdded(DurationFieldType, int)}
0456: * or {@link #plusYears(int)}.
0457: *
0458: * @param period the period to add to this one, null means zero
0459: * @param scalar the amount of times to add, such as -1 to subtract once
0460: * @return a copy of this instance with the period added
0461: * @throws ArithmeticException if the new datetime exceeds the capacity
0462: */
0463: public YearMonthDay withPeriodAdded(ReadablePeriod period,
0464: int scalar) {
0465: if (period == null || scalar == 0) {
0466: return this ;
0467: }
0468: int[] newValues = getValues();
0469: for (int i = 0; i < period.size(); i++) {
0470: DurationFieldType fieldType = period.getFieldType(i);
0471: int index = indexOf(fieldType);
0472: if (index >= 0) {
0473: newValues = getField(index).add(
0474: this ,
0475: index,
0476: newValues,
0477: FieldUtils.safeMultiply(period.getValue(i),
0478: scalar));
0479: }
0480: }
0481: return new YearMonthDay(this , newValues);
0482: }
0483:
0484: //-----------------------------------------------------------------------
0485: /**
0486: * Returns a copy of this date with the specified period added.
0487: * <p>
0488: * If the amount is zero or null, then <code>this</code> is returned.
0489: * <p>
0490: * This method is typically used to add complex period instances.
0491: * Adding one field is best achieved using methods
0492: * like {@link #plusYears(int)}.
0493: *
0494: * @param period the duration to add to this one, null means zero
0495: * @return a copy of this instance with the period added
0496: * @throws ArithmeticException if the new datetime exceeds the capacity of a long
0497: */
0498: public YearMonthDay plus(ReadablePeriod period) {
0499: return withPeriodAdded(period, 1);
0500: }
0501:
0502: //-----------------------------------------------------------------------
0503: /**
0504: * Returns a copy of this date plus the specified number of years.
0505: * <p>
0506: * This date instance is immutable and unaffected by this method call.
0507: * <p>
0508: * The following three lines are identical in effect:
0509: * <pre>
0510: * YearMonthDay added = dt.plusYears(6);
0511: * YearMonthDay added = dt.plus(Period.years(6));
0512: * YearMonthDay added = dt.withFieldAdded(DurationFieldType.years(), 6);
0513: * </pre>
0514: *
0515: * @param years the amount of years to add, may be negative
0516: * @return the new date plus the increased years
0517: * @since 1.1
0518: */
0519: public YearMonthDay plusYears(int years) {
0520: return withFieldAdded(DurationFieldType.years(), years);
0521: }
0522:
0523: /**
0524: * Returns a copy of this date plus the specified number of months.
0525: * <p>
0526: * This date instance is immutable and unaffected by this method call.
0527: * <p>
0528: * The following three lines are identical in effect:
0529: * <pre>
0530: * YearMonthDay added = dt.plusMonths(6);
0531: * YearMonthDay added = dt.plus(Period.months(6));
0532: * YearMonthDay added = dt.withFieldAdded(DurationFieldType.months(), 6);
0533: * </pre>
0534: *
0535: * @param months the amount of months to add, may be negative
0536: * @return the new date plus the increased months
0537: * @since 1.1
0538: */
0539: public YearMonthDay plusMonths(int months) {
0540: return withFieldAdded(DurationFieldType.months(), months);
0541: }
0542:
0543: /**
0544: * Returns a copy of this date plus the specified number of days.
0545: * <p>
0546: * This date instance is immutable and unaffected by this method call.
0547: * <p>
0548: * The following three lines are identical in effect:
0549: * <pre>
0550: * YearMonthDay added = dt.plusDays(6);
0551: * YearMonthDay added = dt.plus(Period.days(6));
0552: * YearMonthDay added = dt.withFieldAdded(DurationFieldType.days(), 6);
0553: * </pre>
0554: *
0555: * @param days the amount of days to add, may be negative
0556: * @return the new date plus the increased days
0557: * @since 1.1
0558: */
0559: public YearMonthDay plusDays(int days) {
0560: return withFieldAdded(DurationFieldType.days(), days);
0561: }
0562:
0563: //-----------------------------------------------------------------------
0564: /**
0565: * Returns a copy of this date with the specified period taken away.
0566: * <p>
0567: * If the amount is zero or null, then <code>this</code> is returned.
0568: * <p>
0569: * This method is typically used to subtract complex period instances.
0570: * Subtracting one field is best achieved using methods
0571: * like {@link #minusYears(int)}.
0572: *
0573: * @param period the period to reduce this instant by
0574: * @return a copy of this instance with the period taken away
0575: * @throws ArithmeticException if the new datetime exceeds the capacity of a long
0576: */
0577: public YearMonthDay minus(ReadablePeriod period) {
0578: return withPeriodAdded(period, -1);
0579: }
0580:
0581: //-----------------------------------------------------------------------
0582: /**
0583: * Returns a copy of this date minus the specified number of years.
0584: * <p>
0585: * This datetime instance is immutable and unaffected by this method call.
0586: * <p>
0587: * The following three lines are identical in effect:
0588: * <pre>
0589: * YearMonthDay subtracted = dt.minusYears(6);
0590: * YearMonthDay subtracted = dt.minus(Period.years(6));
0591: * YearMonthDay subtracted = dt.withFieldAdded(DurationFieldType.years(), -6);
0592: * </pre>
0593: *
0594: * @param years the amount of years to subtract, may be negative
0595: * @return the new datetime minus the increased years
0596: * @since 1.1
0597: */
0598: public YearMonthDay minusYears(int years) {
0599: return withFieldAdded(DurationFieldType.years(), FieldUtils
0600: .safeNegate(years));
0601: }
0602:
0603: /**
0604: * Returns a copy of this date minus the specified number of months.
0605: * <p>
0606: * This datetime instance is immutable and unaffected by this method call.
0607: * <p>
0608: * The following three lines are identical in effect:
0609: * <pre>
0610: * YearMonthDay subtracted = dt.minusMonths(6);
0611: * YearMonthDay subtracted = dt.minus(Period.months(6));
0612: * YearMonthDay subtracted = dt.withFieldAdded(DurationFieldType.months(), -6);
0613: * </pre>
0614: *
0615: * @param months the amount of months to subtract, may be negative
0616: * @return the new datetime minus the increased months
0617: * @since 1.1
0618: */
0619: public YearMonthDay minusMonths(int months) {
0620: return withFieldAdded(DurationFieldType.months(), FieldUtils
0621: .safeNegate(months));
0622: }
0623:
0624: /**
0625: * Returns a copy of this date minus the specified number of days.
0626: * <p>
0627: * This datetime instance is immutable and unaffected by this method call.
0628: * <p>
0629: * The following three lines are identical in effect:
0630: * <pre>
0631: * YearMonthDay subtracted = dt.minusDays(6);
0632: * YearMonthDay subtracted = dt.minus(Period.days(6));
0633: * YearMonthDay subtracted = dt.withFieldAdded(DurationFieldType.days(), -6);
0634: * </pre>
0635: *
0636: * @param days the amount of days to subtract, may be negative
0637: * @return the new datetime minus the increased days
0638: * @since 1.1
0639: */
0640: public YearMonthDay minusDays(int days) {
0641: return withFieldAdded(DurationFieldType.days(), FieldUtils
0642: .safeNegate(days));
0643: }
0644:
0645: //-----------------------------------------------------------------------
0646: /**
0647: * Gets the property object for the specified type, which contains
0648: * many useful methods.
0649: *
0650: * @param type the field type to get the property for
0651: * @return the property object
0652: * @throws IllegalArgumentException if the field is null or unsupported
0653: */
0654: public Property property(DateTimeFieldType type) {
0655: return new Property(this , indexOfSupported(type));
0656: }
0657:
0658: //-----------------------------------------------------------------------
0659: /**
0660: * Converts this object to a LocalDate with the same date and chronology.
0661: *
0662: * @return a LocalDate with the same date and chronology
0663: * @since 1.3
0664: */
0665: public LocalDate toLocalDate() {
0666: return new LocalDate(getYear(), getMonthOfYear(),
0667: getDayOfMonth(), getChronology());
0668: }
0669:
0670: //-----------------------------------------------------------------------
0671: /**
0672: * Converts this YearMonthDay to a full datetime at midnight using the
0673: * default time zone.
0674: *
0675: * @return this date as a datetime at midnight
0676: */
0677: public DateTime toDateTimeAtMidnight() {
0678: return toDateTimeAtMidnight(null);
0679: }
0680:
0681: /**
0682: * Converts this YearMonthDay to a full datetime at midnight using the
0683: * specified time zone.
0684: * <p>
0685: * This method uses the chronology from this instance plus the time zone
0686: * specified.
0687: *
0688: * @param zone the zone to use, null means default
0689: * @return this date as a datetime at midnight
0690: */
0691: public DateTime toDateTimeAtMidnight(DateTimeZone zone) {
0692: Chronology chrono = getChronology().withZone(zone);
0693: return new DateTime(getYear(), getMonthOfYear(),
0694: getDayOfMonth(), 0, 0, 0, 0, chrono);
0695: }
0696:
0697: //-----------------------------------------------------------------------
0698: /**
0699: * Converts this partial to a full datetime using the default time zone
0700: * setting the date fields from this instance and the time fields from
0701: * the current time.
0702: *
0703: * @return this date as a datetime with the time as the current time
0704: */
0705: public DateTime toDateTimeAtCurrentTime() {
0706: return toDateTimeAtCurrentTime(null);
0707: }
0708:
0709: /**
0710: * Converts this partial to a full datetime using the specified time zone
0711: * setting the date fields from this instance and the time fields from
0712: * the current time.
0713: * <p>
0714: * This method uses the chronology from this instance plus the time zone
0715: * specified.
0716: *
0717: * @param zone the zone to use, null means default
0718: * @return this date as a datetime with the time as the current time
0719: */
0720: public DateTime toDateTimeAtCurrentTime(DateTimeZone zone) {
0721: Chronology chrono = getChronology().withZone(zone);
0722: long instantMillis = DateTimeUtils.currentTimeMillis();
0723: long resolved = chrono.set(this , instantMillis);
0724: return new DateTime(resolved, chrono);
0725: }
0726:
0727: //-----------------------------------------------------------------------
0728: /**
0729: * Converts this object to a DateMidnight in the default time zone.
0730: *
0731: * @return the DateMidnight instance in the default zone
0732: */
0733: public DateMidnight toDateMidnight() {
0734: return toDateMidnight(null);
0735: }
0736:
0737: /**
0738: * Converts this object to a DateMidnight.
0739: *
0740: * @param zone the zone to get the DateMidnight in, null means default
0741: * @return the DateMidnight instance
0742: */
0743: public DateMidnight toDateMidnight(DateTimeZone zone) {
0744: Chronology chrono = getChronology().withZone(zone);
0745: return new DateMidnight(getYear(), getMonthOfYear(),
0746: getDayOfMonth(), chrono);
0747: }
0748:
0749: //-----------------------------------------------------------------------
0750: /**
0751: * Converts this object to a DateTime using a TimeOfDay to fill in the
0752: * missing fields and using the default time zone.
0753: * This instance is immutable and unaffected by this method call.
0754: * <p>
0755: * The resulting chronology is determined by the chronology of this
0756: * YearMonthDay plus the time zone.
0757: * The chronology of the time is ignored - only the field values are used.
0758: *
0759: * @param time the time of day to use, null means current time
0760: * @return the DateTime instance
0761: */
0762: public DateTime toDateTime(TimeOfDay time) {
0763: return toDateTime(time, null);
0764: }
0765:
0766: /**
0767: * Converts this object to a DateTime using a TimeOfDay to fill in the
0768: * missing fields.
0769: * This instance is immutable and unaffected by this method call.
0770: * <p>
0771: * The resulting chronology is determined by the chronology of this
0772: * YearMonthDay plus the time zone.
0773: * The chronology of the time is ignored - only the field values are used.
0774: *
0775: * @param time the time of day to use, null means current time
0776: * @param zone the zone to get the DateTime in, null means default
0777: * @return the DateTime instance
0778: */
0779: public DateTime toDateTime(TimeOfDay time, DateTimeZone zone) {
0780: Chronology chrono = getChronology().withZone(zone);
0781: long instant = DateTimeUtils.currentTimeMillis();
0782: instant = chrono.set(this , instant);
0783: if (time != null) {
0784: instant = chrono.set(time, instant);
0785: }
0786: return new DateTime(instant, chrono);
0787: }
0788:
0789: //-----------------------------------------------------------------------
0790: /**
0791: * Converts this object to an Interval representing the whole day
0792: * in the default time zone.
0793: *
0794: * @return a interval over the day
0795: */
0796: public Interval toInterval() {
0797: return toInterval(null);
0798: }
0799:
0800: /**
0801: * Converts this object to an Interval representing the whole day.
0802: *
0803: * @param zone the zone to get the Interval in, null means default
0804: * @return a interval over the day
0805: */
0806: public Interval toInterval(DateTimeZone zone) {
0807: zone = DateTimeUtils.getZone(zone);
0808: return toDateMidnight(zone).toInterval();
0809: }
0810:
0811: //-----------------------------------------------------------------------
0812: /**
0813: * Get the year field value.
0814: *
0815: * @return the year
0816: */
0817: public int getYear() {
0818: return getValue(YEAR);
0819: }
0820:
0821: /**
0822: * Get the month of year field value.
0823: *
0824: * @return the month of year
0825: */
0826: public int getMonthOfYear() {
0827: return getValue(MONTH_OF_YEAR);
0828: }
0829:
0830: /**
0831: * Get the day of month field value.
0832: *
0833: * @return the day of month
0834: */
0835: public int getDayOfMonth() {
0836: return getValue(DAY_OF_MONTH);
0837: }
0838:
0839: //-----------------------------------------------------------------------
0840: /**
0841: * Returns a copy of this date with the year field updated.
0842: * <p>
0843: * YearMonthDay is immutable, so there are no set methods.
0844: * Instead, this method returns a new instance with the value of
0845: * year changed.
0846: *
0847: * @param year the year to set
0848: * @return a copy of this object with the field set
0849: * @throws IllegalArgumentException if the value is invalid
0850: * @since 1.3
0851: */
0852: public YearMonthDay withYear(int year) {
0853: int[] newValues = getValues();
0854: newValues = getChronology().year().set(this , YEAR, newValues,
0855: year);
0856: return new YearMonthDay(this , newValues);
0857: }
0858:
0859: /**
0860: * Returns a copy of this date with the month of year field updated.
0861: * <p>
0862: * YearMonthDay is immutable, so there are no set methods.
0863: * Instead, this method returns a new instance with the value of
0864: * month of year changed.
0865: *
0866: * @param monthOfYear the month of year to set
0867: * @return a copy of this object with the field set
0868: * @throws IllegalArgumentException if the value is invalid
0869: * @since 1.3
0870: */
0871: public YearMonthDay withMonthOfYear(int monthOfYear) {
0872: int[] newValues = getValues();
0873: newValues = getChronology().monthOfYear().set(this ,
0874: MONTH_OF_YEAR, newValues, monthOfYear);
0875: return new YearMonthDay(this , newValues);
0876: }
0877:
0878: /**
0879: * Returns a copy of this date with the day of month field updated.
0880: * <p>
0881: * YearMonthDay is immutable, so there are no set methods.
0882: * Instead, this method returns a new instance with the value of
0883: * day of month changed.
0884: *
0885: * @param dayOfMonth the day of month to set
0886: * @return a copy of this object with the field set
0887: * @throws IllegalArgumentException if the value is invalid
0888: * @since 1.3
0889: */
0890: public YearMonthDay withDayOfMonth(int dayOfMonth) {
0891: int[] newValues = getValues();
0892: newValues = getChronology().dayOfMonth().set(this ,
0893: DAY_OF_MONTH, newValues, dayOfMonth);
0894: return new YearMonthDay(this , newValues);
0895: }
0896:
0897: //-----------------------------------------------------------------------
0898: /**
0899: * Get the year field property which provides access to advanced functionality.
0900: *
0901: * @return the year property
0902: */
0903: public Property year() {
0904: return new Property(this , YEAR);
0905: }
0906:
0907: /**
0908: * Get the month of year field property which provides access to advanced functionality.
0909: *
0910: * @return the month of year property
0911: */
0912: public Property monthOfYear() {
0913: return new Property(this , MONTH_OF_YEAR);
0914: }
0915:
0916: /**
0917: * Get the day of month field property which provides access to advanced functionality.
0918: *
0919: * @return the day of month property
0920: */
0921: public Property dayOfMonth() {
0922: return new Property(this , DAY_OF_MONTH);
0923: }
0924:
0925: //-----------------------------------------------------------------------
0926: /**
0927: * Output the date in the ISO8601 format YYYY-MM-DD.
0928: *
0929: * @return ISO8601 formatted string
0930: */
0931: public String toString() {
0932: return ISODateTimeFormat.yearMonthDay().print(this );
0933: }
0934:
0935: //-----------------------------------------------------------------------
0936: /**
0937: * The property class for <code>YearMonthDay</code>.
0938: * <p>
0939: * This class binds a <code>YearMonthDay</code> to a <code>DateTimeField</code>.
0940: *
0941: * @author Stephen Colebourne
0942: * @since 1.0
0943: * @deprecated Use LocalDate which has a much better internal implementation
0944: */
0945: public static class Property extends AbstractPartialFieldProperty
0946: implements Serializable {
0947:
0948: /** Serialization version */
0949: private static final long serialVersionUID = 5727734012190224363L;
0950:
0951: /** The partial */
0952: private final YearMonthDay iYearMonthDay;
0953: /** The field index */
0954: private final int iFieldIndex;
0955:
0956: /**
0957: * Constructs a property.
0958: *
0959: * @param partial the partial instance
0960: * @param fieldIndex the index in the partial
0961: */
0962: Property(YearMonthDay partial, int fieldIndex) {
0963: super ();
0964: iYearMonthDay = partial;
0965: iFieldIndex = fieldIndex;
0966: }
0967:
0968: /**
0969: * Gets the field that this property uses.
0970: *
0971: * @return the field
0972: */
0973: public DateTimeField getField() {
0974: return iYearMonthDay.getField(iFieldIndex);
0975: }
0976:
0977: /**
0978: * Gets the partial that this property belongs to.
0979: *
0980: * @return the partial
0981: */
0982: protected ReadablePartial getReadablePartial() {
0983: return iYearMonthDay;
0984: }
0985:
0986: /**
0987: * Gets the partial that this property belongs to.
0988: *
0989: * @return the partial
0990: */
0991: public YearMonthDay getYearMonthDay() {
0992: return iYearMonthDay;
0993: }
0994:
0995: /**
0996: * Gets the value of this field.
0997: *
0998: * @return the field value
0999: */
1000: public int get() {
1001: return iYearMonthDay.getValue(iFieldIndex);
1002: }
1003:
1004: //-----------------------------------------------------------------------
1005: /**
1006: * Adds to the value of this field in a copy of this YearMonthDay.
1007: * <p>
1008: * The value will be added to this field. If the value is too large to be
1009: * added solely to this field then it will affect larger fields.
1010: * Smaller fields are unaffected.
1011: * <p>
1012: * If the result would be too large, beyond the maximum year, then an
1013: * IllegalArgumentException is thrown.
1014: * <p>
1015: * The YearMonthDay attached to this property is unchanged by this call.
1016: * Instead, a new instance is returned.
1017: *
1018: * @param valueToAdd the value to add to the field in the copy
1019: * @return a copy of the YearMonthDay with the field value changed
1020: * @throws IllegalArgumentException if the value isn't valid
1021: */
1022: public YearMonthDay addToCopy(int valueToAdd) {
1023: int[] newValues = iYearMonthDay.getValues();
1024: newValues = getField().add(iYearMonthDay, iFieldIndex,
1025: newValues, valueToAdd);
1026: return new YearMonthDay(iYearMonthDay, newValues);
1027: }
1028:
1029: /**
1030: * Adds to the value of this field in a copy of this YearMonthDay wrapping
1031: * within this field if the maximum value is reached.
1032: * <p>
1033: * The value will be added to this field. If the value is too large to be
1034: * added solely to this field then it wraps within this field.
1035: * Other fields are unaffected.
1036: * <p>
1037: * For example,
1038: * <code>2004-12-20</code> addWrapField one month returns <code>2004-01-20</code>.
1039: * <p>
1040: * The YearMonthDay attached to this property is unchanged by this call.
1041: * Instead, a new instance is returned.
1042: *
1043: * @param valueToAdd the value to add to the field in the copy
1044: * @return a copy of the YearMonthDay with the field value changed
1045: * @throws IllegalArgumentException if the value isn't valid
1046: */
1047: public YearMonthDay addWrapFieldToCopy(int valueToAdd) {
1048: int[] newValues = iYearMonthDay.getValues();
1049: newValues = getField().addWrapField(iYearMonthDay,
1050: iFieldIndex, newValues, valueToAdd);
1051: return new YearMonthDay(iYearMonthDay, newValues);
1052: }
1053:
1054: //-----------------------------------------------------------------------
1055: /**
1056: * Sets this field in a copy of the YearMonthDay.
1057: * <p>
1058: * The YearMonthDay attached to this property is unchanged by this call.
1059: * Instead, a new instance is returned.
1060: *
1061: * @param value the value to set the field in the copy to
1062: * @return a copy of the YearMonthDay with the field value changed
1063: * @throws IllegalArgumentException if the value isn't valid
1064: */
1065: public YearMonthDay setCopy(int value) {
1066: int[] newValues = iYearMonthDay.getValues();
1067: newValues = getField().set(iYearMonthDay, iFieldIndex,
1068: newValues, value);
1069: return new YearMonthDay(iYearMonthDay, newValues);
1070: }
1071:
1072: /**
1073: * Sets this field in a copy of the YearMonthDay to a parsed text value.
1074: * <p>
1075: * The YearMonthDay attached to this property is unchanged by this call.
1076: * Instead, a new instance is returned.
1077: *
1078: * @param text the text value to set
1079: * @param locale optional locale to use for selecting a text symbol
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, Locale locale) {
1084: int[] newValues = iYearMonthDay.getValues();
1085: newValues = getField().set(iYearMonthDay, iFieldIndex,
1086: newValues, text, locale);
1087: return new YearMonthDay(iYearMonthDay, newValues);
1088: }
1089:
1090: /**
1091: * Sets this field in a copy of the YearMonthDay to a parsed text value.
1092: * <p>
1093: * The YearMonthDay attached to this property is unchanged by this call.
1094: * Instead, a new instance is returned.
1095: *
1096: * @param text the text value to set
1097: * @return a copy of the YearMonthDay with the field value changed
1098: * @throws IllegalArgumentException if the text value isn't valid
1099: */
1100: public YearMonthDay setCopy(String text) {
1101: return setCopy(text, null);
1102: }
1103:
1104: //-----------------------------------------------------------------------
1105: /**
1106: * Returns a new YearMonthDay with this field set to the maximum value
1107: * for this field.
1108: * <p>
1109: * This operation is useful for obtaining a DateTime on the last day
1110: * of the month, as month lengths vary.
1111: * <pre>
1112: * YearMonthDay lastDayOfMonth = dt.dayOfMonth().withMaximumValue();
1113: * </pre>
1114: * <p>
1115: * The YearMonthDay attached to this property is unchanged by this call.
1116: *
1117: * @return a copy of the YearMonthDay with this field set to its maximum
1118: * @since 1.2
1119: */
1120: public YearMonthDay withMaximumValue() {
1121: return setCopy(getMaximumValue());
1122: }
1123:
1124: /**
1125: * Returns a new YearMonthDay with this field set to the minimum value
1126: * for this field.
1127: * <p>
1128: * The YearMonthDay attached to this property is unchanged by this call.
1129: *
1130: * @return a copy of the YearMonthDay with this field set to its minimum
1131: * @since 1.2
1132: */
1133: public YearMonthDay withMinimumValue() {
1134: return setCopy(getMinimumValue());
1135: }
1136: }
1137:
1138: }
|