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