/* * Joda Software License, Version 1.0 * * * Copyright (c) 2001-2004 Stephen Colebourne. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Joda project (http://www.joda.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The name "Joda" must not be used to endorse or promote products * derived from this software without prior written permission. For * written permission, please contact licence@joda.org. * * 5. Products derived from this software may not be called "Joda", * nor may "Joda" appear in their name, without prior written * permission of the Joda project. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE JODA AUTHORS OR THE PROJECT * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Joda project and was originally * created by Stephen Colebourne . For more * information on the Joda project, please see . */ package org.joda.time; import java.io.Serializable; import java.util.Locale; import org.joda.time.base.BaseDateTime; import org.joda.time.chrono.ISOChronology; import org.joda.time.field.AbstractReadableInstantFieldProperty; /** * DateTime is the standard implementation of an unmodifiable datetime class. * It holds the datetime as milliseconds from the Java epoch of 1970-01-01T00:00:00Z. *

* This class uses a Chronology internally. The Chronology determines how the * millisecond instant value is converted into the date time fields. * The default Chronology is ISOChronology which is the agreed * international standard and compatable with the modern Gregorian calendar. * *

Each individual field can be queried in two ways: *

* The second technique also provides access to other useful methods on the * field: * * *

* DateTime 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 * @author Kandarp Shah * @author Brian S O'Neill * @since 1.0 * @see MutableDateTime */ public final class DateTime extends BaseDateTime implements ReadableDateTime, Serializable { /** Serialization lock */ private static final long serialVersionUID = -5171125899451703815L; //----------------------------------------------------------------------- /** * Constructs an instance set to the current system millisecond time * using ISOChronology in the default time zone. */ public DateTime() { super(); } /** * Constructs an instance set to the current system millisecond time * using ISOChronology in the specified time zone. *

* If the specified time zone is null, the default zone is used. * * @param zone the time zone, null means default zone */ public DateTime(DateTimeZone zone) { super(zone); } /** * Constructs an instance set to the current system millisecond time * using the specified chronology. *

* If the chronology is null, ISOChronology * in the default time zone is used. * * @param chronology the chronology, null means ISOChronology in default zone */ public DateTime(Chronology chronology) { super(chronology); } //----------------------------------------------------------------------- /** * Constructs an instance set to the milliseconds from 1970-01-01T00:00:00Z * using ISOChronology in the default time zone. * * @param instant the milliseconds from 1970-01-01T00:00:00Z */ public DateTime(long instant) { super(instant); } /** * Constructs an instance set to the milliseconds from 1970-01-01T00:00:00Z * using ISOChronology in the specified time zone. *

* If the specified time zone is null, the default zone is used. * * @param instant the milliseconds from 1970-01-01T00:00:00Z * @param zone the time zone, null means default zone */ public DateTime(long instant, DateTimeZone zone) { super(instant, zone); } /** * Constructs an instance set to the milliseconds from 1970-01-01T00:00:00Z * using the specified chronology. *

* If the chronology is null, ISOChronology * in the default time zone is used. * * @param instant the milliseconds from 1970-01-01T00:00:00Z * @param chronology the chronology, null means ISOChronology in default zone */ public DateTime(long instant, Chronology chronology) { super(instant, chronology); } //----------------------------------------------------------------------- /** * Constructs an instance from an Object that represents a datetime. *

* If the object implies a chronology (such as GregorianCalendar does), * then that chronology will be used. Otherwise, ISO default is used. * Thus if a GregorianCalendar is passed in, the chronology used will * be GJ, but if a Date is passed in the chronology will be ISO. *

* The recognised object types are defined in * {@link org.joda.time.convert.ConverterManager ConverterManager} and * include ReadableInstant, String, Calendar and Date. * * @param instant the datetime object, null means now * @throws IllegalArgumentException if the instant is invalid */ public DateTime(Object instant) { super(instant, (Chronology) null); } /** * Constructs an instance from an Object that represents a datetime, * forcing the time zone to that specified. *

* If the object implies a chronology (such as GregorianCalendar does), * then that chronology will be used, but with the time zone adjusted. * Otherwise, ISO is used in the specified time zone. * If the specified time zone is null, the default zone is used. * Thus if a GregorianCalendar is passed in, the chronology used will * be GJ, but if a Date is passed in the chronology will be ISO. *

* The recognised object types are defined in * {@link org.joda.time.convert.ConverterManager ConverterManager} and * include ReadableInstant, String, Calendar and Date. * * @param instant the datetime object, null means now * @param zone the time zone, null means default time zone * @throws IllegalArgumentException if the instant is invalid */ public DateTime(Object instant, DateTimeZone zone) { super(instant, zone); } /** * Constructs an instance from an Object that represents a datetime, * using the specified chronology. *

* If the chronology is null, ISO in the default time zone is used. * Any chronology implied by the object (such as GregorianCalendar does) * is ignored. *

* The recognised object types are defined in * {@link org.joda.time.convert.ConverterManager ConverterManager} and * include ReadableInstant, String, Calendar and Date. * * @param instant the datetime object, null means now * @param chronology the chronology, null means ISO in default zone * @throws IllegalArgumentException if the instant is invalid */ public DateTime(Object instant, Chronology chronology) { super(instant, DateTimeUtils.getChronology(chronology)); } //----------------------------------------------------------------------- /** * Constructs an instance from datetime field values * using ISOChronology in the default time zone. * * @param year the year * @param monthOfYear the month of the year * @param dayOfMonth the day of the month * @param hourOfDay the hour of the day * @param minuteOfHour the minute of the hour * @param secondOfMinute the second of the minute * @param millisOfSecond the millisecond of the second */ public DateTime( int year, int monthOfYear, int dayOfMonth, int hourOfDay, int minuteOfHour, int secondOfMinute, int millisOfSecond) { super(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond); } /** * Constructs an instance from datetime field values * using ISOChronology in the specified time zone. *

* If the specified time zone is null, the default zone is used. * * @param year the year * @param monthOfYear the month of the year * @param dayOfMonth the day of the month * @param hourOfDay the hour of the day * @param minuteOfHour the minute of the hour * @param secondOfMinute the second of the minute * @param millisOfSecond the millisecond of the second * @param zone the time zone, null means default time zone */ public DateTime( int year, int monthOfYear, int dayOfMonth, int hourOfDay, int minuteOfHour, int secondOfMinute, int millisOfSecond, DateTimeZone zone) { super(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond, zone); } /** * Constructs an instance from datetime field values * using the specified chronology. *

* If the chronology is null, ISOChronology * in the default time zone is used. * * @param year the year * @param monthOfYear the month of the year * @param dayOfMonth the day of the month * @param hourOfDay the hour of the day * @param minuteOfHour the minute of the hour * @param secondOfMinute the second of the minute * @param millisOfSecond the millisecond of the second * @param chronology the chronology, null means ISOChronology in default zone */ public DateTime( int year, int monthOfYear, int dayOfMonth, int hourOfDay, int minuteOfHour, int secondOfMinute, int millisOfSecond, Chronology chronology) { super(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond, chronology); } //----------------------------------------------------------------------- /** * Get this object as a DateTime by returning this. * * @return this */ public DateTime toDateTime() { return this; } /** * Get this object as a DateTime using ISOChronology in the default zone, * returning this if possible. * * @return a DateTime using the same millis */ public DateTime toDateTimeISO() { if (getChronology() == ISOChronology.getInstance()) { return this; } return super.toDateTimeISO(); } /** * Get this object as a DateTime, returning this if possible. * * @param zone time zone to apply, or default if null * @return a DateTime using the same millis */ public DateTime toDateTime(DateTimeZone zone) { zone = DateTimeUtils.getZone(zone); if (getZone() == zone) { return this; } return super.toDateTime(zone); } /** * Get this object as a DateTime, returning this if possible. * * @param chronology chronology to apply, or ISOChronology if null * @return a DateTime using the same millis */ public DateTime toDateTime(Chronology chronology) { chronology = DateTimeUtils.getChronology(chronology); if (getChronology() == chronology) { return this; } return super.toDateTime(chronology); } //----------------------------------------------------------------------- /** * Gets a copy of this datetime with different millis. *

* The returned object will be a new instance of the same implementation type. * Only the millis will change, the chronology and time zone are kept. * The returned object will be either be a new instance or this. * * @param newMillis the new millis, from 1970-01-01T00:00:00Z * @return a copy of this datetime with different millis */ public DateTime withMillis(long newMillis) { return (newMillis == getMillis() ? this : new DateTime(newMillis, getChronology())); } /** * Gets a copy of this datetime with a different chronology. *

* The returned object will be a new instance of the same implementation type. * Only the chronology will change, the millis are kept. * The returned object will be either be a new instance or this. * * @param newChronology the new chronology, null means ISO default * @return a copy of this datetime with a different chronology */ public DateTime withChronology(Chronology newChronology) { newChronology = DateTimeUtils.getChronology(newChronology); return (newChronology == getChronology() ? this : new DateTime(getMillis(), newChronology)); } //----------------------------------------------------------------------- /** * Gets a copy of this datetime with a different time zone, preserving the * millisecond instant. *

* This method is useful for finding the local time in another timezone. * For example, if this instant holds 12:30 in Europe/London, the result * from this method with Europe/Paris would be 13:30. *

* The returned object will be a new instance of the same implementation type. * This method changes alters the time zone, and does not change the * millisecond instant, with the effect that the field values usually change. * The returned object will be either be a new instance or this. * * @param newZone the new time zone * @return a copy of this datetime with a different time zone * @see #withZoneRetainFields */ public DateTime withZone(DateTimeZone newZone) { return withChronology(getChronology().withZone(newZone)); } /** * Gets a copy of this datetime with a different time zone, preserving the * field values. *

* This method is useful for finding the millisecond time in another timezone. * For example, if this instant holds 12:30 in Europe/London (ie. 12:30Z), * the result from this method with Europe/Paris would be 12:30 (ie. 11:30Z). *

* The returned object will be a new instance of the same implementation type. * This method alters the time zone and the millisecond instant to keep * the field values the same. * The returned object will be either be a new instance or this. * * @param newZone the new time zone, null means default * @return a copy of this datetime with a different time zone * @see #withZone */ public DateTime withZoneRetainFields(DateTimeZone newZone) { newZone = DateTimeUtils.getZone(newZone); DateTimeZone originalZone = DateTimeUtils.getZone(getZone()); if (newZone == originalZone) { return this; } long millis = originalZone.getMillisKeepLocal(newZone, getMillis()); return new DateTime(millis, getChronology().withZone(newZone)); } //----------------------------------------------------------------------- /** * Gets a copy of this datetime with the specified date, retaining the time fields. *

* If the date is already the date passed in, then this is returned. *

* To set a single field use the properties, for example: *

     * DateTime set = monthOfYear().setCopy(6);
     * 
* * @param year the new year value * @param monthOfYear the new monthOfYear value * @param dayOfMonth the new dayOfMonth value * @return a copy of this datetime with a different date * @throws IllegalArgumentException if any value if invalid */ public DateTime withDate(int year, int monthOfYear, int dayOfMonth) { Chronology chrono = getChronology(); long instant = getMillis(); instant = chrono.year().set(instant, year); instant = chrono.monthOfYear().set(instant, monthOfYear); instant = chrono.dayOfMonth().set(instant, dayOfMonth); return withMillis(instant); } /** * Gets a copy of this datetime with the specified time, retaining the date fields. *

* If the time is already the time passed in, then this is returned. *

* To set a single field use the properties, for example: *

     * DateTime set = dt.hourOfDay().setCopy(6);
     * 
* * @param hourOfDay the hour of the day * @param minuteOfHour the minute of the hour * @param secondOfMinute the second of the minute * @param millisOfSecond the millisecond of the second * @return a copy of this datetime with a different time * @throws IllegalArgumentException if any value if invalid */ public DateTime withTime(int hourOfDay, int minuteOfHour, int secondOfMinute, int millisOfSecond) { Chronology chrono = getChronology(); long instant = getMillis(); instant = chrono.hourOfDay().set(instant, hourOfDay); instant = chrono.minuteOfHour().set(instant, minuteOfHour); instant = chrono.secondOfMinute().set(instant, secondOfMinute); instant = chrono.millisOfSecond().set(instant, millisOfSecond); return withMillis(instant); } //----------------------------------------------------------------------- /** * Gets a copy of this datetime with the partial set of fields replacing those * from this instance. *

* For example, if the partial is a TimeOfDay then the time fields * would be changed in the returned instance. * If the partial is null, then this is returned. * * @param partial the partial set of fields to apply to this datetime, null ignored * @return a copy of this datetime with a different set of fields * @throws IllegalArgumentException if any value is invalid */ public DateTime withFields(ReadablePartial partial) { if (partial == null) { return this; } return withMillis(getChronology().set(partial, getMillis())); } /** * Gets a copy of this datetime with the specified field set to a new value. *

* For example, if the field type is hourOfDay then the hour of day * field would be changed in the returned instance. * If the field type is null, then this is returned. *

* These three lines are equivalent: *

     * DateTime updated = dt.withField(DateTimeFieldType.dayOfMonth(), 6);
     * DateTime updated = dt.dayOfMonth().setCopy(6);
     * DateTime updated = dt.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 datetime with the field set * @throws IllegalArgumentException if the value is null or invalid */ public DateTime withField(DateTimeFieldType fieldType, int value) { if (fieldType == null) { throw new IllegalArgumentException("Field must not be null"); } long instant = fieldType.getField(getChronology()).set(getMillis(), value); return withMillis(instant); } /** * Gets a copy of this datetime with the value of the specified field increased. *

* If the addition is zero or the field is null, then this is returned. *

* These three lines are equivalent: *

     * DateTime added = dt.withField(DateTimeFieldType.dayOfMonth(), 6);
     * DateTime added = dt.dayOfMonth().addToCopy(6);
     * DateTime added = dt.property(DateTimeFieldType.dayOfMonth()).addToCopy(6);
     * 
* * @param fieldType the field type to add to, not null * @param amount the amount to add * @return a copy of this datetime with the field updated * @throws IllegalArgumentException if the value is null or invalid * @throws ArithmeticException if the new datetime exceeds the capacity of a long */ public DateTime withFieldAdded(DurationFieldType fieldType, int amount) { if (fieldType == null) { throw new IllegalArgumentException("Field must not be null"); } if (amount == 0) { return this; } long instant = fieldType.getField(getChronology()).add(getMillis(), amount); return withMillis(instant); } //----------------------------------------------------------------------- /** * Gets a copy of this datetime with the specified duration added. *

* If the addition is zero, then this is returned. * * @param durationToAdd the duration to add to this one * @param scalar the amount of times to add, such as -1 to subtract once * @return a copy of this datetime with the duration added * @throws ArithmeticException if the new datetime exceeds the capacity of a long */ public DateTime withDurationAdded(long durationToAdd, int scalar) { if (durationToAdd == 0 || scalar == 0) { return this; } long instant = getChronology().add(getMillis(), durationToAdd, scalar); return withMillis(instant); } /** * Gets a copy of this datetime with the specified duration added. *

* If the addition is zero, then this is returned. * * @param durationToAdd the duration 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 datetime with the duration added * @throws ArithmeticException if the new datetime exceeds the capacity of a long */ public DateTime withDurationAdded(ReadableDuration durationToAdd, int scalar) { if (durationToAdd == null || scalar == 0) { return this; } return withDurationAdded(durationToAdd.getMillis(), scalar); } /** * Gets a copy of this datetime with the specified period added. *

* If the addition is zero, then this is returned. *

* To add or subtract on a single field use the properties, for example: *

     * DateTime added = dt.hourOfDay().addToCopy(6);
     * 
* * @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 datetime with the period added * @throws ArithmeticException if the new datetime exceeds the capacity of a long */ public DateTime withPeriodAdded(ReadablePeriod period, int scalar) { if (period == null || scalar == 0) { return this; } long instant = getChronology().add(period, getMillis(), scalar); return withMillis(instant); } //----------------------------------------------------------------------- /** * Gets a copy of this datetime with the specified duration added. *

* If the amount is zero or null, then this is returned. * * @param duration the duration to add to this one * @return a copy of this datetime with the duration added * @throws ArithmeticException if the new datetime exceeds the capacity of a long */ public DateTime plus(long duration) { return withDurationAdded(duration, 1); } /** * Gets a copy of this datetime with the specified duration added. *

* If the amount is zero or null, then this is returned. * * @param duration the duration to add to this one, null means zero * @return a copy of this datetime with the duration added * @throws ArithmeticException if the new datetime exceeds the capacity of a long */ public DateTime plus(ReadableDuration duration) { return withDurationAdded(duration, 1); } /** * Gets a copy of this datetime with the specified period added. *

* If the amount is zero or null, then this is returned. *

* The following two lines are identical in effect: *

     * DateTime added = dt.hourOfDay().addToCopy(6);
     * DateTime added = dt.plus(Period.hours(6));
     * 
* * @param period the duration to add to this one, null means zero * @return a copy of this datetime with the period added * @throws ArithmeticException if the new datetime exceeds the capacity of a long */ public DateTime plus(ReadablePeriod period) { return withPeriodAdded(period, 1); } //----------------------------------------------------------------------- /** * Gets a copy of this datetime with the specified duration take away. *

* If the amount is zero or null, then this is returned. * * @param duration the duration to reduce this instant by * @return a copy of this datetime with the duration taken away * @throws ArithmeticException if the new datetime exceeds the capacity of a long */ public DateTime minus(long duration) { return withDurationAdded(duration, -1); } /** * Gets a copy of this datetime with the specified duration take away. *

* If the amount is zero or null, then this is returned. * * @param duration the duration to reduce this instant by * @return a copy of this datetime with the duration taken away * @throws ArithmeticException if the new datetime exceeds the capacity of a long */ public DateTime minus(ReadableDuration duration) { return withDurationAdded(duration, -1); } /** * Gets a copy of this datetime with the specified period take away. *

* If the amount is zero or null, then this is returned. *

* The following two lines are identical in effect: *

     * DateTime added = dt.hourOfDay().addToCopy(-6);
     * DateTime added = dt.minus(Period.hours(6));
     * 
* * @param period the period to reduce this instant by * @return a copy of this datetime with the period taken away * @throws ArithmeticException if the new datetime exceeds the capacity of a long */ public DateTime minus(ReadablePeriod period) { return withPeriodAdded(period, -1); } //----------------------------------------------------------------------- /** * Gets the property object for the specified type, which contains many useful methods. * * @param type the field type to get the chronology for * @return the property object * @throws IllegalArgumentException if the field is null or unsupported */ public Property property(DateTimeFieldType type) { DateTimeField field = type.getField(getChronology()); if (field.isSupported() == false) { throw new IllegalArgumentException("Field '" + type + "' is not supported"); } return new Property(this, field); } //----------------------------------------------------------------------- /** * Converts this object to a DateMidnight using the same millis and chronology. * * @return a DateMidnight using the same millis and chronology */ public DateMidnight toDateMidnight() { return new DateMidnight(getMillis(), getChronology()); } /** * Converts this object to a YearMonthDay using the same millis and chronology. * * @return a YearMonthDay using the same millis and chronology */ public YearMonthDay toYearMonthDay() { return new YearMonthDay(getMillis(), getChronology()); } /** * Converts this object to a TimeOfDay using the same millis and chronology. * * @return a TimeOfDay using the same millis and chronology */ public TimeOfDay toTimeOfDay() { return new TimeOfDay(getMillis(), getChronology()); } // Date properties //----------------------------------------------------------------------- /** * Get the era property. * * @return the era property */ public Property era() { return new Property(this, getChronology().era()); } /** * Get the century of era property. * * @return the year of era property */ public Property centuryOfEra() { return new Property(this, getChronology().centuryOfEra()); } /** * Get the year of century property. * * @return the year of era property */ public Property yearOfCentury() { return new Property(this, getChronology().yearOfCentury()); } /** * Get the year of era property. * * @return the year of era property */ public Property yearOfEra() { return new Property(this, getChronology().yearOfEra()); } /** * Get the year property. * * @return the year property */ public Property year() { return new Property(this, getChronology().year()); } /** * Get the year of a week based year property. * * @return the year of a week based year property */ public Property weekyear() { return new Property(this, getChronology().weekyear()); } /** * Get the month of year property. * * @return the month of year property */ public Property monthOfYear() { return new Property(this, getChronology().monthOfYear()); } /** * Get the week of a week based year property. * * @return the week of a week based year property */ public Property weekOfWeekyear() { return new Property(this, getChronology().weekOfWeekyear()); } /** * Get the day of year property. * * @return the day of year property */ public Property dayOfYear() { return new Property(this, getChronology().dayOfYear()); } /** * Get the day of month property. * * @return the day of month property */ public Property dayOfMonth() { return new Property(this, getChronology().dayOfMonth()); } /** * Get the day of week property. * * @return the day of week property */ public Property dayOfWeek() { return new Property(this, getChronology().dayOfWeek()); } // Time properties //----------------------------------------------------------------------- /** * Get the hour of day field property * * @return the hour of day property */ public Property hourOfDay() { return new Property(this, getChronology().hourOfDay()); } /** * Get the minute of day property * * @return the minute of day property */ public Property minuteOfDay() { return new Property(this, getChronology().minuteOfDay()); } /** * Get the minute of hour field property * * @return the minute of hour property */ public Property minuteOfHour() { return new Property(this, getChronology().minuteOfHour()); } /** * Get the second of day property * * @return the second of day property */ public Property secondOfDay() { return new Property(this, getChronology().secondOfDay()); } /** * Get the second of minute field property * * @return the second of minute property */ public Property secondOfMinute() { return new Property(this, getChronology().secondOfMinute()); } /** * Get the millis of day property * * @return the millis of day property */ public Property millisOfDay() { return new Property(this, getChronology().millisOfDay()); } /** * Get the millis of second property * * @return the millis of second property */ public Property millisOfSecond() { return new Property(this, getChronology().millisOfSecond()); } //----------------------------------------------------------------------- /** * DateTime.Property binds a DateTime to a DateTimeField allowing powerful * datetime functionality to be easily accessed. *

* The simplest use of this class is as an alternative get method, here used to * get the year '1972' (as an int) and the month 'December' (as a String). *

     * DateTime dt = new DateTime(1972, 12, 3, 0, 0, 0, 0);
     * int year = dt.year().get();
     * String monthStr = dt.month().getAsText();
     * 
*

* Methods are also provided that allow date modification. These return new instances * of DateTime - they do not modify the original. The example below yields two * independent immutable date objects 20 years apart. *

     * DateTime dt = new DateTime(1972, 12, 3, 0, 0, 0, 0);
     * DateTime dt20 = dt.year().addToCopy(20);
     * 
* Serious modification of dates (ie. more than just changing one or two fields) * should use the {@link org.joda.time.MutableDateTime MutableDateTime} class. *

* DateTime.Propery itself is thread-safe and immutable, as well as the * DateTime being operated on. * * @author Stephen Colebourne * @author Brian S O'Neill * @since 1.0 */ public static final class Property extends AbstractReadableInstantFieldProperty { /** Serialization version */ private static final long serialVersionUID = -6983323811635733510L; /** The instant this property is working against */ private final DateTime iInstant; /** The field this property is working against */ private final DateTimeField iField; /** * Constructor. * * @param instant the instant to set * @param field the field to use */ Property(DateTime instant, DateTimeField field) { super(); iInstant = instant; iField = field; } //----------------------------------------------------------------------- /** * Gets the field being used. * * @return the field */ public DateTimeField getField() { return iField; } /** * Gets the instant being used. * * @return the instant */ public ReadableInstant getReadableInstant() { return iInstant; } /** * Gets the datetime being used. * * @return the datetime */ public DateTime getDateTime() { return iInstant; } //----------------------------------------------------------------------- /** * Adds to this field in a copy of this DateTime. *

* The DateTime attached to this property is unchanged by this call. * This operation is faster than converting a DateTime to a MutableDateTime * and back again when setting one field. When setting multiple fields, * it is generally quicker to make the conversion to MutableDateTime. * * @param value the value to add to the field in the copy * @return a copy of the DateTime with the field value changed * @throws IllegalArgumentException if the value isn't valid */ public DateTime addToCopy(int value) { return iInstant.withMillis(iField.add(iInstant.getMillis(), value)); } /** * Adds to this field in a copy of this DateTime. *

* The DateTime attached to this property is unchanged by this call. * This operation is faster than converting a DateTime to a MutableDateTime * and back again when setting one field. When setting multiple fields, * it is generally quicker to make the conversion to MutableDateTime. * * @param value the value to add to the field in the copy * @return a copy of the DateTime with the field value changed * @throws IllegalArgumentException if the value isn't valid */ public DateTime addToCopy(long value) { return iInstant.withMillis(iField.add(iInstant.getMillis(), value)); } /** * Adds to this field, possibly wrapped, in a copy of this DateTime. * A wrapped operation only changes this field. * Thus 31st January addWrapField one day goes to the 1st January. *

* The DateTime attached to this property is unchanged by this call. * This operation is faster than converting a DateTime to a MutableDateTime * and back again when setting one field. When setting multiple fields, * it is generally quicker to make the conversion to MutableDateTime. * * @param value the value to add to the field in the copy * @return a copy of the DateTime with the field value changed * @throws IllegalArgumentException if the value isn't valid */ public DateTime addWrapFieldToCopy(int value) { return iInstant.withMillis(iField.addWrapField(iInstant.getMillis(), value)); } //----------------------------------------------------------------------- /** * Sets this field in a copy of the DateTime. *

* The DateTime attached to this property is unchanged by this call. * This operation is faster than converting a DateTime to a MutableDateTime * and back again when setting one field. When setting multiple fields, * it is generally quicker to make the conversion to MutableDateTime. * * @param value the value to set the field in the copy to * @return a copy of the DateTime with the field value changed * @throws IllegalArgumentException if the value isn't valid */ public DateTime setCopy(int value) { return iInstant.withMillis(iField.set(iInstant.getMillis(), value)); } /** * Sets this field in a copy of the DateTime to a parsed text value. *

* The DateTime attached to this property is unchanged by this call. * This operation is faster than converting a DateTime to a MutableDateTime * and back again when setting one field. When setting multiple fields, * it is generally quicker to make the conversion to MutableDateTime. * * @param text the text value to set * @param locale optional locale to use for selecting a text symbol * @return a copy of the DateTime with the field value changed * @throws IllegalArgumentException if the text value isn't valid */ public DateTime setCopy(String text, Locale locale) { return iInstant.withMillis(iField.set(iInstant.getMillis(), text, locale)); } /** * Sets this field in a copy of the DateTime to a parsed text value. *

* The DateTime attached to this property is unchanged by this call. * This operation is faster than converting a DateTime to a MutableDateTime * and back again when setting one field. When setting multiple fields, * it is generally quicker to make the conversion to MutableDateTime. * * @param text the text value to set * @return a copy of the DateTime with the field value changed * @throws IllegalArgumentException if the text value isn't valid */ public DateTime setCopy(String text) { return setCopy(text, null); } //----------------------------------------------------------------------- /** * Rounds to the lowest whole unit of this field on a copy of this DateTime. * * @return a copy of the DateTime with the field value changed */ public DateTime roundFloorCopy() { return iInstant.withMillis(iField.roundFloor(iInstant.getMillis())); } /** * Rounds to the highest whole unit of this field on a copy of this DateTime. * * @return a copy of the DateTime with the field value changed */ public DateTime roundCeilingCopy() { return iInstant.withMillis(iField.roundCeiling(iInstant.getMillis())); } /** * Rounds to the nearest whole unit of this field on a copy of this DateTime, * favoring the floor if halfway. * * @return a copy of the DateTime with the field value changed */ public DateTime roundHalfFloorCopy() { return iInstant.withMillis(iField.roundHalfFloor(iInstant.getMillis())); } /** * Rounds to the nearest whole unit of this field on a copy of this DateTime, * favoring the ceiling if halfway. * * @return a copy of the DateTime with the field value changed */ public DateTime roundHalfCeilingCopy() { return iInstant.withMillis(iField.roundHalfCeiling(iInstant.getMillis())); } /** * Rounds to the nearest whole unit of this field on a copy of this * DateTime. If halfway, the ceiling is favored over the floor only if * it makes this field's value even. * * @return a copy of the DateTime with the field value changed */ public DateTime roundHalfEvenCopy() { return iInstant.withMillis(iField.roundHalfEven(iInstant.getMillis())); } } }