0001: /*
0002: * Copyright 2001-2007 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.IOException;
0019: import java.io.ObjectInputStream;
0020: import java.io.ObjectOutputStream;
0021: import java.io.Serializable;
0022: import java.util.Calendar;
0023: import java.util.Date;
0024: import java.util.HashSet;
0025: import java.util.Locale;
0026: import java.util.Set;
0027:
0028: import org.joda.time.base.BaseLocal;
0029: import org.joda.time.chrono.ISOChronology;
0030: import org.joda.time.convert.ConverterManager;
0031: import org.joda.time.convert.PartialConverter;
0032: import org.joda.time.field.AbstractReadableInstantFieldProperty;
0033: import org.joda.time.format.DateTimeFormat;
0034: import org.joda.time.format.ISODateTimeFormat;
0035:
0036: /**
0037: * LocalTime is an immutable time class representing a time
0038: * without a time zone.
0039: * <p>
0040: * LocalTime implements the {@link ReadablePartial} interface.
0041: * To do this, the interface methods focus on the key fields -
0042: * HourOfDay, MinuteOfHour, SecondOfMinute and MillisOfSecond.
0043: * However, <b>all</b> time fields may in fact be queried.
0044: * <p>
0045: * Calculations on LocalTime are performed using a {@link Chronology}.
0046: * This chronology will be set internally to be in the UTC time zone
0047: * for all calculations.
0048: *
0049: * <p>Each individual field can be queried in two ways:
0050: * <ul>
0051: * <li><code>getHourOfDay()</code>
0052: * <li><code>hourOfDay().get()</code>
0053: * </ul>
0054: * The second technique also provides access to other useful methods on the
0055: * field:
0056: * <ul>
0057: * <li>numeric value
0058: * <li>text value
0059: * <li>short text value
0060: * <li>maximum/minimum values
0061: * <li>add/subtract
0062: * <li>set
0063: * <li>rounding
0064: * </ul>
0065: *
0066: * <p>
0067: * LocalTime is thread-safe and immutable, provided that the Chronology is as well.
0068: * All standard Chronology classes supplied are thread-safe and immutable.
0069: *
0070: * @author Stephen Colebourne
0071: * @since 1.3
0072: */
0073: public final class LocalTime extends BaseLocal implements
0074: ReadablePartial, Serializable {
0075:
0076: /** Serialization lock */
0077: private static final long serialVersionUID = -12873158713873L;
0078:
0079: /** Constant for midnight. */
0080: public static final LocalTime MIDNIGHT = new LocalTime(0, 0, 0, 0);
0081:
0082: /** The index of the hourOfDay field in the field array */
0083: private static final int HOUR_OF_DAY = 0;
0084: /** The index of the minuteOfHour field in the field array */
0085: private static final int MINUTE_OF_HOUR = 1;
0086: /** The index of the secondOfMinute field in the field array */
0087: private static final int SECOND_OF_MINUTE = 2;
0088: /** The index of the millisOfSecond field in the field array */
0089: private static final int MILLIS_OF_SECOND = 3;
0090: /** Set of known duration types. */
0091: private static final Set TIME_DURATION_TYPES = new HashSet();
0092: static {
0093: TIME_DURATION_TYPES.add(DurationFieldType.millis());
0094: TIME_DURATION_TYPES.add(DurationFieldType.seconds());
0095: TIME_DURATION_TYPES.add(DurationFieldType.minutes());
0096: TIME_DURATION_TYPES.add(DurationFieldType.hours());
0097: }
0098:
0099: /** The local millis from 1970-01-01T00:00:00 */
0100: private long iLocalMillis;
0101: /** The chronology to use, in UTC */
0102: private Chronology iChronology;
0103:
0104: //-----------------------------------------------------------------------
0105: /**
0106: * Constructs a LocalTime from the specified millis of day using the
0107: * ISO chronology.
0108: * <p>
0109: * The millisOfDay value may exceed the number of millis in one day,
0110: * but additional days will be ignored.
0111: * This method uses the UTC time zone internally.
0112: *
0113: * @param millisOfDay the number of milliseconds into a day to convert
0114: */
0115: public static LocalTime fromMillisOfDay(long millisOfDay) {
0116: return fromMillisOfDay(millisOfDay, null);
0117: }
0118:
0119: /**
0120: * Constructs a LocalTime from the specified millis of day using the
0121: * specified chronology.
0122: * <p>
0123: * The millisOfDay value may exceed the number of millis in one day,
0124: * but additional days will be ignored.
0125: * This method uses the UTC time zone internally.
0126: *
0127: * @param millisOfDay the number of milliseconds into a day to convert
0128: * @param chrono the chronology, null means ISO chronology
0129: */
0130: public static LocalTime fromMillisOfDay(long millisOfDay,
0131: Chronology chrono) {
0132: chrono = DateTimeUtils.getChronology(chrono).withUTC();
0133: return new LocalTime(millisOfDay, chrono);
0134: }
0135:
0136: //-----------------------------------------------------------------------
0137: /**
0138: * Constructs a LocalTime from a <code>java.util.Calendar</code>
0139: * using exactly the same field values avoiding any time zone effects.
0140: * <p>
0141: * Each field is queried from the Calendar and assigned to the LocalTime.
0142: * This is useful if you have been using the Calendar as a local time,
0143: * ignoing the zone.
0144: * <p>
0145: * This factory method ignores the type of the calendar and always
0146: * creates a LocalTime with ISO chronology. It is expected that you
0147: * will only pass in instances of <code>GregorianCalendar</code> however
0148: * this is not validated.
0149: *
0150: * @param calendar the Calendar to extract fields from
0151: * @return the created LocalTime
0152: * @throws IllegalArgumentException if the calendar is null
0153: * @throws IllegalArgumentException if the date is invalid for the ISO chronology
0154: */
0155: public static LocalTime fromCalendarFields(Calendar calendar) {
0156: if (calendar == null) {
0157: throw new IllegalArgumentException(
0158: "The calendar must not be null");
0159: }
0160: return new LocalTime(calendar.get(Calendar.HOUR_OF_DAY),
0161: calendar.get(Calendar.MINUTE), calendar
0162: .get(Calendar.SECOND), calendar
0163: .get(Calendar.MILLISECOND));
0164: }
0165:
0166: /**
0167: * Constructs a LocalTime from a <code>java.util.Date</code>
0168: * using exactly the same field values avoiding any time zone effects.
0169: * <p>
0170: * Each field is queried from the Date and assigned to the LocalTime.
0171: * This is useful if you have been using the Date as a local time,
0172: * ignoing the zone.
0173: * <p>
0174: * This factory method always creates a LocalTime with ISO chronology.
0175: *
0176: * @param date the Date to extract fields from
0177: * @return the created LocalTime
0178: * @throws IllegalArgumentException if the calendar is null
0179: * @throws IllegalArgumentException if the date is invalid for the ISO chronology
0180: */
0181: public static LocalTime fromDateFields(Date date) {
0182: if (date == null) {
0183: throw new IllegalArgumentException(
0184: "The date must not be null");
0185: }
0186: return new LocalTime(date.getHours(), date.getMinutes(), date
0187: .getSeconds(), (int) (date.getTime() % 1000));
0188: }
0189:
0190: //-----------------------------------------------------------------------
0191: /**
0192: * Constructs an instance set to the current local time evaluated using
0193: * ISO chronology in the default zone.
0194: * <p>
0195: * Once the constructor is completed, the zone is no longer used.
0196: */
0197: public LocalTime() {
0198: this (DateTimeUtils.currentTimeMillis(), ISOChronology
0199: .getInstance());
0200: }
0201:
0202: /**
0203: * Constructs an instance set to the current local time evaluated using
0204: * ISO chronology in the specified zone.
0205: * <p>
0206: * If the specified time zone is null, the default zone is used.
0207: * Once the constructor is completed, the zone is no longer used.
0208: *
0209: * @param zone the time zone, null means default zone
0210: */
0211: public LocalTime(DateTimeZone zone) {
0212: this (DateTimeUtils.currentTimeMillis(), ISOChronology
0213: .getInstance(zone));
0214: }
0215:
0216: /**
0217: * Constructs an instance set to the current local time evaluated using
0218: * specified chronology and zone.
0219: * <p>
0220: * If the chronology is null, ISO chronology in the default time zone is used.
0221: * Once the constructor is completed, the zone is no longer used.
0222: *
0223: * @param chronology the chronology, null means ISOChronology in default zone
0224: */
0225: public LocalTime(Chronology chronology) {
0226: this (DateTimeUtils.currentTimeMillis(), chronology);
0227: }
0228:
0229: //-----------------------------------------------------------------------
0230: /**
0231: * Constructs an instance set to the local time defined by the specified
0232: * instant evaluated using ISO chronology in the default zone.
0233: * <p>
0234: * Once the constructor is completed, the zone is no longer used.
0235: *
0236: * @param instant the milliseconds from 1970-01-01T00:00:00Z
0237: */
0238: public LocalTime(long instant) {
0239: this (instant, ISOChronology.getInstance());
0240: }
0241:
0242: /**
0243: * Constructs an instance set to the local time defined by the specified
0244: * instant evaluated using ISO chronology in the specified zone.
0245: * <p>
0246: * If the specified time zone is null, the default zone is used.
0247: * Once the constructor is completed, the zone is no longer used.
0248: *
0249: * @param instant the milliseconds from 1970-01-01T00:00:00Z
0250: * @param zone the time zone, null means default zone
0251: */
0252: public LocalTime(long instant, DateTimeZone zone) {
0253: this (instant, ISOChronology.getInstance(zone));
0254: }
0255:
0256: /**
0257: * Constructs an instance set to the local time defined by the specified
0258: * instant evaluated using the specified chronology.
0259: * <p>
0260: * If the chronology is null, ISO chronology in the default zone is used.
0261: * Once the constructor is completed, the zone is no longer used.
0262: *
0263: * @param instant the milliseconds from 1970-01-01T00:00:00Z
0264: * @param chronology the chronology, null means ISOChronology in default zone
0265: */
0266: public LocalTime(long instant, Chronology chronology) {
0267: chronology = DateTimeUtils.getChronology(chronology);
0268:
0269: long localMillis = chronology.getZone().getMillisKeepLocal(
0270: DateTimeZone.UTC, instant);
0271: chronology = chronology.withUTC();
0272: iLocalMillis = chronology.millisOfDay().get(localMillis);
0273: iChronology = chronology;
0274: }
0275:
0276: //-----------------------------------------------------------------------
0277: /**
0278: * Constructs an instance from an Object that represents a datetime.
0279: * <p>
0280: * If the object contains no chronology, <code>ISOChronology</code> is used.
0281: * If the object contains no time zone, the default zone is used.
0282: * Once the constructor is completed, the zone is no longer used.
0283: * <p>
0284: * The recognised object types are defined in
0285: * {@link org.joda.time.convert.ConverterManager ConverterManager} and
0286: * include ReadablePartial, ReadableInstant, String, Calendar and Date.
0287: * The String formats are described by {@link ISODateTimeFormat#localTimeParser()}.
0288: * The default String converter ignores the zone and only parses the field values.
0289: *
0290: * @param instant the datetime object
0291: * @throws IllegalArgumentException if the instant is invalid
0292: */
0293: public LocalTime(Object instant) {
0294: this (instant, (Chronology) null);
0295: }
0296:
0297: /**
0298: * Constructs an instance from an Object that represents a datetime,
0299: * forcing the time zone to that specified.
0300: * <p>
0301: * If the object contains no chronology, <code>ISOChronology</code> is used.
0302: * If the specified time zone is null, the default zone is used.
0303: * Once the constructor is completed, the zone is no longer used.
0304: * <p>
0305: * The recognised object types are defined in
0306: * {@link org.joda.time.convert.ConverterManager ConverterManager} and
0307: * include ReadablePartial, ReadableInstant, String, Calendar and Date.
0308: * The String formats are described by {@link ISODateTimeFormat#localTimeParser()}.
0309: * The default String converter ignores the zone and only parses the field values.
0310: *
0311: * @param instant the datetime object
0312: * @param zone the time zone
0313: * @throws IllegalArgumentException if the instant is invalid
0314: */
0315: public LocalTime(Object instant, DateTimeZone zone) {
0316: PartialConverter converter = ConverterManager.getInstance()
0317: .getPartialConverter(instant);
0318: Chronology chronology = converter.getChronology(instant, zone);
0319: chronology = DateTimeUtils.getChronology(chronology);
0320: iChronology = chronology.withUTC();
0321: int[] values = converter.getPartialValues(this , instant,
0322: chronology, ISODateTimeFormat.localTimeParser());
0323: iLocalMillis = iChronology.getDateTimeMillis(0L, values[0],
0324: values[1], values[2], values[3]);
0325: }
0326:
0327: /**
0328: * Constructs an instance from an Object that represents a datetime,
0329: * using the specified chronology.
0330: * <p>
0331: * If the chronology is null, ISO in the default time zone is used.
0332: * Once the constructor is completed, the zone is no longer used.
0333: * <p>
0334: * The recognised object types are defined in
0335: * {@link org.joda.time.convert.ConverterManager ConverterManager} and
0336: * include ReadablePartial, ReadableInstant, String, Calendar and Date.
0337: * The String formats are described by {@link ISODateTimeFormat#localTimeParser()}.
0338: * The default String converter ignores the zone and only parses the field values.
0339: *
0340: * @param instant the datetime object
0341: * @param chronology the chronology
0342: * @throws IllegalArgumentException if the instant is invalid
0343: */
0344: public LocalTime(Object instant, Chronology chronology) {
0345: PartialConverter converter = ConverterManager.getInstance()
0346: .getPartialConverter(instant);
0347: chronology = converter.getChronology(instant, chronology);
0348: chronology = DateTimeUtils.getChronology(chronology);
0349: iChronology = chronology.withUTC();
0350: int[] values = converter.getPartialValues(this , instant,
0351: chronology, ISODateTimeFormat.localTimeParser());
0352: iLocalMillis = iChronology.getDateTimeMillis(0L, values[0],
0353: values[1], values[2], values[3]);
0354: }
0355:
0356: //-----------------------------------------------------------------------
0357: /**
0358: * Constructs an instance set to the specified time
0359: * using <code>ISOChronology</code>.
0360: *
0361: * @param hourOfDay the hour of the day
0362: * @param minuteOfHour the minute of the hour
0363: */
0364: public LocalTime(int hourOfDay, int minuteOfHour) {
0365: this (hourOfDay, minuteOfHour, 0, 0, ISOChronology
0366: .getInstanceUTC());
0367: }
0368:
0369: /**
0370: * Constructs an instance set to the specified time
0371: * using <code>ISOChronology</code>.
0372: *
0373: * @param hourOfDay the hour of the day
0374: * @param minuteOfHour the minute of the hour
0375: * @param secondOfMinute the second of the minute
0376: */
0377: public LocalTime(int hourOfDay, int minuteOfHour, int secondOfMinute) {
0378: this (hourOfDay, minuteOfHour, secondOfMinute, 0, ISOChronology
0379: .getInstanceUTC());
0380: }
0381:
0382: /**
0383: * Constructs an instance set to the specified time
0384: * using <code>ISOChronology</code>.
0385: *
0386: * @param hourOfDay the hour of the day
0387: * @param minuteOfHour the minute of the hour
0388: * @param secondOfMinute the second of the minute
0389: * @param millisOfSecond the millisecond of the second
0390: */
0391: public LocalTime(int hourOfDay, int minuteOfHour,
0392: int secondOfMinute, int millisOfSecond) {
0393: this (hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond,
0394: ISOChronology.getInstanceUTC());
0395: }
0396:
0397: /**
0398: * Constructs an instance set to the specified time
0399: * using the specified chronology, whose zone is ignored.
0400: * <p>
0401: * If the chronology is null, <code>ISOChronology</code> is used.
0402: *
0403: * @param hourOfDay the hour of the day
0404: * @param minuteOfHour the minute of the hour
0405: * @param secondOfMinute the second of the minute
0406: * @param millisOfSecond the millisecond of the second
0407: * @param chronology the chronology, null means ISOChronology in default zone
0408: */
0409: public LocalTime(int hourOfDay, int minuteOfHour,
0410: int secondOfMinute, int millisOfSecond,
0411: Chronology chronology) {
0412: super ();
0413: chronology = DateTimeUtils.getChronology(chronology).withUTC();
0414: long instant = chronology.getDateTimeMillis(0L, hourOfDay,
0415: minuteOfHour, secondOfMinute, millisOfSecond);
0416: iChronology = chronology;
0417: iLocalMillis = instant;
0418: }
0419:
0420: //-----------------------------------------------------------------------
0421: /**
0422: * Gets the number of fields in this partial, which is four.
0423: * The supported fields are HourOfDay, MinuteOfHour, SecondOfMinute
0424: * and MillisOfSecond.
0425: *
0426: * @return the field count, four
0427: */
0428: public int size() {
0429: return 4;
0430: }
0431:
0432: /**
0433: * Gets the field for a specific index in the chronology specified.
0434: * <p>
0435: * This method must not use any instance variables.
0436: *
0437: * @param index the index to retrieve
0438: * @param chrono the chronology to use
0439: * @return the field
0440: */
0441: protected DateTimeField getField(int index, Chronology chrono) {
0442: switch (index) {
0443: case HOUR_OF_DAY:
0444: return chrono.hourOfDay();
0445: case MINUTE_OF_HOUR:
0446: return chrono.minuteOfHour();
0447: case SECOND_OF_MINUTE:
0448: return chrono.secondOfMinute();
0449: case MILLIS_OF_SECOND:
0450: return chrono.millisOfSecond();
0451: default:
0452: throw new IndexOutOfBoundsException("Invalid index: "
0453: + index);
0454: }
0455: }
0456:
0457: /**
0458: * Gets the value of the field at the specifed index.
0459: * <p>
0460: * This method is required to support the <code>ReadablePartial</code>
0461: * interface. The supported fields are HourOfDay, MinuteOfHour,
0462: * SecondOfMinute and MillisOfSecond.
0463: *
0464: * @param index the index, zero to three
0465: * @return the value
0466: * @throws IndexOutOfBoundsException if the index is invalid
0467: */
0468: public int getValue(int index) {
0469: switch (index) {
0470: case HOUR_OF_DAY:
0471: return getChronology().hourOfDay().get(getLocalMillis());
0472: case MINUTE_OF_HOUR:
0473: return getChronology().minuteOfHour().get(getLocalMillis());
0474: case SECOND_OF_MINUTE:
0475: return getChronology().secondOfMinute().get(
0476: getLocalMillis());
0477: case MILLIS_OF_SECOND:
0478: return getChronology().millisOfSecond().get(
0479: getLocalMillis());
0480: default:
0481: throw new IndexOutOfBoundsException("Invalid index: "
0482: + index);
0483: }
0484: }
0485:
0486: //-----------------------------------------------------------------------
0487: /**
0488: * Get the value of one of the fields of time.
0489: * <p>
0490: * This method gets the value of the specified field.
0491: * For example:
0492: * <pre>
0493: * DateTime dt = new DateTime();
0494: * int hourOfDay = dt.get(DateTimeFieldType.hourOfDay());
0495: * </pre>
0496: *
0497: * @param fieldType a field type, usually obtained from DateTimeFieldType, not null
0498: * @return the value of that field
0499: * @throws IllegalArgumentException if the field type is null
0500: */
0501: public int get(DateTimeFieldType fieldType) {
0502: if (fieldType == null) {
0503: throw new IllegalArgumentException(
0504: "The DateTimeFieldType must not be null");
0505: }
0506: if (isSupported(fieldType) == false) {
0507: throw new IllegalArgumentException("Field '" + fieldType
0508: + "' is not supported");
0509: }
0510: return fieldType.getField(getChronology())
0511: .get(getLocalMillis());
0512: }
0513:
0514: /**
0515: * Checks if the field type specified is supported by this
0516: * local time and chronology.
0517: * This can be used to avoid exceptions in {@link #get(DateTimeFieldType)}.
0518: *
0519: * @param type a field type, usually obtained from DateTimeFieldType
0520: * @return true if the field type is supported
0521: */
0522: public boolean isSupported(DateTimeFieldType type) {
0523: if (type == null) {
0524: return false;
0525: }
0526: if (isSupported(type.getDurationType()) == false) {
0527: return false;
0528: }
0529: DurationFieldType range = type.getRangeDurationType();
0530: return (isSupported(range) || range == DurationFieldType.days());
0531: }
0532:
0533: /**
0534: * Checks if the duration type specified is supported by this
0535: * local time and chronology.
0536: *
0537: * @param type a duration type, usually obtained from DurationFieldType
0538: * @return true if the field type is supported
0539: */
0540: public boolean isSupported(DurationFieldType type) {
0541: if (type == null) {
0542: return false;
0543: }
0544: DurationField field = type.getField(getChronology());
0545: if (TIME_DURATION_TYPES.contains(type)
0546: || field.getUnitMillis() < getChronology().days()
0547: .getUnitMillis()) {
0548: return field.isSupported();
0549: }
0550: return false;
0551: }
0552:
0553: //-----------------------------------------------------------------------
0554: /**
0555: * Gets the local milliseconds from the Java epoch
0556: * of 1970-01-01T00:00:00 (not fixed to any specific time zone).
0557: *
0558: * @return the number of milliseconds since 1970-01-01T00:00:00
0559: * @since 1.5 (previously private)
0560: */
0561: protected long getLocalMillis() {
0562: return iLocalMillis;
0563: }
0564:
0565: /**
0566: * Gets the chronology of the time.
0567: *
0568: * @return the Chronology that the time is using
0569: */
0570: public Chronology getChronology() {
0571: return iChronology;
0572: }
0573:
0574: //-----------------------------------------------------------------------
0575: /**
0576: * Compares this ReadablePartial with another returning true if the chronology,
0577: * field types and values are equal.
0578: *
0579: * @param partial an object to check against
0580: * @return true if fields and values are equal
0581: */
0582: public boolean equals(Object partial) {
0583: // override to perform faster
0584: if (this == partial) {
0585: return true;
0586: }
0587: if (partial instanceof LocalTime) {
0588: LocalTime other = (LocalTime) partial;
0589: if (iChronology.equals(other.iChronology)) {
0590: return iLocalMillis == other.iLocalMillis;
0591: }
0592: }
0593: return super .equals(partial);
0594: }
0595:
0596: /**
0597: * Compares this partial with another returning an integer
0598: * indicating the order.
0599: * <p>
0600: * The fields are compared in order, from largest to smallest.
0601: * The first field that is non-equal is used to determine the result.
0602: * <p>
0603: * The specified object must be a partial instance whose field types
0604: * match those of this partial.
0605: * <p>
0606: * NOTE: This implementation violates the Comparable contract.
0607: * This method will accept any instance of ReadablePartial as input.
0608: * However, it is possible that some implementations of ReadablePartial
0609: * exist that do not extend AbstractPartial, and thus will throw a
0610: * ClassCastException if compared in the opposite direction.
0611: * The cause of this problem is that ReadablePartial doesn't define
0612: * the compareTo() method, however we can't change that until v2.0.
0613: *
0614: * @param partial an object to check against
0615: * @return negative if this is less, zero if equal, positive if greater
0616: * @throws ClassCastException if the partial is the wrong class
0617: * or if it has field types that don't match
0618: * @throws NullPointerException if the partial is null
0619: */
0620: public int compareTo(Object partial) {
0621: // override to perform faster
0622: if (this == partial) {
0623: return 0;
0624: }
0625: if (partial instanceof LocalTime) {
0626: LocalTime other = (LocalTime) partial;
0627: if (iChronology.equals(other.iChronology)) {
0628: return (iLocalMillis < other.iLocalMillis ? -1
0629: : (iLocalMillis == other.iLocalMillis ? 0 : 1));
0630:
0631: }
0632: }
0633: return super .compareTo(partial);
0634: }
0635:
0636: //-----------------------------------------------------------------------
0637: /**
0638: * Returns a copy of this time with different local millis.
0639: * <p>
0640: * The returned object will be a new instance of the same type.
0641: * Only the millis will change, the chronology is kept.
0642: * The returned object will be either be a new instance or <code>this</code>.
0643: *
0644: * @param newMillis the new millis, from 1970-01-01T00:00:00
0645: * @return a copy of this time with different millis
0646: */
0647: LocalTime withLocalMillis(long newMillis) {
0648: return (newMillis == getLocalMillis() ? this : new LocalTime(
0649: newMillis, getChronology()));
0650: }
0651:
0652: //-----------------------------------------------------------------------
0653: /**
0654: * Returns a copy of this time with the partial set of fields replacing
0655: * those from this instance.
0656: * <p>
0657: * For example, if the partial contains an hour and minute then those two
0658: * fields will be changed in the returned instance.
0659: * Unsupported fields are ignored.
0660: * If the partial is null, then <code>this</code> is returned.
0661: *
0662: * @param partial the partial set of fields to apply to this time, null ignored
0663: * @return a copy of this time with a different set of fields
0664: * @throws IllegalArgumentException if any value is invalid
0665: */
0666: public LocalTime withFields(ReadablePartial partial) {
0667: if (partial == null) {
0668: return this ;
0669: }
0670: return withLocalMillis(getChronology().set(partial,
0671: getLocalMillis()));
0672: }
0673:
0674: /**
0675: * Returns a copy of this time with the specified field set
0676: * to a new value.
0677: * <p>
0678: * For example, if the field type is <code>hourOfDay</code> then the hour of day
0679: * field would be changed in the returned instance.
0680: * If the field type is null, then <code>this</code> is returned.
0681: * <p>
0682: * These lines are equivalent:
0683: * <pre>
0684: * LocalTime updated = dt.withHourOfDay(6);
0685: * LocalTime updated = dt.withField(DateTimeFieldType.hourOfDay(), 6);
0686: * </pre>
0687: *
0688: * @param fieldType the field type to set, not null
0689: * @param value the value to set
0690: * @return a copy of this time with the field set
0691: * @throws IllegalArgumentException if the value is null or invalid
0692: */
0693: public LocalTime withField(DateTimeFieldType fieldType, int value) {
0694: if (fieldType == null) {
0695: throw new IllegalArgumentException("Field must not be null");
0696: }
0697: if (isSupported(fieldType) == false) {
0698: throw new IllegalArgumentException("Field '" + fieldType
0699: + "' is not supported");
0700: }
0701: long instant = fieldType.getField(getChronology()).set(
0702: getLocalMillis(), value);
0703: return withLocalMillis(instant);
0704: }
0705:
0706: /**
0707: * Returns a copy of this time with the value of the specified
0708: * field increased.
0709: * <p>
0710: * If the addition is zero or the field is null, then <code>this</code>
0711: * is returned.
0712: * <p>
0713: * If the addition causes the maximum value of the field to be exceeded,
0714: * then the value will wrap. Thus 23:59 plus two minutes yields 00:01.
0715: * <p>
0716: * These lines are equivalent:
0717: * <pre>
0718: * LocalTime added = dt.plusHours(6);
0719: * LocalTime added = dt.withFieldAdded(DurationFieldType.hours(), 6);
0720: * </pre>
0721: *
0722: * @param fieldType the field type to add to, not null
0723: * @param amount the amount to add
0724: * @return a copy of this time with the field updated
0725: * @throws IllegalArgumentException if the value is null or invalid
0726: * @throws ArithmeticException if the result exceeds the internal capacity
0727: */
0728: public LocalTime withFieldAdded(DurationFieldType fieldType,
0729: int amount) {
0730: if (fieldType == null) {
0731: throw new IllegalArgumentException("Field must not be null");
0732: }
0733: if (isSupported(fieldType) == false) {
0734: throw new IllegalArgumentException("Field '" + fieldType
0735: + "' is not supported");
0736: }
0737: if (amount == 0) {
0738: return this ;
0739: }
0740: long instant = fieldType.getField(getChronology()).add(
0741: getLocalMillis(), amount);
0742: return withLocalMillis(instant);
0743: }
0744:
0745: //-----------------------------------------------------------------------
0746: /**
0747: * Returns a copy of this time with the specified period added.
0748: * <p>
0749: * If the addition is zero, then <code>this</code> is returned.
0750: * <p>
0751: * This method is typically used to add multiple copies of complex
0752: * period instances. Adding one field is best achieved using methods
0753: * like {@link #withFieldAdded(DurationFieldType, int)}
0754: * or {@link #plusHours(int)}.
0755: *
0756: * @param period the period to add to this one, null means zero
0757: * @param scalar the amount of times to add, such as -1 to subtract once
0758: * @return a copy of this time with the period added
0759: * @throws ArithmeticException if the result exceeds the internal capacity
0760: */
0761: public LocalTime withPeriodAdded(ReadablePeriod period, int scalar) {
0762: if (period == null || scalar == 0) {
0763: return this ;
0764: }
0765: long instant = getChronology().add(period, getLocalMillis(),
0766: scalar);
0767: return withLocalMillis(instant);
0768: }
0769:
0770: //-----------------------------------------------------------------------
0771: /**
0772: * Returns a copy of this time with the specified period added.
0773: * <p>
0774: * If the amount is zero or null, then <code>this</code> is returned.
0775: * <p>
0776: * This method is typically used to add complex period instances.
0777: * Adding one field is best achieved using methods
0778: * like {@link #plusHours(int)}.
0779: *
0780: * @param period the period to add to this one, null means zero
0781: * @return a copy of this time with the period added
0782: * @throws ArithmeticException if the result exceeds the internal capacity
0783: */
0784: public LocalTime plus(ReadablePeriod period) {
0785: return withPeriodAdded(period, 1);
0786: }
0787:
0788: //-----------------------------------------------------------------------
0789: /**
0790: * Returns a copy of this time plus the specified number of hours.
0791: * <p>
0792: * This LocalTime instance is immutable and unaffected by this method call.
0793: * <p>
0794: * The following three lines are identical in effect:
0795: * <pre>
0796: * LocalTime added = dt.plusHours(6);
0797: * LocalTime added = dt.plus(Period.hours(6));
0798: * LocalTime added = dt.withFieldAdded(DurationFieldType.hours(), 6);
0799: * </pre>
0800: *
0801: * @param hours the amount of hours to add, may be negative
0802: * @return the new LocalTime plus the increased hours
0803: */
0804: public LocalTime plusHours(int hours) {
0805: if (hours == 0) {
0806: return this ;
0807: }
0808: long instant = getChronology().hours().add(getLocalMillis(),
0809: hours);
0810: return withLocalMillis(instant);
0811: }
0812:
0813: /**
0814: * Returns a copy of this time plus the specified number of minutes.
0815: * <p>
0816: * This LocalTime instance is immutable and unaffected by this method call.
0817: * <p>
0818: * The following three lines are identical in effect:
0819: * <pre>
0820: * LocalTime added = dt.plusMinutes(6);
0821: * LocalTime added = dt.plus(Period.minutes(6));
0822: * LocalTime added = dt.withFieldAdded(DurationFieldType.minutes(), 6);
0823: * </pre>
0824: *
0825: * @param minutes the amount of minutes to add, may be negative
0826: * @return the new LocalTime plus the increased minutes
0827: */
0828: public LocalTime plusMinutes(int minutes) {
0829: if (minutes == 0) {
0830: return this ;
0831: }
0832: long instant = getChronology().minutes().add(getLocalMillis(),
0833: minutes);
0834: return withLocalMillis(instant);
0835: }
0836:
0837: /**
0838: * Returns a copy of this time plus the specified number of seconds.
0839: * <p>
0840: * This LocalTime instance is immutable and unaffected by this method call.
0841: * <p>
0842: * The following three lines are identical in effect:
0843: * <pre>
0844: * LocalTime added = dt.plusSeconds(6);
0845: * LocalTime added = dt.plus(Period.seconds(6));
0846: * LocalTime added = dt.withFieldAdded(DurationFieldType.seconds(), 6);
0847: * </pre>
0848: *
0849: * @param seconds the amount of seconds to add, may be negative
0850: * @return the new LocalTime plus the increased seconds
0851: */
0852: public LocalTime plusSeconds(int seconds) {
0853: if (seconds == 0) {
0854: return this ;
0855: }
0856: long instant = getChronology().seconds().add(getLocalMillis(),
0857: seconds);
0858: return withLocalMillis(instant);
0859: }
0860:
0861: /**
0862: * Returns a copy of this time plus the specified number of millis.
0863: * <p>
0864: * This LocalTime instance is immutable and unaffected by this method call.
0865: * <p>
0866: * The following three lines are identical in effect:
0867: * <pre>
0868: * LocalTime added = dt.plusMillis(6);
0869: * LocalTime added = dt.plus(Period.millis(6));
0870: * LocalTime added = dt.withFieldAdded(DurationFieldType.millis(), 6);
0871: * </pre>
0872: *
0873: * @param millis the amount of millis to add, may be negative
0874: * @return the new LocalTime plus the increased millis
0875: */
0876: public LocalTime plusMillis(int millis) {
0877: if (millis == 0) {
0878: return this ;
0879: }
0880: long instant = getChronology().millis().add(getLocalMillis(),
0881: millis);
0882: return withLocalMillis(instant);
0883: }
0884:
0885: //-----------------------------------------------------------------------
0886: /**
0887: * Returns a copy of this time with the specified period taken away.
0888: * <p>
0889: * If the amount is zero or null, then <code>this</code> is returned.
0890: * <p>
0891: * This method is typically used to subtract complex period instances.
0892: * Subtracting one field is best achieved using methods
0893: * like {@link #minusHours(int)}.
0894: *
0895: * @param period the period to reduce this instant by
0896: * @return a copy of this time with the period taken away
0897: * @throws ArithmeticException if the result exceeds the internal capacity
0898: */
0899: public LocalTime minus(ReadablePeriod period) {
0900: return withPeriodAdded(period, -1);
0901: }
0902:
0903: //-----------------------------------------------------------------------
0904: /**
0905: * Returns a copy of this time minus the specified number of hours.
0906: * <p>
0907: * This LocalTime instance is immutable and unaffected by this method call.
0908: * <p>
0909: * The following three lines are identical in effect:
0910: * <pre>
0911: * LocalTime subtracted = dt.minusHours(6);
0912: * LocalTime subtracted = dt.minus(Period.hours(6));
0913: * LocalTime subtracted = dt.withFieldAdded(DurationFieldType.hours(), -6);
0914: * </pre>
0915: *
0916: * @param hours the amount of hours to subtract, may be negative
0917: * @return the new LocalTime minus the increased hours
0918: */
0919: public LocalTime minusHours(int hours) {
0920: if (hours == 0) {
0921: return this ;
0922: }
0923: long instant = getChronology().hours().subtract(
0924: getLocalMillis(), hours);
0925: return withLocalMillis(instant);
0926: }
0927:
0928: /**
0929: * Returns a copy of this time minus the specified number of minutes.
0930: * <p>
0931: * This LocalTime instance is immutable and unaffected by this method call.
0932: * <p>
0933: * The following three lines are identical in effect:
0934: * <pre>
0935: * LocalTime subtracted = dt.minusMinutes(6);
0936: * LocalTime subtracted = dt.minus(Period.minutes(6));
0937: * LocalTime subtracted = dt.withFieldAdded(DurationFieldType.minutes(), -6);
0938: * </pre>
0939: *
0940: * @param minutes the amount of minutes to subtract, may be negative
0941: * @return the new LocalTime minus the increased minutes
0942: */
0943: public LocalTime minusMinutes(int minutes) {
0944: if (minutes == 0) {
0945: return this ;
0946: }
0947: long instant = getChronology().minutes().subtract(
0948: getLocalMillis(), minutes);
0949: return withLocalMillis(instant);
0950: }
0951:
0952: /**
0953: * Returns a copy of this time minus the specified number of seconds.
0954: * <p>
0955: * This LocalTime instance is immutable and unaffected by this method call.
0956: * <p>
0957: * The following three lines are identical in effect:
0958: * <pre>
0959: * LocalTime subtracted = dt.minusSeconds(6);
0960: * LocalTime subtracted = dt.minus(Period.seconds(6));
0961: * LocalTime subtracted = dt.withFieldAdded(DurationFieldType.seconds(), -6);
0962: * </pre>
0963: *
0964: * @param seconds the amount of seconds to subtract, may be negative
0965: * @return the new LocalTime minus the increased seconds
0966: */
0967: public LocalTime minusSeconds(int seconds) {
0968: if (seconds == 0) {
0969: return this ;
0970: }
0971: long instant = getChronology().seconds().subtract(
0972: getLocalMillis(), seconds);
0973: return withLocalMillis(instant);
0974: }
0975:
0976: /**
0977: * Returns a copy of this time minus the specified number of millis.
0978: * <p>
0979: * This LocalTime instance is immutable and unaffected by this method call.
0980: * <p>
0981: * The following three lines are identical in effect:
0982: * <pre>
0983: * LocalTime subtracted = dt.minusMillis(6);
0984: * LocalTime subtracted = dt.minus(Period.millis(6));
0985: * LocalTime subtracted = dt.withFieldAdded(DurationFieldType.millis(), -6);
0986: * </pre>
0987: *
0988: * @param millis the amount of millis to subtract, may be negative
0989: * @return the new LocalTime minus the increased millis
0990: */
0991: public LocalTime minusMillis(int millis) {
0992: if (millis == 0) {
0993: return this ;
0994: }
0995: long instant = getChronology().millis().subtract(
0996: getLocalMillis(), millis);
0997: return withLocalMillis(instant);
0998: }
0999:
1000: //-----------------------------------------------------------------------
1001: /**
1002: * Gets the property object for the specified type, which contains
1003: * many useful methods.
1004: *
1005: * @param fieldType the field type to get the chronology for
1006: * @return the property object
1007: * @throws IllegalArgumentException if the field is null or unsupported
1008: */
1009: public Property property(DateTimeFieldType fieldType) {
1010: if (fieldType == null) {
1011: throw new IllegalArgumentException(
1012: "The DateTimeFieldType must not be null");
1013: }
1014: if (isSupported(fieldType) == false) {
1015: throw new IllegalArgumentException("Field '" + fieldType
1016: + "' is not supported");
1017: }
1018: return new Property(this , fieldType.getField(getChronology()));
1019: }
1020:
1021: //-----------------------------------------------------------------------
1022: /**
1023: * Get the hour of day field value.
1024: *
1025: * @return the hour of day
1026: */
1027: public int getHourOfDay() {
1028: return getChronology().hourOfDay().get(getLocalMillis());
1029: }
1030:
1031: /**
1032: * Get the minute of hour field value.
1033: *
1034: * @return the minute of hour
1035: */
1036: public int getMinuteOfHour() {
1037: return getChronology().minuteOfHour().get(getLocalMillis());
1038: }
1039:
1040: /**
1041: * Get the second of minute field value.
1042: *
1043: * @return the second of minute
1044: */
1045: public int getSecondOfMinute() {
1046: return getChronology().secondOfMinute().get(getLocalMillis());
1047: }
1048:
1049: /**
1050: * Get the millis of second field value.
1051: *
1052: * @return the millis of second
1053: */
1054: public int getMillisOfSecond() {
1055: return getChronology().millisOfSecond().get(getLocalMillis());
1056: }
1057:
1058: /**
1059: * Get the millis of day field value.
1060: *
1061: * @return the millis of day
1062: */
1063: public int getMillisOfDay() {
1064: return getChronology().millisOfDay().get(getLocalMillis());
1065: }
1066:
1067: //-----------------------------------------------------------------------
1068: /**
1069: * Returns a copy of this time with the hour of day field updated.
1070: * <p>
1071: * LocalTime is immutable, so there are no set methods.
1072: * Instead, this method returns a new instance with the value of
1073: * hour of day changed.
1074: *
1075: * @param hour the hour of day to set
1076: * @return a copy of this object with the field set
1077: * @throws IllegalArgumentException if the value is invalid
1078: */
1079: public LocalTime withHourOfDay(int hour) {
1080: return withLocalMillis(getChronology().hourOfDay().set(
1081: getLocalMillis(), hour));
1082: }
1083:
1084: /**
1085: * Returns a copy of this time with the minute of hour field updated.
1086: * <p>
1087: * LocalTime is immutable, so there are no set methods.
1088: * Instead, this method returns a new instance with the value of
1089: * minute of hour changed.
1090: *
1091: * @param minute the minute of hour to set
1092: * @return a copy of this object with the field set
1093: * @throws IllegalArgumentException if the value is invalid
1094: */
1095: public LocalTime withMinuteOfHour(int minute) {
1096: return withLocalMillis(getChronology().minuteOfHour().set(
1097: getLocalMillis(), minute));
1098: }
1099:
1100: /**
1101: * Returns a copy of this time with the second of minute field updated.
1102: * <p>
1103: * LocalTime is immutable, so there are no set methods.
1104: * Instead, this method returns a new instance with the value of
1105: * second of minute changed.
1106: *
1107: * @param second the second of minute to set
1108: * @return a copy of this object with the field set
1109: * @throws IllegalArgumentException if the value is invalid
1110: */
1111: public LocalTime withSecondOfMinute(int second) {
1112: return withLocalMillis(getChronology().secondOfMinute().set(
1113: getLocalMillis(), second));
1114: }
1115:
1116: /**
1117: * Returns a copy of this time with the millis of second field updated.
1118: * <p>
1119: * LocalTime is immutable, so there are no set methods.
1120: * Instead, this method returns a new instance with the value of
1121: * millis of second changed.
1122: *
1123: * @param millis the millis of second to set
1124: * @return a copy of this object with the field set
1125: * @throws IllegalArgumentException if the value is invalid
1126: */
1127: public LocalTime withMillisOfSecond(int millis) {
1128: return withLocalMillis(getChronology().millisOfSecond().set(
1129: getLocalMillis(), millis));
1130: }
1131:
1132: /**
1133: * Returns a copy of this time with the millis of day field updated.
1134: * <p>
1135: * LocalTime is immutable, so there are no set methods.
1136: * Instead, this method returns a new instance with the value of
1137: * millis of day changed.
1138: *
1139: * @param millis the millis of day to set
1140: * @return a copy of this object with the field set
1141: * @throws IllegalArgumentException if the value is invalid
1142: */
1143: public LocalTime withMillisOfDay(int millis) {
1144: return withLocalMillis(getChronology().millisOfDay().set(
1145: getLocalMillis(), millis));
1146: }
1147:
1148: //-----------------------------------------------------------------------
1149: /**
1150: * Get the hour of day field property which provides access to advanced functionality.
1151: *
1152: * @return the hour of day property
1153: */
1154: public Property hourOfDay() {
1155: return new Property(this , getChronology().hourOfDay());
1156: }
1157:
1158: /**
1159: * Get the minute of hour field property which provides access to advanced functionality.
1160: *
1161: * @return the minute of hour property
1162: */
1163: public Property minuteOfHour() {
1164: return new Property(this , getChronology().minuteOfHour());
1165: }
1166:
1167: /**
1168: * Get the second of minute field property which provides access to advanced functionality.
1169: *
1170: * @return the second of minute property
1171: */
1172: public Property secondOfMinute() {
1173: return new Property(this , getChronology().secondOfMinute());
1174: }
1175:
1176: /**
1177: * Get the millis of second property which provides access to advanced functionality.
1178: *
1179: * @return the millis of second property
1180: */
1181: public Property millisOfSecond() {
1182: return new Property(this , getChronology().millisOfSecond());
1183: }
1184:
1185: /**
1186: * Get the millis of day property which provides access to advanced functionality.
1187: *
1188: * @return the millis of day property
1189: */
1190: public Property millisOfDay() {
1191: return new Property(this , getChronology().millisOfDay());
1192: }
1193:
1194: //-----------------------------------------------------------------------
1195: /**
1196: * Converts this LocalTime to a full datetime using the default time zone
1197: * setting the time fields from this instance and the date fields from
1198: * the current date.
1199: *
1200: * @return this time as a datetime using todays date
1201: */
1202: public DateTime toDateTimeToday() {
1203: return toDateTimeToday(null);
1204: }
1205:
1206: /**
1207: * Converts this LocalTime to a full datetime using the specified time zone
1208: * setting the time fields from this instance and the date fields from
1209: * the current time.
1210: * <p>
1211: * This method uses the chronology from this instance plus the time zone
1212: * specified.
1213: *
1214: * @param zone the zone to use, null means default
1215: * @return this time as a datetime using todays date
1216: */
1217: public DateTime toDateTimeToday(DateTimeZone zone) {
1218: Chronology chrono = getChronology().withZone(zone);
1219: long instantMillis = DateTimeUtils.currentTimeMillis();
1220: long resolved = chrono.set(this , instantMillis);
1221: return new DateTime(resolved, chrono);
1222: }
1223:
1224: //-----------------------------------------------------------------------
1225: /**
1226: * Output the time in ISO8601 format (HH:mm:ss.SSSZ).
1227: *
1228: * @return ISO8601 time formatted string.
1229: */
1230: public String toString() {
1231: return ISODateTimeFormat.time().print(this );
1232: }
1233:
1234: /**
1235: * Output the time using the specified format pattern.
1236: *
1237: * @param pattern the pattern specification, null means use <code>toString</code>
1238: * @see org.joda.time.format.DateTimeFormat
1239: */
1240: public String toString(String pattern) {
1241: if (pattern == null) {
1242: return toString();
1243: }
1244: return DateTimeFormat.forPattern(pattern).print(this );
1245: }
1246:
1247: /**
1248: * Output the time using the specified format pattern.
1249: *
1250: * @param pattern the pattern specification, null means use <code>toString</code>
1251: * @param locale Locale to use, null means default
1252: * @see org.joda.time.format.DateTimeFormat
1253: */
1254: public String toString(String pattern, Locale locale)
1255: throws IllegalArgumentException {
1256: if (pattern == null) {
1257: return toString();
1258: }
1259: return DateTimeFormat.forPattern(pattern).withLocale(locale)
1260: .print(this );
1261: }
1262:
1263: //-----------------------------------------------------------------------
1264: /**
1265: * LocalTime.Property binds a LocalTime to a DateTimeField allowing
1266: * powerful datetime functionality to be easily accessed.
1267: * <p>
1268: * The simplest use of this class is as an alternative get method, here used to
1269: * get the minute '30'.
1270: * <pre>
1271: * LocalTime dt = new LocalTime(12, 30);
1272: * int year = dt.minuteOfHour().get();
1273: * </pre>
1274: * <p>
1275: * Methods are also provided that allow time modification. These return
1276: * new instances of LocalTime - they do not modify the original. The example
1277: * below yields two independent immutable date objects 2 hours apart.
1278: * <pre>
1279: * LocalTime dt1230 = new LocalTime(12, 30);
1280: * LocalTime dt1430 = dt1230.hourOfDay().setCopy(14);
1281: * </pre>
1282: * <p>
1283: * LocalTime.Property itself is thread-safe and immutable, as well as the
1284: * LocalTime being operated on.
1285: *
1286: * @author Stephen Colebourne
1287: * @author Brian S O'Neill
1288: * @since 1.3
1289: */
1290: public static final class Property extends
1291: AbstractReadableInstantFieldProperty {
1292:
1293: /** Serialization version */
1294: private static final long serialVersionUID = -325842547277223L;
1295:
1296: /** The instant this property is working against */
1297: private transient LocalTime iInstant;
1298: /** The field this property is working against */
1299: private transient DateTimeField iField;
1300:
1301: /**
1302: * Constructor.
1303: *
1304: * @param instant the instant to set
1305: * @param field the field to use
1306: */
1307: Property(LocalTime instant, DateTimeField field) {
1308: super ();
1309: iInstant = instant;
1310: iField = field;
1311: }
1312:
1313: /**
1314: * Writes the property in a safe serialization format.
1315: */
1316: private void writeObject(ObjectOutputStream oos)
1317: throws IOException {
1318: oos.writeObject(iInstant);
1319: oos.writeObject(iField.getType());
1320: }
1321:
1322: /**
1323: * Reads the property from a safe serialization format.
1324: */
1325: private void readObject(ObjectInputStream oos)
1326: throws IOException, ClassNotFoundException {
1327: iInstant = (LocalTime) oos.readObject();
1328: DateTimeFieldType type = (DateTimeFieldType) oos
1329: .readObject();
1330: iField = type.getField(iInstant.getChronology());
1331: }
1332:
1333: //-----------------------------------------------------------------------
1334: /**
1335: * Gets the field being used.
1336: *
1337: * @return the field
1338: */
1339: public DateTimeField getField() {
1340: return iField;
1341: }
1342:
1343: /**
1344: * Gets the milliseconds of the time that this property is linked to.
1345: *
1346: * @return the milliseconds
1347: */
1348: protected long getMillis() {
1349: return iInstant.getLocalMillis();
1350: }
1351:
1352: /**
1353: * Gets the chronology of the datetime that this property is linked to.
1354: *
1355: * @return the chronology
1356: * @since 1.4
1357: */
1358: protected Chronology getChronology() {
1359: return iInstant.getChronology();
1360: }
1361:
1362: /**
1363: * Gets the LocalTime object linked to this property.
1364: *
1365: * @return the linked LocalTime
1366: */
1367: public LocalTime getLocalTime() {
1368: return iInstant;
1369: }
1370:
1371: //-----------------------------------------------------------------------
1372: /**
1373: * Adds to this field in a copy of this LocalTime.
1374: * <p>
1375: * The LocalTime attached to this property is unchanged by this call.
1376: *
1377: * @param value the value to add to the field in the copy
1378: * @return a copy of the LocalTime with the field value changed
1379: */
1380: public LocalTime addCopy(int value) {
1381: return iInstant.withLocalMillis(iField.add(iInstant
1382: .getLocalMillis(), value));
1383: }
1384:
1385: /**
1386: * Adds to this field in a copy of this LocalTime.
1387: * If the addition exceeds the maximum value (eg. 23:59) it will
1388: * wrap to the minimum value (eg. 00:00).
1389: * <p>
1390: * The LocalTime attached to this property is unchanged by this call.
1391: *
1392: * @param value the value to add to the field in the copy
1393: * @return a copy of the LocalTime with the field value changed
1394: */
1395: public LocalTime addCopy(long value) {
1396: return iInstant.withLocalMillis(iField.add(iInstant
1397: .getLocalMillis(), value));
1398: }
1399:
1400: /**
1401: * Adds to this field in a copy of this LocalTime.
1402: * If the addition exceeds the maximum value (eg. 23:59) then
1403: * an exception will be thrown.
1404: * Contrast this behaviour to {@link #addCopy(int)}.
1405: * <p>
1406: * The LocalTime attached to this property is unchanged by this call.
1407: *
1408: * @param value the value to add to the field in the copy
1409: * @return a copy of the LocalTime with the field value changed
1410: * @throws IllegalArgumentException if the result is invalid
1411: */
1412: public LocalTime addNoWrapToCopy(int value) {
1413: long millis = iField.add(iInstant.getLocalMillis(), value);
1414: long rounded = iInstant.getChronology().millisOfDay().get(
1415: millis);
1416: if (rounded != millis) {
1417: throw new IllegalArgumentException(
1418: "The addition exceeded the boundaries of LocalTime");
1419: }
1420: return iInstant.withLocalMillis(millis);
1421: }
1422:
1423: /**
1424: * Adds to this field, possibly wrapped, in a copy of this LocalTime.
1425: * A field wrapped operation only changes this field.
1426: * Thus 10:59 plusWrapField one minute goes to 10:00.
1427: * <p>
1428: * The LocalTime attached to this property is unchanged by this call.
1429: *
1430: * @param value the value to add to the field in the copy
1431: * @return a copy of the LocalTime with the field value changed
1432: * @throws IllegalArgumentException if the value isn't valid
1433: */
1434: public LocalTime addWrapFieldToCopy(int value) {
1435: return iInstant.withLocalMillis(iField.addWrapField(
1436: iInstant.getLocalMillis(), value));
1437: }
1438:
1439: //-----------------------------------------------------------------------
1440: /**
1441: * Sets this field in a copy of the LocalTime.
1442: * <p>
1443: * The LocalTime attached to this property is unchanged by this call.
1444: *
1445: * @param value the value to set the field in the copy to
1446: * @return a copy of the LocalTime with the field value changed
1447: * @throws IllegalArgumentException if the value isn't valid
1448: */
1449: public LocalTime setCopy(int value) {
1450: return iInstant.withLocalMillis(iField.set(iInstant
1451: .getLocalMillis(), value));
1452: }
1453:
1454: /**
1455: * Sets this field in a copy of the LocalTime to a parsed text value.
1456: * <p>
1457: * The LocalTime attached to this property is unchanged by this call.
1458: *
1459: * @param text the text value to set
1460: * @param locale optional locale to use for selecting a text symbol
1461: * @return a copy of the LocalTime with the field value changed
1462: * @throws IllegalArgumentException if the text value isn't valid
1463: */
1464: public LocalTime setCopy(String text, Locale locale) {
1465: return iInstant.withLocalMillis(iField.set(iInstant
1466: .getLocalMillis(), text, locale));
1467: }
1468:
1469: /**
1470: * Sets this field in a copy of the LocalTime to a parsed text value.
1471: * <p>
1472: * The LocalTime attached to this property is unchanged by this call.
1473: *
1474: * @param text the text value to set
1475: * @return a copy of the LocalTime with the field value changed
1476: * @throws IllegalArgumentException if the text value isn't valid
1477: */
1478: public LocalTime setCopy(String text) {
1479: return setCopy(text, null);
1480: }
1481:
1482: //-----------------------------------------------------------------------
1483: /**
1484: * Returns a new LocalTime with this field set to the maximum value
1485: * for this field.
1486: * <p>
1487: * The LocalTime attached to this property is unchanged by this call.
1488: *
1489: * @return a copy of the LocalTime with this field set to its maximum
1490: */
1491: public LocalTime withMaximumValue() {
1492: return setCopy(getMaximumValue());
1493: }
1494:
1495: /**
1496: * Returns a new LocalTime with this field set to the minimum value
1497: * for this field.
1498: * <p>
1499: * The LocalTime attached to this property is unchanged by this call.
1500: *
1501: * @return a copy of the LocalTime with this field set to its minimum
1502: */
1503: public LocalTime withMinimumValue() {
1504: return setCopy(getMinimumValue());
1505: }
1506:
1507: //-----------------------------------------------------------------------
1508: /**
1509: * Rounds to the lowest whole unit of this field on a copy of this
1510: * LocalTime.
1511: * <p>
1512: * For example, rounding floor on the hourOfDay field of a LocalTime
1513: * where the time is 10:30 would result in new LocalTime with the
1514: * time of 10:00.
1515: *
1516: * @return a copy of the LocalTime with the field value changed
1517: */
1518: public LocalTime roundFloorCopy() {
1519: return iInstant.withLocalMillis(iField.roundFloor(iInstant
1520: .getLocalMillis()));
1521: }
1522:
1523: /**
1524: * Rounds to the highest whole unit of this field on a copy of this
1525: * LocalTime.
1526: * <p>
1527: * For example, rounding floor on the hourOfDay field of a LocalTime
1528: * where the time is 10:30 would result in new LocalTime with the
1529: * time of 11:00.
1530: *
1531: * @return a copy of the LocalTime with the field value changed
1532: */
1533: public LocalTime roundCeilingCopy() {
1534: return iInstant.withLocalMillis(iField
1535: .roundCeiling(iInstant.getLocalMillis()));
1536: }
1537:
1538: /**
1539: * Rounds to the nearest whole unit of this field on a copy of this
1540: * LocalTime, favoring the floor if halfway.
1541: *
1542: * @return a copy of the LocalTime with the field value changed
1543: */
1544: public LocalTime roundHalfFloorCopy() {
1545: return iInstant.withLocalMillis(iField
1546: .roundHalfFloor(iInstant.getLocalMillis()));
1547: }
1548:
1549: /**
1550: * Rounds to the nearest whole unit of this field on a copy of this
1551: * LocalTime, favoring the ceiling if halfway.
1552: *
1553: * @return a copy of the LocalTime with the field value changed
1554: */
1555: public LocalTime roundHalfCeilingCopy() {
1556: return iInstant.withLocalMillis(iField
1557: .roundHalfCeiling(iInstant.getLocalMillis()));
1558: }
1559:
1560: /**
1561: * Rounds to the nearest whole unit of this field on a copy of this
1562: * LocalTime. If halfway, the ceiling is favored over the floor
1563: * only if it makes this field's value even.
1564: *
1565: * @return a copy of the LocalTime with the field value changed
1566: */
1567: public LocalTime roundHalfEvenCopy() {
1568: return iInstant.withLocalMillis(iField
1569: .roundHalfEven(iInstant.getLocalMillis()));
1570: }
1571: }
1572:
1573: }
|