001: /*
002: * Copyright 2001-2005 Stephen Colebourne
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.joda.time.base;
017:
018: import org.joda.time.Duration;
019: import org.joda.time.Period;
020: import org.joda.time.ReadableDuration;
021: import org.joda.time.format.FormatUtils;
022:
023: /**
024: * AbstractDuration provides the common behaviour for duration classes.
025: * <p>
026: * This class should generally not be used directly by API users. The
027: * {@link ReadableDuration} interface should be used when different
028: * kinds of durations are to be referenced.
029: * <p>
030: * AbstractDuration subclasses may be mutable and not thread-safe.
031: *
032: * @author Brian S O'Neill
033: * @author Stephen Colebourne
034: * @since 1.0
035: */
036: public abstract class AbstractDuration implements ReadableDuration {
037:
038: /**
039: * Constructor.
040: */
041: protected AbstractDuration() {
042: super ();
043: }
044:
045: //-----------------------------------------------------------------------
046: /**
047: * Get this duration as an immutable <code>Duration</code> object.
048: *
049: * @return a Duration created using the millisecond duration from this instance
050: */
051: public Duration toDuration() {
052: return new Duration(getMillis());
053: }
054:
055: //-----------------------------------------------------------------------
056: /**
057: * Converts this duration to a Period instance using the standard period type
058: * and the ISO chronology.
059: * <p>
060: * Only precise fields in the period type will be used. Thus, only the hour,
061: * minute, second and millisecond fields on the period will be used.
062: * The year, month, week and day fields will not be populated.
063: * <p>
064: * If the duration is small, less than one day, then this method will perform
065: * as you might expect and split the fields evenly.
066: * If the duration is larger than one day then all the remaining duration will
067: * be stored in the largest available field, hours in this case.
068: * <p>
069: * For example, a duration effectively equal to (365 + 60 + 5) days will be
070: * converted to ((365 + 60 + 5) * 24) hours by this constructor.
071: * <p>
072: * For more control over the conversion process, you must pair the duration with
073: * an instant, see {@link Period#Period(ReadableInstant,ReadableDuration)}.
074: *
075: * @return a Period created using the millisecond duration from this instance
076: */
077: public Period toPeriod() {
078: return new Period(getMillis());
079: }
080:
081: //-----------------------------------------------------------------------
082: /**
083: * Compares this duration with the specified duration based on length.
084: *
085: * @param obj a duration to check against
086: * @return negative value if this is less, 0 if equal, or positive value if greater
087: * @throws NullPointerException if the object is null
088: * @throws ClassCastException if the given object is not supported
089: */
090: public int compareTo(Object obj) {
091: // Comparable contract means we cannot handle null or other types gracefully
092: ReadableDuration this Duration = (ReadableDuration) this ;
093: ReadableDuration otherDuration = (ReadableDuration) obj;
094:
095: long this Millis = this Duration.getMillis();
096: long otherMillis = otherDuration.getMillis();
097:
098: // cannot do (thisMillis - otherMillis) as it can overflow
099: if (this Millis < otherMillis) {
100: return -1;
101: }
102: if (this Millis > otherMillis) {
103: return 1;
104: }
105: return 0;
106: }
107:
108: /**
109: * Is the length of this duration equal to the duration passed in.
110: *
111: * @param duration another duration to compare to, null means zero milliseconds
112: * @return true if this duration is equal to than the duration passed in
113: */
114: public boolean isEqual(ReadableDuration duration) {
115: if (duration == null) {
116: duration = Duration.ZERO;
117: }
118: return compareTo(duration) == 0;
119: }
120:
121: /**
122: * Is the length of this duration longer than the duration passed in.
123: *
124: * @param duration another duration to compare to, null means zero milliseconds
125: * @return true if this duration is equal to than the duration passed in
126: */
127: public boolean isLongerThan(ReadableDuration duration) {
128: if (duration == null) {
129: duration = Duration.ZERO;
130: }
131: return compareTo(duration) > 0;
132: }
133:
134: /**
135: * Is the length of this duration shorter than the duration passed in.
136: *
137: * @param duration another duration to compare to, null means zero milliseconds
138: * @return true if this duration is equal to than the duration passed in
139: */
140: public boolean isShorterThan(ReadableDuration duration) {
141: if (duration == null) {
142: duration = Duration.ZERO;
143: }
144: return compareTo(duration) < 0;
145: }
146:
147: //-----------------------------------------------------------------------
148: /**
149: * Compares this object with the specified object for equality based
150: * on the millisecond length. All ReadableDuration instances are accepted.
151: *
152: * @param duration a readable duration to check against
153: * @return true if the length of the duration is equal
154: */
155: public boolean equals(Object duration) {
156: if (this == duration) {
157: return true;
158: }
159: if (duration instanceof ReadableDuration == false) {
160: return false;
161: }
162: ReadableDuration other = (ReadableDuration) duration;
163: return (getMillis() == other.getMillis());
164: }
165:
166: /**
167: * Gets a hash code for the duration that is compatible with the
168: * equals method.
169: *
170: * @return a hash code
171: */
172: public int hashCode() {
173: long len = getMillis();
174: return (int) (len ^ (len >>> 32));
175: }
176:
177: //-----------------------------------------------------------------------
178: /**
179: * Gets the value as a String in the ISO8601 duration format including
180: * only seconds and milliseconds.
181: * <p>
182: * For example, "PT72.345S" represents 1 minute, 12 seconds and 345 milliseconds.
183: * <p>
184: * For more control over the output, see
185: * {@link org.joda.time.format.PeriodFormatterBuilder PeriodFormatterBuilder}.
186: *
187: * @return the value as an ISO8601 string
188: */
189: public String toString() {
190: long millis = getMillis();
191: StringBuffer buf = new StringBuffer();
192: buf.append("PT");
193: FormatUtils.appendUnpaddedInteger(buf, millis / 1000);
194: long part = Math.abs(millis % 1000);
195: if (part > 0) {
196: buf.append('.');
197: FormatUtils.appendPaddedInteger(buf, part, 3);
198: }
199: buf.append('S');
200: return buf.toString();
201: }
202:
203: }
|