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 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     */
041    public 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    }