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 }
596