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 thisDuration = (ReadableDuration) this;
093 ReadableDuration otherDuration = (ReadableDuration) obj;
094
095 long thisMillis = thisDuration.getMillis();
096 long otherMillis = otherDuration.getMillis();
097
098 // cannot do (thisMillis - otherMillis) as it can overflow
099 if (thisMillis < otherMillis) {
100 return -1;
101 }
102 if (thisMillis > 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 }