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;
017
018 import java.io.Serializable;
019
020 /**
021 * Identifies a duration field, such as years or minutes, in a chronology-neutral way.
022 * <p>
023 * A duration field type defines the type of the field, such as hours.
024 * If does not directly enable any calculations, however it does provide a
025 * {@link #getField(Chronology)} method that returns the actual calculation engine
026 * for a particular chronology.
027 * <p>
028 * Instances of <code>DurationFieldType</code> are singletons.
029 * They can be compared using <code>==</code>.
030 * <p>
031 * If required, you can create your own field, for example a quarters.
032 * You must create a subclass of <code>DurationFieldType</code> that defines the field type.
033 * This class returns the actual calculation engine from {@link #getField(Chronology)}.
034 *
035 * @author Stephen Colebourne
036 * @author Brian S O'Neill
037 * @since 1.0
038 */
039 public abstract class DurationFieldType implements Serializable {
040
041 /** Serialization version */
042 private static final long serialVersionUID = 8765135187319L;
043
044 // Ordinals for standard field types.
045 static final byte
046 ERAS = 1,
047 CENTURIES = 2,
048 WEEKYEARS = 3,
049 YEARS = 4,
050 MONTHS = 5,
051 WEEKS = 6,
052 DAYS = 7,
053 HALFDAYS = 8,
054 HOURS = 9,
055 MINUTES = 10,
056 SECONDS = 11,
057 MILLIS = 12;
058
059 /** The eras field type. */
060 static final DurationFieldType ERAS_TYPE = new StandardDurationFieldType("eras", ERAS);
061 /** The centuries field type. */
062 static final DurationFieldType CENTURIES_TYPE = new StandardDurationFieldType("centuries", CENTURIES);
063 /** The weekyears field type. */
064 static final DurationFieldType WEEKYEARS_TYPE = new StandardDurationFieldType("weekyears", WEEKYEARS);
065 /** The years field type. */
066 static final DurationFieldType YEARS_TYPE = new StandardDurationFieldType("years", YEARS);
067 /** The months field type. */
068 static final DurationFieldType MONTHS_TYPE = new StandardDurationFieldType("months", MONTHS);
069 /** The weeks field type. */
070 static final DurationFieldType WEEKS_TYPE = new StandardDurationFieldType("weeks", WEEKS);
071 /** The days field type. */
072 static final DurationFieldType DAYS_TYPE = new StandardDurationFieldType("days", DAYS);
073 /** The halfdays field type. */
074 static final DurationFieldType HALFDAYS_TYPE = new StandardDurationFieldType("halfdays", HALFDAYS);
075 /** The hours field type. */
076 static final DurationFieldType HOURS_TYPE = new StandardDurationFieldType("hours", HOURS);
077 /** The minutes field type. */
078 static final DurationFieldType MINUTES_TYPE = new StandardDurationFieldType("minutes", MINUTES);
079 /** The seconds field type. */
080 static final DurationFieldType SECONDS_TYPE = new StandardDurationFieldType("seconds", SECONDS);
081 /** The millis field type. */
082 static final DurationFieldType MILLIS_TYPE = new StandardDurationFieldType("millis", MILLIS);
083
084 /** The name of the field type. */
085 private final String iName;
086
087 //-----------------------------------------------------------------------
088 /**
089 * Constructor.
090 *
091 * @param name the name to use, which by convention, are plural.
092 */
093 protected DurationFieldType(String name) {
094 super();
095 iName = name;
096 }
097
098 //-----------------------------------------------------------------------
099 /**
100 * Get the millis field type.
101 *
102 * @return the DateTimeFieldType constant
103 */
104 public static DurationFieldType millis() {
105 return MILLIS_TYPE;
106 }
107
108 /**
109 * Get the seconds field type.
110 *
111 * @return the DateTimeFieldType constant
112 */
113 public static DurationFieldType seconds() {
114 return SECONDS_TYPE;
115 }
116
117 /**
118 * Get the minutes field type.
119 *
120 * @return the DateTimeFieldType constant
121 */
122 public static DurationFieldType minutes() {
123 return MINUTES_TYPE;
124 }
125
126 /**
127 * Get the hours field type.
128 *
129 * @return the DateTimeFieldType constant
130 */
131 public static DurationFieldType hours() {
132 return HOURS_TYPE;
133 }
134
135 /**
136 * Get the halfdays field type.
137 *
138 * @return the DateTimeFieldType constant
139 */
140 public static DurationFieldType halfdays() {
141 return HALFDAYS_TYPE;
142 }
143
144 //-----------------------------------------------------------------------
145 /**
146 * Get the days field type.
147 *
148 * @return the DateTimeFieldType constant
149 */
150 public static DurationFieldType days() {
151 return DAYS_TYPE;
152 }
153
154 /**
155 * Get the weeks field type.
156 *
157 * @return the DateTimeFieldType constant
158 */
159 public static DurationFieldType weeks() {
160 return WEEKS_TYPE;
161 }
162
163 /**
164 * Get the weekyears field type.
165 *
166 * @return the DateTimeFieldType constant
167 */
168 public static DurationFieldType weekyears() {
169 return WEEKYEARS_TYPE;
170 }
171
172 /**
173 * Get the months field type.
174 *
175 * @return the DateTimeFieldType constant
176 */
177 public static DurationFieldType months() {
178 return MONTHS_TYPE;
179 }
180
181 /**
182 * Get the years field type.
183 *
184 * @return the DateTimeFieldType constant
185 */
186 public static DurationFieldType years() {
187 return YEARS_TYPE;
188 }
189
190 /**
191 * Get the centuries field type.
192 *
193 * @return the DateTimeFieldType constant
194 */
195 public static DurationFieldType centuries() {
196 return CENTURIES_TYPE;
197 }
198
199 /**
200 * Get the eras field type.
201 *
202 * @return the DateTimeFieldType constant
203 */
204 public static DurationFieldType eras() {
205 return ERAS_TYPE;
206 }
207
208 //-----------------------------------------------------------------------
209 /**
210 * Get the name of the field.
211 * By convention, names are plural.
212 *
213 * @return field name
214 */
215 public String getName() {
216 return iName;
217 }
218
219 /**
220 * Gets a suitable field for this type from the given Chronology.
221 *
222 * @param chronology the chronology to use, null means ISOChronology in default zone
223 * @return a suitable field
224 */
225 public abstract DurationField getField(Chronology chronology);
226
227 /**
228 * Checks whether this field supported in the given Chronology.
229 *
230 * @param chronology the chronology to use, null means ISOChronology in default zone
231 * @return true if supported
232 */
233 public boolean isSupported(Chronology chronology) {
234 return getField(chronology).isSupported();
235 }
236
237 /**
238 * Get a suitable debug string.
239 *
240 * @return debug string
241 */
242 public String toString() {
243 return getName();
244 }
245
246 private static class StandardDurationFieldType extends DurationFieldType {
247 /** Serialization version */
248 private static final long serialVersionUID = 31156755687123L;
249
250 /** The ordinal of the standard field type, for switch statements */
251 private final byte iOrdinal;
252
253 /**
254 * Constructor.
255 *
256 * @param name the name to use
257 */
258 StandardDurationFieldType(String name, byte ordinal) {
259 super(name);
260 iOrdinal = ordinal;
261 }
262
263 /** @inheritdoc */
264 @Override
265 public boolean equals(Object obj) {
266 if (this == obj) {
267 return true;
268 }
269 if (obj instanceof StandardDurationFieldType) {
270 return iOrdinal == ((StandardDurationFieldType) obj).iOrdinal;
271 }
272 return false;
273 }
274
275 /** @inheritdoc */
276 @Override
277 public int hashCode() {
278 return (1 << iOrdinal);
279 }
280
281 public DurationField getField(Chronology chronology) {
282 chronology = DateTimeUtils.getChronology(chronology);
283
284 switch (iOrdinal) {
285 case ERAS:
286 return chronology.eras();
287 case CENTURIES:
288 return chronology.centuries();
289 case WEEKYEARS:
290 return chronology.weekyears();
291 case YEARS:
292 return chronology.years();
293 case MONTHS:
294 return chronology.months();
295 case WEEKS:
296 return chronology.weeks();
297 case DAYS:
298 return chronology.days();
299 case HALFDAYS:
300 return chronology.halfdays();
301 case HOURS:
302 return chronology.hours();
303 case MINUTES:
304 return chronology.minutes();
305 case SECONDS:
306 return chronology.seconds();
307 case MILLIS:
308 return chronology.millis();
309 default:
310 // Shouldn't happen.
311 throw new InternalError();
312 }
313 }
314
315 /**
316 * Ensure a singleton is returned.
317 *
318 * @return the singleton type
319 */
320 private Object readResolve() {
321 switch (iOrdinal) {
322 case ERAS:
323 return ERAS_TYPE;
324 case CENTURIES:
325 return CENTURIES_TYPE;
326 case WEEKYEARS:
327 return WEEKYEARS_TYPE;
328 case YEARS:
329 return YEARS_TYPE;
330 case MONTHS:
331 return MONTHS_TYPE;
332 case WEEKS:
333 return WEEKS_TYPE;
334 case DAYS:
335 return DAYS_TYPE;
336 case HALFDAYS:
337 return HALFDAYS_TYPE;
338 case HOURS:
339 return HOURS_TYPE;
340 case MINUTES:
341 return MINUTES_TYPE;
342 case SECONDS:
343 return SECONDS_TYPE;
344 case MILLIS:
345 return MILLIS_TYPE;
346 default:
347 // Shouldn't happen.
348 return this;
349 }
350 }
351 }
352 }