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 public DurationField getField(Chronology chronology) {
264 chronology = DateTimeUtils.getChronology(chronology);
265
266 switch (iOrdinal) {
267 case ERAS:
268 return chronology.eras();
269 case CENTURIES:
270 return chronology.centuries();
271 case WEEKYEARS:
272 return chronology.weekyears();
273 case YEARS:
274 return chronology.years();
275 case MONTHS:
276 return chronology.months();
277 case WEEKS:
278 return chronology.weeks();
279 case DAYS:
280 return chronology.days();
281 case HALFDAYS:
282 return chronology.halfdays();
283 case HOURS:
284 return chronology.hours();
285 case MINUTES:
286 return chronology.minutes();
287 case SECONDS:
288 return chronology.seconds();
289 case MILLIS:
290 return chronology.millis();
291 default:
292 // Shouldn't happen.
293 throw new InternalError();
294 }
295 }
296
297 /**
298 * Ensure a singleton is returned.
299 *
300 * @return the singleton type
301 */
302 private Object readResolve() {
303 switch (iOrdinal) {
304 case ERAS:
305 return ERAS_TYPE;
306 case CENTURIES:
307 return CENTURIES_TYPE;
308 case WEEKYEARS:
309 return WEEKYEARS_TYPE;
310 case YEARS:
311 return YEARS_TYPE;
312 case MONTHS:
313 return MONTHS_TYPE;
314 case WEEKS:
315 return WEEKS_TYPE;
316 case DAYS:
317 return DAYS_TYPE;
318 case HALFDAYS:
319 return HALFDAYS_TYPE;
320 case HOURS:
321 return HOURS_TYPE;
322 case MINUTES:
323 return MINUTES_TYPE;
324 case SECONDS:
325 return SECONDS_TYPE;
326 case MILLIS:
327 return MILLIS_TYPE;
328 default:
329 // Shouldn't happen.
330 return this;
331 }
332 }
333
334 }
335 }