001/*
002 *  Copyright 2001-2009 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 */
016package org.joda.time;
017
018/**
019 * Defines the calculation engine for duration fields.
020 * The interface defines a set of methods that manipulate a millisecond duration
021 * with regards to a single field, such as months or seconds.
022 * <p>
023 * This design is extensible so, if you wish, you can extract a different field from
024 * the millisecond duration. A number of standard implementations are provided to assist.
025 *
026 * @author Stephen Colebourne
027 * @author Brian S O'Neill
028 * @since 1.0
029 */
030public abstract class DurationField implements Comparable<DurationField> {
031
032    /**
033     * Get the type of the field.
034     * 
035     * @return field type
036     */
037    public abstract DurationFieldType getType();
038
039    /**
040     * Get the name of the field.
041     * <p>
042     * By convention, names are plural.
043     * 
044     * @return field name
045     */
046    public abstract String getName();
047
048    /**
049     * Returns true if this field is supported.
050     * 
051     * @return true if this field is supported
052     */
053    public abstract boolean isSupported();
054
055    /**
056     * Is this field precise. A precise field can calculate its value from
057     * milliseconds without needing a reference date. Put another way, a
058     * precise field's unit size is not variable.
059     * 
060     * @return true if precise
061     * @see #getUnitMillis()
062     */
063    public abstract boolean isPrecise();
064    
065    /**
066     * Returns the amount of milliseconds per unit value of this field. For
067     * example, if this field represents "seconds", then this returns the
068     * milliseconds in one second.
069     * <p>
070     * For imprecise fields, the unit size is variable, and so this method
071     * returns a suitable average value.
072     *
073     * @return the unit size of this field, in milliseconds
074     * @see #isPrecise()
075     */
076    public abstract long getUnitMillis();
077
078    //------------------------------------------------------------------------
079    /**
080     * Get the value of this field from the milliseconds, which is approximate
081     * if this field is imprecise.
082     *
083     * @param duration  the milliseconds to query, which may be negative
084     * @return the value of the field, in the units of the field, which may be
085     * negative
086     * @throws ArithmeticException if the value is too large for an int
087     */
088    public abstract int getValue(long duration);
089
090    /**
091     * Get the value of this field from the milliseconds, which is approximate
092     * if this field is imprecise.
093     *
094     * @param duration  the milliseconds to query, which may be negative
095     * @return the value of the field, in the units of the field, which may be
096     * negative
097     */
098    public abstract long getValueAsLong(long duration);
099
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}