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