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;
17
18 import java.io.Serializable;
19
20 /**
21 * Identifies a duration field, such as years or minutes, in a chronology-neutral way.
22 * <p>
23 * A duration field type defines the type of the field, such as hours.
24 * If does not directly enable any calculations, however it does provide a
25 * {@link #getField(Chronology)} method that returns the actual calculation engine
26 * for a particular chronology.
27 * <p>
28 * Instances of <code>DurationFieldType</code> are singletons.
29 * They can be compared using <code>==</code>.
30 * <p>
31 * If required, you can create your own field, for example a quarters.
32 * You must create a subclass of <code>DurationFieldType</code> that defines the field type.
33 * This class returns the actual calculation engine from {@link #getField(Chronology)}.
34 *
35 * @author Stephen Colebourne
36 * @author Brian S O'Neill
37 * @since 1.0
38 */
39 public abstract class DurationFieldType implements Serializable {
40
41 /** Serialization version */
42 private static final long serialVersionUID = 8765135187319L;
43
44 // Ordinals for standard field types.
45 static final byte
46 ERAS = 1,
47 CENTURIES = 2,
48 WEEKYEARS = 3,
49 YEARS = 4,
50 MONTHS = 5,
51 WEEKS = 6,
52 DAYS = 7,
53 HALFDAYS = 8,
54 HOURS = 9,
55 MINUTES = 10,
56 SECONDS = 11,
57 MILLIS = 12;
58
59 /** The eras field type. */
60 static final DurationFieldType ERAS_TYPE = new StandardDurationFieldType("eras", ERAS);
61 /** The centuries field type. */
62 static final DurationFieldType CENTURIES_TYPE = new StandardDurationFieldType("centuries", CENTURIES);
63 /** The weekyears field type. */
64 static final DurationFieldType WEEKYEARS_TYPE = new StandardDurationFieldType("weekyears", WEEKYEARS);
65 /** The years field type. */
66 static final DurationFieldType YEARS_TYPE = new StandardDurationFieldType("years", YEARS);
67 /** The months field type. */
68 static final DurationFieldType MONTHS_TYPE = new StandardDurationFieldType("months", MONTHS);
69 /** The weeks field type. */
70 static final DurationFieldType WEEKS_TYPE = new StandardDurationFieldType("weeks", WEEKS);
71 /** The days field type. */
72 static final DurationFieldType DAYS_TYPE = new StandardDurationFieldType("days", DAYS);
73 /** The halfdays field type. */
74 static final DurationFieldType HALFDAYS_TYPE = new StandardDurationFieldType("halfdays", HALFDAYS);
75 /** The hours field type. */
76 static final DurationFieldType HOURS_TYPE = new StandardDurationFieldType("hours", HOURS);
77 /** The minutes field type. */
78 static final DurationFieldType MINUTES_TYPE = new StandardDurationFieldType("minutes", MINUTES);
79 /** The seconds field type. */
80 static final DurationFieldType SECONDS_TYPE = new StandardDurationFieldType("seconds", SECONDS);
81 /** The millis field type. */
82 static final DurationFieldType MILLIS_TYPE = new StandardDurationFieldType("millis", MILLIS);
83
84 /** The name of the field type. */
85 private final String iName;
86
87 //-----------------------------------------------------------------------
88 /**
89 * Constructor.
90 *
91 * @param name the name to use, which by convention, are plural.
92 */
93 protected DurationFieldType(String name) {
94 super();
95 iName = name;
96 }
97
98 //-----------------------------------------------------------------------
99 /**
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 }
353