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 field, such as year or minuteOfHour, in a chronology-neutral way.
22   * <p>
23   * A field type defines the type of the field, such as hourOfDay.
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   * It also provides access to the related {@link DurationFieldType}s.
28   * <p>
29   * Instances of <code>DateTimeFieldType</code> are singletons.
30   * They can be compared using <code>==</code>.
31   * <p>
32   * If required, you can create your own field, for example a quarterOfYear.
33   * You must create a subclass of <code>DateTimeFieldType</code> that defines the field type.
34   * This class returns the actual calculation engine from {@link #getField(Chronology)}.
35   * The subclass should implement equals and hashCode.
36   *
37   * @author Stephen Colebourne
38   * @author Brian S O'Neill
39   * @since 1.0
40   */
41  public abstract class DateTimeFieldType implements Serializable {
42  
43      /** Serialization version */
44      private static final long serialVersionUID = -42615285973990L;
45  
46      /** Ordinal values for standard field types. */
47      static final byte
48          ERA = 1,
49          YEAR_OF_ERA = 2,
50          CENTURY_OF_ERA = 3,
51          YEAR_OF_CENTURY = 4,
52          YEAR = 5,
53          DAY_OF_YEAR = 6,
54          MONTH_OF_YEAR = 7,
55          DAY_OF_MONTH = 8,
56          WEEKYEAR_OF_CENTURY = 9,
57          WEEKYEAR = 10,
58          WEEK_OF_WEEKYEAR = 11,
59          DAY_OF_WEEK = 12,
60          HALFDAY_OF_DAY = 13,
61          HOUR_OF_HALFDAY = 14,
62          CLOCKHOUR_OF_HALFDAY = 15,
63          CLOCKHOUR_OF_DAY = 16,
64          HOUR_OF_DAY = 17,
65          MINUTE_OF_DAY = 18,
66          MINUTE_OF_HOUR = 19,
67          SECOND_OF_DAY = 20,
68          SECOND_OF_MINUTE = 21,
69          MILLIS_OF_DAY = 22,
70          MILLIS_OF_SECOND = 23;
71  
72      /** The era field type. */
73      private static final DateTimeFieldType ERA_TYPE = new StandardDateTimeFieldType(
74          "era", ERA, DurationFieldType.eras(), null);
75      /** The yearOfEra field type. */
76      private static final DateTimeFieldType YEAR_OF_ERA_TYPE = new StandardDateTimeFieldType(
77          "yearOfEra", YEAR_OF_ERA, DurationFieldType.years(), DurationFieldType.eras());
78      /** The centuryOfEra field type. */
79      private static final DateTimeFieldType CENTURY_OF_ERA_TYPE = new StandardDateTimeFieldType(
80          "centuryOfEra", CENTURY_OF_ERA, DurationFieldType.centuries(), DurationFieldType.eras());
81      /** The yearOfCentury field type. */
82      private static final DateTimeFieldType YEAR_OF_CENTURY_TYPE = new StandardDateTimeFieldType(
83          "yearOfCentury", YEAR_OF_CENTURY, DurationFieldType.years(), DurationFieldType.centuries());
84      /** The year field type. */
85      private static final DateTimeFieldType YEAR_TYPE = new StandardDateTimeFieldType(
86          "year", YEAR, DurationFieldType.years(), null);
87      /** The dayOfYear field type. */
88      private static final DateTimeFieldType DAY_OF_YEAR_TYPE = new StandardDateTimeFieldType(
89          "dayOfYear", DAY_OF_YEAR, DurationFieldType.days(), DurationFieldType.years());
90      /** The monthOfYear field type. */
91      private static final DateTimeFieldType MONTH_OF_YEAR_TYPE = new StandardDateTimeFieldType(
92          "monthOfYear", MONTH_OF_YEAR, DurationFieldType.months(), DurationFieldType.years());
93      /** The dayOfMonth field type. */
94      private static final DateTimeFieldType DAY_OF_MONTH_TYPE = new StandardDateTimeFieldType(
95          "dayOfMonth", DAY_OF_MONTH, DurationFieldType.days(), DurationFieldType.months());
96      /** The weekyearOfCentury field type. */
97      private static final DateTimeFieldType WEEKYEAR_OF_CENTURY_TYPE = new StandardDateTimeFieldType(
98          "weekyearOfCentury", WEEKYEAR_OF_CENTURY, DurationFieldType.weekyears(), DurationFieldType.centuries());
99      /** The weekyear field type. */
100     private static final DateTimeFieldType WEEKYEAR_TYPE = new StandardDateTimeFieldType(
101         "weekyear", WEEKYEAR, DurationFieldType.weekyears(), null);
102     /** The weekOfWeekyear field type. */
103     private static final DateTimeFieldType WEEK_OF_WEEKYEAR_TYPE = new StandardDateTimeFieldType(
104         "weekOfWeekyear", WEEK_OF_WEEKYEAR, DurationFieldType.weeks(), DurationFieldType.weekyears());
105     /** The dayOfWeek field type. */
106     private static final DateTimeFieldType DAY_OF_WEEK_TYPE = new StandardDateTimeFieldType(
107         "dayOfWeek", DAY_OF_WEEK, DurationFieldType.days(), DurationFieldType.weeks());
108 
109     /** The halfday field type. */
110     private static final DateTimeFieldType HALFDAY_OF_DAY_TYPE = new StandardDateTimeFieldType(
111         "halfdayOfDay", HALFDAY_OF_DAY, DurationFieldType.halfdays(), DurationFieldType.days());
112     /** The hourOfHalfday field type. */
113     private static final DateTimeFieldType HOUR_OF_HALFDAY_TYPE = new StandardDateTimeFieldType(
114         "hourOfHalfday", HOUR_OF_HALFDAY, DurationFieldType.hours(), DurationFieldType.halfdays());
115     /** The clockhourOfHalfday field type. */
116     private static final DateTimeFieldType CLOCKHOUR_OF_HALFDAY_TYPE = new StandardDateTimeFieldType(
117         "clockhourOfHalfday", CLOCKHOUR_OF_HALFDAY, DurationFieldType.hours(), DurationFieldType.halfdays());
118     /** The clockhourOfDay field type. */
119     private static final DateTimeFieldType CLOCKHOUR_OF_DAY_TYPE = new StandardDateTimeFieldType(
120         "clockhourOfDay", CLOCKHOUR_OF_DAY, DurationFieldType.hours(), DurationFieldType.days());
121     /** The hourOfDay field type. */
122     private static final DateTimeFieldType HOUR_OF_DAY_TYPE = new StandardDateTimeFieldType(
123         "hourOfDay", HOUR_OF_DAY, DurationFieldType.hours(), DurationFieldType.days());
124     /** The minuteOfDay field type. */
125     private static final DateTimeFieldType MINUTE_OF_DAY_TYPE = new StandardDateTimeFieldType(
126         "minuteOfDay", MINUTE_OF_DAY, DurationFieldType.minutes(), DurationFieldType.days());
127     /** The minuteOfHour field type. */
128     private static final DateTimeFieldType MINUTE_OF_HOUR_TYPE = new StandardDateTimeFieldType(
129         "minuteOfHour", MINUTE_OF_HOUR, DurationFieldType.minutes(), DurationFieldType.hours());
130     /** The secondOfDay field type. */
131     private static final DateTimeFieldType SECOND_OF_DAY_TYPE = new StandardDateTimeFieldType(
132         "secondOfDay", SECOND_OF_DAY, DurationFieldType.seconds(), DurationFieldType.days());
133     /** The secondOfMinute field type. */
134     private static final DateTimeFieldType SECOND_OF_MINUTE_TYPE = new StandardDateTimeFieldType(
135         "secondOfMinute", SECOND_OF_MINUTE, DurationFieldType.seconds(), DurationFieldType.minutes());
136     /** The millisOfDay field type. */
137     private static final DateTimeFieldType MILLIS_OF_DAY_TYPE = new StandardDateTimeFieldType(
138         "millisOfDay", MILLIS_OF_DAY, DurationFieldType.millis(), DurationFieldType.days());
139     /** The millisOfSecond field type. */
140     private static final DateTimeFieldType MILLIS_OF_SECOND_TYPE = new StandardDateTimeFieldType(
141         "millisOfSecond", MILLIS_OF_SECOND, DurationFieldType.millis(), DurationFieldType.seconds());
142 
143     /** The name of the field. */
144     private final String iName;
145 
146     //-----------------------------------------------------------------------
147     /**
148      * Constructor.
149      * 
150      * @param name  the name to use
151      */
152     protected DateTimeFieldType(String name) {
153         super();
154         iName = name;
155     }
156 
157     //-----------------------------------------------------------------------
158     /**
159      * Get the millis of second field type.
160      * 
161      * @return the DateTimeFieldType constant
162      */
163     public static DateTimeFieldType millisOfSecond() {
164         return MILLIS_OF_SECOND_TYPE;
165     }
166 
167     /**
168      * Get the millis of day field type.
169      * 
170      * @return the DateTimeFieldType constant
171      */
172     public static DateTimeFieldType millisOfDay() {
173         return MILLIS_OF_DAY_TYPE;
174     }
175 
176     /**
177      * Get the second of minute field type.
178      * 
179      * @return the DateTimeFieldType constant
180      */
181     public static DateTimeFieldType secondOfMinute() {
182         return SECOND_OF_MINUTE_TYPE;
183     }
184 
185     /**
186      * Get the second of day field type.
187      * 
188      * @return the DateTimeFieldType constant
189      */
190     public static DateTimeFieldType secondOfDay() {
191         return SECOND_OF_DAY_TYPE;
192     }
193 
194     /**
195      * Get the minute of hour field type.
196      * 
197      * @return the DateTimeFieldType constant
198      */
199     public static DateTimeFieldType minuteOfHour() {
200         return MINUTE_OF_HOUR_TYPE;
201     }
202 
203     /**
204      * Get the minute of day field type.
205      * 
206      * @return the DateTimeFieldType constant
207      */
208     public static DateTimeFieldType minuteOfDay() {
209         return MINUTE_OF_DAY_TYPE;
210     }
211 
212     /**
213      * Get the hour of day (0-23) field type.
214      * 
215      * @return the DateTimeFieldType constant
216      */
217     public static DateTimeFieldType hourOfDay() {
218         return HOUR_OF_DAY_TYPE;
219     }
220 
221     /**
222      * Get the hour of day (offset to 1-24) field type.
223      * 
224      * @return the DateTimeFieldType constant
225      */
226     public static DateTimeFieldType clockhourOfDay() {
227         return CLOCKHOUR_OF_DAY_TYPE;
228     }
229 
230     /**
231      * Get the hour of am/pm (0-11) field type.
232      * 
233      * @return the DateTimeFieldType constant
234      */
235     public static DateTimeFieldType hourOfHalfday() {
236         return HOUR_OF_HALFDAY_TYPE;
237     }
238 
239     /**
240      * Get the hour of am/pm (offset to 1-12) field type.
241      * 
242      * @return the DateTimeFieldType constant
243      */
244     public static DateTimeFieldType clockhourOfHalfday() {
245         return CLOCKHOUR_OF_HALFDAY_TYPE;
246     }
247 
248     /**
249      * Get the AM(0) PM(1) field type.
250      * 
251      * @return the DateTimeFieldType constant
252      */
253     public static DateTimeFieldType halfdayOfDay() {
254         return HALFDAY_OF_DAY_TYPE;
255     }
256 
257     //-----------------------------------------------------------------------
258     /**
259      * Get the day of week field type.
260      * 
261      * @return the DateTimeFieldType constant
262      */
263     public static DateTimeFieldType dayOfWeek() {
264         return DAY_OF_WEEK_TYPE;
265     }
266 
267     /**
268      * Get the day of month field type.
269      * 
270      * @return the DateTimeFieldType constant
271      */
272     public static DateTimeFieldType dayOfMonth() {
273         return DAY_OF_MONTH_TYPE;
274     }
275 
276     /**
277      * Get the day of year field type.
278      * 
279      * @return the DateTimeFieldType constant
280      */
281     public static DateTimeFieldType dayOfYear() {
282         return DAY_OF_YEAR_TYPE;
283     }
284 
285     /**
286      * Get the week of a week based year field type.
287      * 
288      * @return the DateTimeFieldType constant
289      */
290     public static DateTimeFieldType weekOfWeekyear() {
291         return WEEK_OF_WEEKYEAR_TYPE;
292     }
293 
294     /**
295      * Get the year of a week based year field type.
296      * 
297      * @return the DateTimeFieldType constant
298      */
299     public static DateTimeFieldType weekyear() {
300         return WEEKYEAR_TYPE;
301     }
302 
303     /**
304      * Get the year of a week based year within a century field type.
305      * 
306      * @return the DateTimeFieldType constant
307      */
308     public static DateTimeFieldType weekyearOfCentury() {
309         return WEEKYEAR_OF_CENTURY_TYPE;
310     }
311 
312     /**
313      * Get the month of year field type.
314      * 
315      * @return the DateTimeFieldType constant
316      */
317     public static DateTimeFieldType monthOfYear() {
318         return MONTH_OF_YEAR_TYPE;
319     }
320 
321     /**
322      * Get the year field type.
323      * 
324      * @return the DateTimeFieldType constant
325      */
326     public static DateTimeFieldType year() {
327         return YEAR_TYPE;
328     }
329 
330     /**
331      * Get the year of era field type.
332      * 
333      * @return the DateTimeFieldType constant
334      */
335     public static DateTimeFieldType yearOfEra() {
336         return YEAR_OF_ERA_TYPE;
337     }
338 
339     /**
340      * Get the year of century field type.
341      * 
342      * @return the DateTimeFieldType constant
343      */
344     public static DateTimeFieldType yearOfCentury() {
345         return YEAR_OF_CENTURY_TYPE;
346     }
347 
348     /**
349      * Get the century of era field type.
350      * 
351      * @return the DateTimeFieldType constant
352      */
353     public static DateTimeFieldType centuryOfEra() {
354         return CENTURY_OF_ERA_TYPE;
355     }
356 
357     /**
358      * Get the era field type.
359      * 
360      * @return the DateTimeFieldType constant
361      */
362     public static DateTimeFieldType era() {
363         return ERA_TYPE;
364     }
365 
366     //-----------------------------------------------------------------------
367     /**
368      * Get the name of the field.
369      * <p>
370      * By convention, names follow a pattern of "dddOfRrr", where "ddd" represents
371      * the (singular) duration unit field name and "Rrr" represents the (singular)
372      * duration range field name. If the range field is not applicable, then
373      * the name of the field is simply the (singular) duration field name.
374      * 
375      * @return field name
376      */
377     public String getName() {
378         return iName;
379     }
380 
381     /**
382      * Get the duration unit of the field.
383      * 
384      * @return duration unit of the field, never null
385      */
386     public abstract DurationFieldType getDurationType();
387 
388     /**
389      * Get the duration range of the field.
390      * 
391      * @return duration range of the field, null if unbounded
392      */
393     public abstract DurationFieldType getRangeDurationType();
394 
395     /**
396      * Gets a suitable field for this type from the given Chronology.
397      *
398      * @param chronology  the chronology to use, null means ISOChronology in default zone
399      * @return a suitable field
400      */
401     public abstract DateTimeField getField(Chronology chronology);
402 
403     /**
404      * Checks whether this field supported in the given Chronology.
405      *
406      * @param chronology  the chronology to use, null means ISOChronology in default zone
407      * @return true if supported
408      */
409     public boolean isSupported(Chronology chronology) {
410         return getField(chronology).isSupported();
411     }
412 
413     /**
414      * Get a suitable debug string.
415      * 
416      * @return debug string
417      */
418     public String toString() {
419         return getName();
420     }
421 
422     private static class StandardDateTimeFieldType extends DateTimeFieldType {
423         /** Serialization version */
424         private static final long serialVersionUID = -9937958251642L;
425 
426         /** The ordinal of the standard field type, for switch statements */
427         private final byte iOrdinal;
428 
429         /** The unit duration of the field. */
430         private final transient DurationFieldType iUnitType;
431         /** The range duration of the field. */
432         private final transient DurationFieldType iRangeType;
433 
434         /**
435          * Constructor.
436          * 
437          * @param name  the name to use
438          * @param ordinal  the byte value for the oridinal index
439          * @param unitType  the unit duration type
440          * @param rangeType  the range duration type
441          */
442         StandardDateTimeFieldType(String name, byte ordinal,
443                                   DurationFieldType unitType, DurationFieldType rangeType) {
444             super(name);
445             iOrdinal = ordinal;
446             iUnitType = unitType;
447             iRangeType = rangeType;
448         }
449 
450         /** @inheritdoc */
451         public DurationFieldType getDurationType() {
452             return iUnitType;
453         }
454 
455         /** @inheritdoc */
456         public DurationFieldType getRangeDurationType() {
457             return iRangeType;
458         }
459 
460         /** @inheritdoc */
461         @Override
462         public boolean equals(Object obj) {
463             if (this == obj) {
464                 return true;
465             }
466             if (obj instanceof StandardDateTimeFieldType) {
467                 return iOrdinal == ((StandardDateTimeFieldType) obj).iOrdinal;
468             }
469             return false;
470         }
471 
472         /** @inheritdoc */
473         @Override
474         public int hashCode() {
475             return (1 << iOrdinal);
476         }
477 
478         /** @inheritdoc */
479         public DateTimeField getField(Chronology chronology) {
480             chronology = DateTimeUtils.getChronology(chronology);
481 
482             switch (iOrdinal) {
483                 case ERA:
484                     return chronology.era();
485                 case YEAR_OF_ERA:
486                     return chronology.yearOfEra();
487                 case CENTURY_OF_ERA:
488                     return chronology.centuryOfEra();
489                 case YEAR_OF_CENTURY:
490                     return chronology.yearOfCentury();
491                 case YEAR:
492                     return chronology.year();
493                 case DAY_OF_YEAR:
494                     return chronology.dayOfYear();
495                 case MONTH_OF_YEAR:
496                     return chronology.monthOfYear();
497                 case DAY_OF_MONTH:
498                     return chronology.dayOfMonth();
499                 case WEEKYEAR_OF_CENTURY:
500                     return chronology.weekyearOfCentury();
501                 case WEEKYEAR:
502                     return chronology.weekyear();
503                 case WEEK_OF_WEEKYEAR:
504                     return chronology.weekOfWeekyear();
505                 case DAY_OF_WEEK:
506                     return chronology.dayOfWeek();
507                 case HALFDAY_OF_DAY:
508                     return chronology.halfdayOfDay();
509                 case HOUR_OF_HALFDAY:
510                     return chronology.hourOfHalfday();
511                 case CLOCKHOUR_OF_HALFDAY:
512                     return chronology.clockhourOfHalfday();
513                 case CLOCKHOUR_OF_DAY:
514                     return chronology.clockhourOfDay();
515                 case HOUR_OF_DAY:
516                     return chronology.hourOfDay();
517                 case MINUTE_OF_DAY:
518                     return chronology.minuteOfDay();
519                 case MINUTE_OF_HOUR:
520                     return chronology.minuteOfHour();
521                 case SECOND_OF_DAY:
522                     return chronology.secondOfDay();
523                 case SECOND_OF_MINUTE:
524                     return chronology.secondOfMinute();
525                 case MILLIS_OF_DAY:
526                     return chronology.millisOfDay();
527                 case MILLIS_OF_SECOND:
528                     return chronology.millisOfSecond();
529                 default:
530                     // Shouldn't happen.
531                     throw new InternalError();
532             }
533         }
534 
535         /**
536          * Ensure a singleton is returned.
537          * 
538          * @return the singleton type
539          */
540         private Object readResolve() {
541             switch (iOrdinal) {
542                 case ERA:
543                     return ERA_TYPE;
544                 case YEAR_OF_ERA:
545                     return YEAR_OF_ERA_TYPE;
546                 case CENTURY_OF_ERA:
547                     return CENTURY_OF_ERA_TYPE;
548                 case YEAR_OF_CENTURY:
549                     return YEAR_OF_CENTURY_TYPE;
550                 case YEAR:
551                     return YEAR_TYPE;
552                 case DAY_OF_YEAR:
553                     return DAY_OF_YEAR_TYPE;
554                 case MONTH_OF_YEAR:
555                     return MONTH_OF_YEAR_TYPE;
556                 case DAY_OF_MONTH:
557                     return DAY_OF_MONTH_TYPE;
558                 case WEEKYEAR_OF_CENTURY:
559                     return WEEKYEAR_OF_CENTURY_TYPE;
560                 case WEEKYEAR:
561                     return WEEKYEAR_TYPE;
562                 case WEEK_OF_WEEKYEAR:
563                     return WEEK_OF_WEEKYEAR_TYPE;
564                 case DAY_OF_WEEK:
565                     return DAY_OF_WEEK_TYPE;
566                 case HALFDAY_OF_DAY:
567                     return HALFDAY_OF_DAY_TYPE;
568                 case HOUR_OF_HALFDAY:
569                     return HOUR_OF_HALFDAY_TYPE;
570                 case CLOCKHOUR_OF_HALFDAY:
571                     return CLOCKHOUR_OF_HALFDAY_TYPE;
572                 case CLOCKHOUR_OF_DAY:
573                     return CLOCKHOUR_OF_DAY_TYPE;
574                 case HOUR_OF_DAY:
575                     return HOUR_OF_DAY_TYPE;
576                 case MINUTE_OF_DAY:
577                     return MINUTE_OF_DAY_TYPE;
578                 case MINUTE_OF_HOUR:
579                     return MINUTE_OF_HOUR_TYPE;
580                 case SECOND_OF_DAY:
581                     return SECOND_OF_DAY_TYPE;
582                 case SECOND_OF_MINUTE:
583                     return SECOND_OF_MINUTE_TYPE;
584                 case MILLIS_OF_DAY:
585                     return MILLIS_OF_DAY_TYPE;
586                 case MILLIS_OF_SECOND:
587                     return MILLIS_OF_SECOND_TYPE;
588                 default:
589                     // Shouldn't happen.
590                     return this;
591             }
592         }
593     }
594 
595 }