1 | /* |
2 | * Copyright 2001-2005 Stephen Colebourne |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | package org.joda.time.base; |
17 | |
18 | import org.joda.time.Duration; |
19 | import org.joda.time.Period; |
20 | import org.joda.time.ReadableDuration; |
21 | import org.joda.time.format.FormatUtils; |
22 | |
23 | /** |
24 | * AbstractDuration provides the common behaviour for duration classes. |
25 | * <p> |
26 | * This class should generally not be used directly by API users. The |
27 | * {@link ReadableDuration} interface should be used when different |
28 | * kinds of durations are to be referenced. |
29 | * <p> |
30 | * AbstractDuration subclasses may be mutable and not thread-safe. |
31 | * |
32 | * @author Brian S O'Neill |
33 | * @author Stephen Colebourne |
34 | * @since 1.0 |
35 | */ |
36 | public abstract class AbstractDuration implements ReadableDuration { |
37 | |
38 | /** |
39 | * Constructor. |
40 | */ |
41 | protected AbstractDuration() { |
42 | super(); |
43 | } |
44 | |
45 | //----------------------------------------------------------------------- |
46 | /** |
47 | * Get this duration as an immutable <code>Duration</code> object. |
48 | * |
49 | * @return a Duration created using the millisecond duration from this instance |
50 | */ |
51 | public Duration toDuration() { |
52 | return new Duration(getMillis()); |
53 | } |
54 | |
55 | //----------------------------------------------------------------------- |
56 | /** |
57 | * Converts this duration to a Period instance using the standard period type |
58 | * and the ISO chronology. |
59 | * <p> |
60 | * Only precise fields in the period type will be used. Thus, only the hour, |
61 | * minute, second and millisecond fields on the period will be used. |
62 | * The year, month, week and day fields will not be populated. |
63 | * <p> |
64 | * If the duration is small, less than one day, then this method will perform |
65 | * as you might expect and split the fields evenly. |
66 | * If the duration is larger than one day then all the remaining duration will |
67 | * be stored in the largest available field, hours in this case. |
68 | * <p> |
69 | * For example, a duration effectively equal to (365 + 60 + 5) days will be |
70 | * converted to ((365 + 60 + 5) * 24) hours by this constructor. |
71 | * <p> |
72 | * For more control over the conversion process, you must pair the duration with |
73 | * an instant, see {@link Period#Period(ReadableInstant,ReadableDuration)}. |
74 | * |
75 | * @return a Period created using the millisecond duration from this instance |
76 | */ |
77 | public Period toPeriod() { |
78 | return new Period(getMillis()); |
79 | } |
80 | |
81 | //----------------------------------------------------------------------- |
82 | /** |
83 | * Compares this duration with the specified duration based on length. |
84 | * |
85 | * @param obj a duration to check against |
86 | * @return negative value if this is less, 0 if equal, or positive value if greater |
87 | * @throws NullPointerException if the object is null |
88 | * @throws ClassCastException if the given object is not supported |
89 | */ |
90 | public int compareTo(Object obj) { |
91 | // Comparable contract means we cannot handle null or other types gracefully |
92 | ReadableDuration thisDuration = (ReadableDuration) this; |
93 | ReadableDuration otherDuration = (ReadableDuration) obj; |
94 | |
95 | long thisMillis = thisDuration.getMillis(); |
96 | long otherMillis = otherDuration.getMillis(); |
97 | |
98 | // cannot do (thisMillis - otherMillis) as it can overflow |
99 | 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 | } |