
org.joda.time.YearMonthDay Maven / Gradle / Ivy
/*
* Copyright 2001-2011 Stephen Colebourne
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.joda.time;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import org.joda.time.base.BasePartial;
import org.joda.time.chrono.ISOChronology;
import org.joda.time.field.AbstractPartialFieldProperty;
import org.joda.time.field.FieldUtils;
import org.joda.time.format.ISODateTimeFormat;
/**
* YearMonthDay is an immutable partial supporting the year, monthOfYear
* and dayOfMonth fields.
*
* NOTE: This class only supports the three fields listed above. Thus, you
* cannot query the dayOfWeek or centuryOfEra fields for example.
* The new LocalDate
class removes this restriction.
*
* Calculations on YearMonthDay are performed using a {@link Chronology}.
* This chronology is set to be in the UTC time zone for all calculations.
*
* Each individual field can be queried in two ways:
*
* getMonthOfYear()
* monthOfYear().get()
*
* The second technique also provides access to other useful methods on the
* field:
*
* - numeric value -
monthOfYear().get()
* - text value -
monthOfYear().getAsText()
* - short text value -
monthOfYear().getAsShortText()
* - maximum/minimum values -
monthOfYear().getMaximumValue()
* - add/subtract -
monthOfYear().addToCopy()
* - set -
monthOfYear().setCopy()
*
*
* YearMonthDay is thread-safe and immutable, provided that the Chronology is as well.
* All standard Chronology classes supplied are thread-safe and immutable.
*
* @author Stephen Colebourne
* @since 1.0
* @deprecated Use LocalDate which has a much better internal implementation and
* has been available since 1.3
*/
@Deprecated
public final class YearMonthDay
extends BasePartial
implements ReadablePartial, Serializable {
/** Serialization version */
private static final long serialVersionUID = 797544782896179L;
/** The singleton set of field types */
private static final DateTimeFieldType[] FIELD_TYPES = new DateTimeFieldType[] {
DateTimeFieldType.year(),
DateTimeFieldType.monthOfYear(),
DateTimeFieldType.dayOfMonth(),
};
/** The index of the year field in the field array */
public static final int YEAR = 0;
/** The index of the monthOfYear field in the field array */
public static final int MONTH_OF_YEAR = 1;
/** The index of the dayOfMonth field in the field array */
public static final int DAY_OF_MONTH = 2;
//-----------------------------------------------------------------------
/**
* Constructs a YearMonthDay from a java.util.Calendar
* using exactly the same field values avoiding any time zone effects.
*
* Each field is queried from the Calendar and assigned to the YearMonthDay.
* This is useful if you have been using the Calendar as a local date,
* ignoring the zone.
*
* This factory method ignores the type of the calendar and always
* creates a YearMonthDay with ISO chronology. It is expected that you
* will only pass in instances of GregorianCalendar
however
* this is not validated.
*
* @param calendar the Calendar to extract fields from
* @return the created YearMonthDay
* @throws IllegalArgumentException if the calendar is null
* @throws IllegalArgumentException if the date is invalid for the ISO chronology
* @since 1.2
*/
public static YearMonthDay fromCalendarFields(Calendar calendar) {
if (calendar == null) {
throw new IllegalArgumentException("The calendar must not be null");
}
return new YearMonthDay(
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH) + 1,
calendar.get(Calendar.DAY_OF_MONTH)
);
}
/**
* Constructs a YearMonthDay from a java.util.Date
* using exactly the same field values avoiding any time zone effects.
*
* Each field is queried from the Date and assigned to the YearMonthDay.
* This is useful if you have been using the Date as a local date,
* ignoring the zone.
*
* This factory method always creates a YearMonthDay with ISO chronology.
*
* @param date the Date to extract fields from
* @return the created YearMonthDay
* @throws IllegalArgumentException if the calendar is null
* @throws IllegalArgumentException if the date is invalid for the ISO chronology
* @since 1.2
*/
public static YearMonthDay fromDateFields(Date date) {
if (date == null) {
throw new IllegalArgumentException("The date must not be null");
}
return new YearMonthDay(
date.getYear() + 1900,
date.getMonth() + 1,
date.getDate()
);
}
//-----------------------------------------------------------------------
/**
* Constructs a YearMonthDay with the current date, using ISOChronology in
* the default zone to extract the fields.
*
* The constructor uses the default time zone, resulting in the local time
* being initialised. Once the constructor is complete, all further calculations
* are performed without reference to a timezone (by switching to UTC).
*/
public YearMonthDay() {
super();
}
/**
* Constructs a YearMonthDay with the current date, using ISOChronology in
* the specified zone to extract the fields.
*
* The constructor uses the specified time zone to obtain the current date.
* Once the constructor is complete, all further calculations
* are performed without reference to a timezone (by switching to UTC).
*
* @param zone the zone to use, null means default zone
* @since 1.1
*/
public YearMonthDay(DateTimeZone zone) {
super(ISOChronology.getInstance(zone));
}
/**
* Constructs a YearMonthDay with the current date, using the specified chronology
* and zone to extract the fields.
*
* The constructor uses the time zone of the chronology specified.
* Once the constructor is complete, all further calculations are performed
* without reference to a timezone (by switching to UTC).
*
* @param chronology the chronology, null means ISOChronology in the default zone
*/
public YearMonthDay(Chronology chronology) {
super(chronology);
}
/**
* Constructs a YearMonthDay extracting the partial fields from the specified
* milliseconds using the ISOChronology in the default zone.
*
* The constructor uses the default time zone, resulting in the local time
* being initialised. Once the constructor is complete, all further calculations
* are performed without reference to a timezone (by switching to UTC).
*
* @param instant the milliseconds from 1970-01-01T00:00:00Z
*/
public YearMonthDay(long instant) {
super(instant);
}
/**
* Constructs a YearMonthDay extracting the partial fields from the specified
* milliseconds using the chronology provided.
*
* The constructor uses the time zone of the chronology specified.
* Once the constructor is complete, all further calculations are performed
* without reference to a timezone (by switching to UTC).
*
* @param instant the milliseconds from 1970-01-01T00:00:00Z
* @param chronology the chronology, null means ISOChronology in the default zone
*/
public YearMonthDay(long instant, Chronology chronology) {
super(instant, chronology);
}
/**
* Constructs a YearMonthDay from an Object that represents a time.
*
* The recognised object types are defined in
* {@link org.joda.time.convert.ConverterManager ConverterManager} and
* include ReadableInstant, String, Calendar and Date.
* The String formats are described by {@link ISODateTimeFormat#dateOptionalTimeParser()}.
*
* The chronology used will be derived from the object, defaulting to ISO.
*
* NOTE: Prior to v1.3 the string format was described by
* {@link ISODateTimeFormat#dateTimeParser()}. Time only strings are now rejected.
*
* @param instant the datetime object, null means now
* @throws IllegalArgumentException if the instant is invalid
*/
public YearMonthDay(Object instant) {
super(instant, null, ISODateTimeFormat.dateOptionalTimeParser());
}
/**
* Constructs a YearMonthDay from an Object that represents a time, using the
* specified chronology.
*
* The recognised object types are defined in
* {@link org.joda.time.convert.ConverterManager ConverterManager} and
* include ReadableInstant, String, Calendar and Date.
* The String formats are described by {@link ISODateTimeFormat#dateOptionalTimeParser()}.
*
* The constructor uses the time zone of the chronology specified.
* Once the constructor is complete, all further calculations are performed
* without reference to a timezone (by switching to UTC).
* The specified chronology overrides that of the object.
*
* NOTE: Prior to v1.3 the string format was described by
* {@link ISODateTimeFormat#dateTimeParser()}. Time only strings are now rejected.
*
* @param instant the datetime object, null means now
* @param chronology the chronology, null means ISO default
* @throws IllegalArgumentException if the instant is invalid
*/
public YearMonthDay(Object instant, Chronology chronology) {
super(instant, DateTimeUtils.getChronology(chronology), ISODateTimeFormat.dateOptionalTimeParser());
}
/**
* Constructs a YearMonthDay with specified time field values
* using ISOChronology
in the default zone.
*
* The constructor uses the no time zone initialising the fields as provided.
* Once the constructor is complete, all further calculations
* are performed without reference to a timezone (by switching to UTC).
*
* @param year the year
* @param monthOfYear the month of the year
* @param dayOfMonth the day of the month
*/
public YearMonthDay(int year, int monthOfYear, int dayOfMonth) {
this(year, monthOfYear, dayOfMonth, null);
}
/**
* Constructs a YearMonthDay with specified time field values.
*
* The constructor uses the time zone of the chronology specified.
* Once the constructor is complete, all further calculations are performed
* without reference to a timezone (by switching to UTC).
*
* @param year the year
* @param monthOfYear the month of the year
* @param dayOfMonth the day of the month
* @param chronology the chronology, null means ISOChronology in the default zone
*/
public YearMonthDay(int year, int monthOfYear, int dayOfMonth, Chronology chronology) {
super(new int[] {year, monthOfYear, dayOfMonth}, chronology);
}
/**
* Constructs a YearMonthDay with chronology from this instance and new values.
*
* @param partial the partial to base this new instance on
* @param values the new set of values
*/
YearMonthDay(YearMonthDay partial, int[] values) {
super(partial, values);
}
/**
* Constructs a YearMonthDay with values from this instance and a new chronology.
*
* @param partial the partial to base this new instance on
* @param chrono the new chronology
*/
YearMonthDay(YearMonthDay partial, Chronology chrono) {
super(partial, chrono);
}
//-----------------------------------------------------------------------
/**
* Gets the number of fields in this partial.
*
* @return the field count
*/
public int size() {
return 3;
}
/**
* Gets the field for a specific index in the chronology specified.
*
* This method must not use any instance variables.
*
* @param index the index to retrieve
* @param chrono the chronology to use
* @return the field
*/
protected DateTimeField getField(int index, Chronology chrono) {
switch (index) {
case YEAR:
return chrono.year();
case MONTH_OF_YEAR:
return chrono.monthOfYear();
case DAY_OF_MONTH:
return chrono.dayOfMonth();
default:
throw new IndexOutOfBoundsException("Invalid index: " + index);
}
}
/**
* Gets the field type at the specified index.
*
* @param index the index to retrieve
* @return the field at the specified index
* @throws IndexOutOfBoundsException if the index is invalid
*/
public DateTimeFieldType getFieldType(int index) {
return FIELD_TYPES[index];
}
/**
* Gets an array of the field type of each of the fields that this partial supports.
*
* The fields are returned largest to smallest, Year, Month, Day
*
* @return the array of field types (cloned), largest to smallest
*/
public DateTimeFieldType[] getFieldTypes() {
return (DateTimeFieldType[]) FIELD_TYPES.clone();
}
//-----------------------------------------------------------------------
/**
* Returns a copy of this date with the specified chronology.
* This instance is immutable and unaffected by this method call.
*
* This method retains the values of the fields, thus the result will
* typically refer to a different instant.
*
* The time zone of the specified chronology is ignored, as YearMonthDay
* operates without a time zone.
*
* @param newChronology the new chronology, null means ISO
* @return a copy of this datetime with a different chronology
* @throws IllegalArgumentException if the values are invalid for the new chronology
*/
public YearMonthDay withChronologyRetainFields(Chronology newChronology) {
newChronology = DateTimeUtils.getChronology(newChronology);
newChronology = newChronology.withUTC();
if (newChronology == getChronology()) {
return this;
} else {
YearMonthDay newYearMonthDay = new YearMonthDay(this, newChronology);
newChronology.validate(newYearMonthDay, getValues());
return newYearMonthDay;
}
}
/**
* Returns a copy of this date with the specified field set to a new value.
*
* For example, if the field type is dayOfMonth
then the day
* would be changed in the returned instance.
*
* These three lines are equivalent:
*
* YearMonthDay updated = ymd.withField(DateTimeFieldType.dayOfMonth(), 6);
* YearMonthDay updated = ymd.dayOfMonth().setCopy(6);
* YearMonthDay updated = ymd.property(DateTimeFieldType.dayOfMonth()).setCopy(6);
*
*
* @param fieldType the field type to set, not null
* @param value the value to set
* @return a copy of this instance with the field set
* @throws IllegalArgumentException if the value is null or invalid
*/
public YearMonthDay withField(DateTimeFieldType fieldType, int value) {
int index = indexOfSupported(fieldType);
if (value == getValue(index)) {
return this;
}
int[] newValues = getValues();
newValues = getField(index).set(this, index, newValues, value);
return new YearMonthDay(this, newValues);
}
/**
* Returns a copy of this date with the value of the specified field increased.
*
* If the addition is zero, then this
is returned.
*
* These three lines are equivalent:
*
* YearMonthDay added = ymd.withFieldAdded(DurationFieldType.days(), 6);
* YearMonthDay added = ymd.plusDays(6);
* YearMonthDay added = ymd.dayOfMonth().addToCopy(6);
*
*
* @param fieldType the field type to add to, not null
* @param amount the amount to add
* @return a copy of this instance with the field updated
* @throws IllegalArgumentException if the value is null or invalid
* @throws ArithmeticException if the new datetime exceeds the capacity
*/
public YearMonthDay withFieldAdded(DurationFieldType fieldType, int amount) {
int index = indexOfSupported(fieldType);
if (amount == 0) {
return this;
}
int[] newValues = getValues();
newValues = getField(index).add(this, index, newValues, amount);
return new YearMonthDay(this, newValues);
}
/**
* Returns a copy of this date with the specified period added.
*
* If the addition is zero, then this
is returned.
* Fields in the period that aren't present in the partial are ignored.
*
* This method is typically used to add multiple copies of complex
* period instances. Adding one field is best achieved using methods
* like {@link #withFieldAdded(DurationFieldType, int)}
* or {@link #plusYears(int)}.
*
* @param period the period to add to this one, null means zero
* @param scalar the amount of times to add, such as -1 to subtract once
* @return a copy of this instance with the period added
* @throws ArithmeticException if the new datetime exceeds the capacity
*/
public YearMonthDay withPeriodAdded(ReadablePeriod period, int scalar) {
if (period == null || scalar == 0) {
return this;
}
int[] newValues = getValues();
for (int i = 0; i < period.size(); i++) {
DurationFieldType fieldType = period.getFieldType(i);
int index = indexOf(fieldType);
if (index >= 0) {
newValues = getField(index).add(this, index, newValues,
FieldUtils.safeMultiply(period.getValue(i), scalar));
}
}
return new YearMonthDay(this, newValues);
}
//-----------------------------------------------------------------------
/**
* Returns a copy of this date with the specified period added.
*
* If the amount is zero or null, then this
is returned.
*
* This method is typically used to add complex period instances.
* Adding one field is best achieved using methods
* like {@link #plusYears(int)}.
*
* @param period the duration to add to this one, null means zero
* @return a copy of this instance with the period added
* @throws ArithmeticException if the new datetime exceeds the capacity of a long
*/
public YearMonthDay plus(ReadablePeriod period) {
return withPeriodAdded(period, 1);
}
//-----------------------------------------------------------------------
/**
* Returns a copy of this date plus the specified number of years.
*
* This date instance is immutable and unaffected by this method call.
*