1 /*
2 * Copyright 2001-2009 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;
17
18 /**
19 * Defines the calculation engine for duration fields.
20 * The interface defines a set of methods that manipulate a millisecond duration
21 * with regards to a single field, such as months or seconds.
22 * <p>
23 * This design is extensible so, if you wish, you can extract a different field from
24 * the millisecond duration. A number of standard implementations are provided to assist.
25 *
26 * @author Stephen Colebourne
27 * @author Brian S O'Neill
28 * @since 1.0
29 */
30 public abstract class DurationField implements Comparable<DurationField> {
31
32 /**
33 * Get the type of the field.
34 *
35 * @return field type
36 */
37 public abstract DurationFieldType getType();
38
39 /**
40 * Get the name of the field.
41 * <p>
42 * By convention, names are plural.
43 *
44 * @return field name
45 */
46 public abstract String getName();
47
48 /**
49 * Returns true if this field is supported.
50 *
51 * @return true if this field is supported
52 */
53 public abstract boolean isSupported();
54
55 /**
56 * Is this field precise. A precise field can calculate its value from
57 * milliseconds without needing a reference date. Put another way, a
58 * precise field's unit size is not variable.
59 *
60 * @return true if precise
61 * @see #getUnitMillis()
62 */
63 public abstract boolean isPrecise();
64
65 /**
66 * Returns the amount of milliseconds per unit value of this field. For
67 * example, if this field represents "seconds", then this returns the
68 * milliseconds in one second.
69 * <p>
70 * For imprecise fields, the unit size is variable, and so this method
71 * returns a suitable average value.
72 *
73 * @return the unit size of this field, in milliseconds
74 * @see #isPrecise()
75 */
76 public abstract long getUnitMillis();
77
78 //------------------------------------------------------------------------
79 /**
80 * Get the value of this field from the milliseconds, which is approximate
81 * if this field is imprecise.
82 *
83 * @param duration the milliseconds to query, which may be negative
84 * @return the value of the field, in the units of the field, which may be
85 * negative
86 * @throws ArithmeticException if the value is too large for an int
87 */
88 public abstract int getValue(long duration);
89
90 /**
91 * Get the value of this field from the milliseconds, which is approximate
92 * if this field is imprecise.
93 *
94 * @param duration the milliseconds to query, which may be negative
95 * @return the value of the field, in the units of the field, which may be
96 * negative
97 */
98 public abstract long getValueAsLong(long duration);
99
100 /**
101 * Get the value of this field from the milliseconds relative to an
102 * instant. For precise fields this method produces the same result as for
103 * the single argument get method.
104 * <p>
105 * If the millisecond duration is positive, then the instant is treated as a
106 * "start instant". If negative, the instant is treated as an "end instant".
107 *
108 * @param duration the milliseconds to query, which may be negative
109 * @param instant the start instant to calculate relative to
110 * @return the value of the field, in the units of the field, which may be
111 * negative
112 * @throws ArithmeticException if the value is too large for an int
113 */
114 public abstract int getValue(long duration, long instant);
115
116 /**
117 * Get the value of this field from the milliseconds relative to an
118 * instant. For precise fields this method produces the same result as for
119 * the single argument get method.
120 * <p>
121 * If the millisecond duration is positive, then the instant is treated as a
122 * "start instant". If negative, the instant is treated as an "end instant".
123 *
124 * @param duration the milliseconds to query, which may be negative
125 * @param instant the start instant to calculate relative to
126 * @return the value of the field, in the units of the field, which may be
127 * negative
128 */
129 public abstract long getValueAsLong(long duration, long instant);
130
131 //------------------------------------------------------------------------
132 /**
133 * Get the millisecond duration of this field from its value, which is
134 * approximate if this field is imprecise.
135 *
136 * @param value the value of the field, which may be negative
137 * @return the milliseconds that the field represents, which may be
138 * negative
139 */
140 public abstract long getMillis(int value);
141
142 /**
143 * Get the millisecond duration of this field from its value, which is
144 * approximate if this field is imprecise.
145 *
146 * @param value the value of the field, which may be negative
147 * @return the milliseconds that the field represents, which may be
148 * negative
149 */
150 public abstract long getMillis(long value);
151
152 /**
153 * Get the millisecond duration of this field from its value relative to an
154 * instant. For precise fields this method produces the same result as for
155 * the single argument getMillis method.
156 * <p>
157 * If the value is positive, then the instant is treated as a "start
158 * instant". If negative, the instant is treated as an "end instant".
159 *
160 * @param value the value of the field, which may be negative
161 * @param instant the instant to calculate relative to
162 * @return the millisecond duration that the field represents, which may be
163 * negative
164 */
165 public abstract long getMillis(int value, long instant);
166
167 /**
168 * Get the millisecond duration of this field from its value relative to an
169 * instant. For precise fields this method produces the same result as for
170 * the single argument getMillis method.
171 * <p>
172 * If the value is positive, then the instant is treated as a "start
173 * instant". If negative, the instant is treated as an "end instant".
174 *
175 * @param value the value of the field, which may be negative
176 * @param instant the instant to calculate relative to
177 * @return the millisecond duration that the field represents, which may be
178 * negative
179 */
180 public abstract long getMillis(long value, long instant);
181
182 /**
183 * Adds a duration value (which may be negative) to the instant.
184 *
185 * @param instant the milliseconds from 1970-01-01T00:00:00Z to add to
186 * @param value the value to add, in the units of the field
187 * @return the updated milliseconds
188 */
189 public abstract long add(long instant, int value);
190
191 /**
192 * Adds a duration value (which may be negative) to the instant.
193 *
194 * @param instant the milliseconds from 1970-01-01T00:00:00Z to add to
195 * @param value the value to add, in the units of the field
196 * @return the updated milliseconds
197 */
198 public abstract long add(long instant, long value);
199
200 /**
201 * Subtracts a duration value (which may be negative) from the instant.
202 *
203 * @param instant the milliseconds from 1970-01-01T00:00:00Z to subtract from
204 * @param value the value to subtract, in the units of the field
205 * @return the updated milliseconds
206 * @since 1.1
207 */
208 public long subtract(long instant, int value) {
209 if (value == Integer.MIN_VALUE) {
210 return subtract(instant, (long) value);
211 }
212 return add(instant, -value);
213 }
214
215 /**
216 * Subtracts a duration value (which may be negative) from the instant.
217 *
218 * @param instant the milliseconds from 1970-01-01T00:00:00Z to subtract from
219 * @param value the value to subtract, in the units of the field
220 * @return the updated milliseconds
221 * @since 1.1
222 */
223 public long subtract(long instant, long value) {
224 if (value == Long.MIN_VALUE) {
225 throw new ArithmeticException("Long.MIN_VALUE cannot be negated");
226 }
227 return add(instant, -value);
228 }
229
230 /**
231 * Computes the difference between two instants, as measured in the units
232 * of this field. Any fractional units are dropped from the result. Calling
233 * getDifference reverses the effect of calling add. In the following code:
234 *
235 * <pre>
236 * long instant = ...
237 * int v = ...
238 * int age = getDifference(add(instant, v), instant);
239 * </pre>
240 *
241 * The value 'age' is the same as the value 'v'.
242 *
243 * @param minuendInstant the milliseconds from 1970-01-01T00:00:00Z to
244 * subtract from
245 * @param subtrahendInstant the milliseconds from 1970-01-01T00:00:00Z to
246 * subtract off the minuend
247 * @return the difference in the units of this field
248 */
249 public abstract int getDifference(long minuendInstant, long subtrahendInstant);
250
251 /**
252 * Computes the difference between two instants, as measured in the units
253 * of this field. Any fractional units are dropped from the result. Calling
254 * getDifference reverses the effect of calling add. In the following code:
255 *
256 * <pre>
257 * long instant = ...
258 * long v = ...
259 * long age = getDifferenceAsLong(add(instant, v), instant);
260 * </pre>
261 *
262 * The value 'age' is the same as the value 'v'.
263 *
264 * @param minuendInstant the milliseconds from 1970-01-01T00:00:00Z to
265 * subtract from
266 * @param subtrahendInstant the milliseconds from 1970-01-01T00:00:00Z to
267 * subtract off the minuend
268 * @return the difference in the units of this field
269 */
270 public abstract long getDifferenceAsLong(long minuendInstant, long subtrahendInstant);
271
272 // Adding this definition would be backwards incompatible with earlier subclasses
273 // This definition of compareTo was present in previous versions, and still applies
274 // /**
275 // * Compares this duration field with another duration field for ascending
276 // * unit millisecond order. This ordering is inconsistent with equals, as it
277 // * ignores name and precision.
278 // *
279 // * @param durationField a duration field to check against
280 // * @return negative value if this is less, 0 if equal, or positive value if greater
281 // * @throws NullPointerException if the object is null
282 // * @throws ClassCastException if the object type is not supported
283 // */
284 // public abstract int compareTo(DurationField durationField);
285
286 /**
287 * Returns a localized unit name of this field, using the given value as an
288 * aid. For example, the unit name may differ if it is plural.
289 *
290 * @param value the duration value to use for selecting a unit name
291 * @param locale the locale to use for selecting a name, null for default
292 */
293 //String getUnitName(long value, Locale locale);
294
295 /**
296 * Returns a localized unit name of this field, using the given value as an
297 * aid. For example, the unit name may differ if it is plural.
298 *
299 * @param value the duration value to use for selecting a unit name
300 */
301 //String getUnitName(long value);
302
303 /**
304 * Get the maximum length string returned by getUnitName.
305 *
306 * @param locale the locale to use for selecting a unit name, null for
307 * default
308 * @return the maximum name length
309 */
310 //int getMaximumUnitNameLength(Locale locale);
311
312 //------------------------------------------------------------------------
313 /**
314 * Get a suitable debug string.
315 *
316 * @return debug string
317 */
318 public abstract String toString();
319
320 }