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