View Javadoc

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 }