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 */
016package org.joda.time;
017
018import java.io.Serializable;
019
020/**
021 * Identifies a field, such as year or minuteOfHour, in a chronology-neutral way.
022 * <p>
023 * A field type defines the type of the field, such as hourOfDay.
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 * It also provides access to the related {@link DurationFieldType}s.
028 * <p>
029 * Instances of <code>DateTimeFieldType</code> are singletons.
030 * They can be compared using <code>==</code>.
031 * <p>
032 * If required, you can create your own field, for example a quarterOfYear.
033 * You must create a subclass of <code>DateTimeFieldType</code> that defines the field type.
034 * This class returns the actual calculation engine from {@link #getField(Chronology)}.
035 * The subclass should implement equals and hashCode.
036 *
037 * @author Stephen Colebourne
038 * @author Brian S O'Neill
039 * @since 1.0
040 */
041public abstract class DateTimeFieldType implements Serializable {
042
043    /** Serialization version */
044    private static final long serialVersionUID = -42615285973990L;
045
046    /** Ordinal values for standard field types. */
047    static final byte
048        ERA = 1,
049        YEAR_OF_ERA = 2,
050        CENTURY_OF_ERA = 3,
051        YEAR_OF_CENTURY = 4,
052        YEAR = 5,
053        DAY_OF_YEAR = 6,
054        MONTH_OF_YEAR = 7,
055        DAY_OF_MONTH = 8,
056        WEEKYEAR_OF_CENTURY = 9,
057        WEEKYEAR = 10,
058        WEEK_OF_WEEKYEAR = 11,
059        DAY_OF_WEEK = 12,
060        HALFDAY_OF_DAY = 13,
061        HOUR_OF_HALFDAY = 14,
062        CLOCKHOUR_OF_HALFDAY = 15,
063        CLOCKHOUR_OF_DAY = 16,
064        HOUR_OF_DAY = 17,
065        MINUTE_OF_DAY = 18,
066        MINUTE_OF_HOUR = 19,
067        SECOND_OF_DAY = 20,
068        SECOND_OF_MINUTE = 21,
069        MILLIS_OF_DAY = 22,
070        MILLIS_OF_SECOND = 23;
071
072    /** The era field type. */
073    private static final DateTimeFieldType ERA_TYPE = new StandardDateTimeFieldType(
074        "era", ERA, DurationFieldType.eras(), null);
075    /** The yearOfEra field type. */
076    private static final DateTimeFieldType YEAR_OF_ERA_TYPE = new StandardDateTimeFieldType(
077        "yearOfEra", YEAR_OF_ERA, DurationFieldType.years(), DurationFieldType.eras());
078    /** The centuryOfEra field type. */
079    private static final DateTimeFieldType CENTURY_OF_ERA_TYPE = new StandardDateTimeFieldType(
080        "centuryOfEra", CENTURY_OF_ERA, DurationFieldType.centuries(), DurationFieldType.eras());
081    /** The yearOfCentury field type. */
082    private static final DateTimeFieldType YEAR_OF_CENTURY_TYPE = new StandardDateTimeFieldType(
083        "yearOfCentury", YEAR_OF_CENTURY, DurationFieldType.years(), DurationFieldType.centuries());
084    /** The year field type. */
085    private static final DateTimeFieldType YEAR_TYPE = new StandardDateTimeFieldType(
086        "year", YEAR, DurationFieldType.years(), null);
087    /** The dayOfYear field type. */
088    private static final DateTimeFieldType DAY_OF_YEAR_TYPE = new StandardDateTimeFieldType(
089        "dayOfYear", DAY_OF_YEAR, DurationFieldType.days(), DurationFieldType.years());
090    /** The monthOfYear field type. */
091    private static final DateTimeFieldType MONTH_OF_YEAR_TYPE = new StandardDateTimeFieldType(
092        "monthOfYear", MONTH_OF_YEAR, DurationFieldType.months(), DurationFieldType.years());
093    /** The dayOfMonth field type. */
094    private static final DateTimeFieldType DAY_OF_MONTH_TYPE = new StandardDateTimeFieldType(
095        "dayOfMonth", DAY_OF_MONTH, DurationFieldType.days(), DurationFieldType.months());
096    /** The weekyearOfCentury field type. */
097    private static final DateTimeFieldType WEEKYEAR_OF_CENTURY_TYPE = new StandardDateTimeFieldType(
098        "weekyearOfCentury", WEEKYEAR_OF_CENTURY, DurationFieldType.weekyears(), DurationFieldType.centuries());
099    /** 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}