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 *
036 * @author Stephen Colebourne
037 * @author Brian S O'Neill
038 * @since 1.0
039 */
040 public abstract class DateTimeFieldType implements Serializable {
041
042 /** Serialization version */
043 private static final long serialVersionUID = -42615285973990L;
044
045 /** Ordinal values for standard field types. */
046 static final byte
047 ERA = 1,
048 YEAR_OF_ERA = 2,
049 CENTURY_OF_ERA = 3,
050 YEAR_OF_CENTURY = 4,
051 YEAR = 5,
052 DAY_OF_YEAR = 6,
053 MONTH_OF_YEAR = 7,
054 DAY_OF_MONTH = 8,
055 WEEKYEAR_OF_CENTURY = 9,
056 WEEKYEAR = 10,
057 WEEK_OF_WEEKYEAR = 11,
058 DAY_OF_WEEK = 12,
059 HALFDAY_OF_DAY = 13,
060 HOUR_OF_HALFDAY = 14,
061 CLOCKHOUR_OF_HALFDAY = 15,
062 CLOCKHOUR_OF_DAY = 16,
063 HOUR_OF_DAY = 17,
064 MINUTE_OF_DAY = 18,
065 MINUTE_OF_HOUR = 19,
066 SECOND_OF_DAY = 20,
067 SECOND_OF_MINUTE = 21,
068 MILLIS_OF_DAY = 22,
069 MILLIS_OF_SECOND = 23;
070
071 /** The era field type. */
072 private static final DateTimeFieldType ERA_TYPE = new StandardDateTimeFieldType(
073 "era", ERA, DurationFieldType.eras(), null);
074 /** The yearOfEra field type. */
075 private static final DateTimeFieldType YEAR_OF_ERA_TYPE = new StandardDateTimeFieldType(
076 "yearOfEra", YEAR_OF_ERA, DurationFieldType.years(), DurationFieldType.eras());
077 /** The centuryOfEra field type. */
078 private static final DateTimeFieldType CENTURY_OF_ERA_TYPE = new StandardDateTimeFieldType(
079 "centuryOfEra", CENTURY_OF_ERA, DurationFieldType.centuries(), DurationFieldType.eras());
080 /** The yearOfCentury field type. */
081 private static final DateTimeFieldType YEAR_OF_CENTURY_TYPE = new StandardDateTimeFieldType(
082 "yearOfCentury", YEAR_OF_CENTURY, DurationFieldType.years(), DurationFieldType.centuries());
083 /** The year field type. */
084 private static final DateTimeFieldType YEAR_TYPE = new StandardDateTimeFieldType(
085 "year", YEAR, DurationFieldType.years(), null);
086 /** The dayOfYear field type. */
087 private static final DateTimeFieldType DAY_OF_YEAR_TYPE = new StandardDateTimeFieldType(
088 "dayOfYear", DAY_OF_YEAR, DurationFieldType.days(), DurationFieldType.years());
089 /** The monthOfYear field type. */
090 private static final DateTimeFieldType MONTH_OF_YEAR_TYPE = new StandardDateTimeFieldType(
091 "monthOfYear", MONTH_OF_YEAR, DurationFieldType.months(), DurationFieldType.years());
092 /** The dayOfMonth field type. */
093 private static final DateTimeFieldType DAY_OF_MONTH_TYPE = new StandardDateTimeFieldType(
094 "dayOfMonth", DAY_OF_MONTH, DurationFieldType.days(), DurationFieldType.months());
095 /** The weekyearOfCentury field type. */
096 private static final DateTimeFieldType WEEKYEAR_OF_CENTURY_TYPE = new StandardDateTimeFieldType(
097 "weekyearOfCentury", WEEKYEAR_OF_CENTURY, DurationFieldType.weekyears(), DurationFieldType.centuries());
098 /** The weekyear field type. */
099 private static final DateTimeFieldType WEEKYEAR_TYPE = new StandardDateTimeFieldType(
100 "weekyear", WEEKYEAR, DurationFieldType.weekyears(), null);
101 /** The weekOfWeekyear field type. */
102 private static final DateTimeFieldType WEEK_OF_WEEKYEAR_TYPE = new StandardDateTimeFieldType(
103 "weekOfWeekyear", WEEK_OF_WEEKYEAR, DurationFieldType.weeks(), DurationFieldType.weekyears());
104 /** The dayOfWeek field type. */
105 private static final DateTimeFieldType DAY_OF_WEEK_TYPE = new StandardDateTimeFieldType(
106 "dayOfWeek", DAY_OF_WEEK, DurationFieldType.days(), DurationFieldType.weeks());
107
108 /** The halfday field type. */
109 private static final DateTimeFieldType HALFDAY_OF_DAY_TYPE = new StandardDateTimeFieldType(
110 "halfdayOfDay", HALFDAY_OF_DAY, DurationFieldType.halfdays(), DurationFieldType.days());
111 /** The hourOfHalfday field type. */
112 private static final DateTimeFieldType HOUR_OF_HALFDAY_TYPE = new StandardDateTimeFieldType(
113 "hourOfHalfday", HOUR_OF_HALFDAY, DurationFieldType.hours(), DurationFieldType.halfdays());
114 /** The clockhourOfHalfday field type. */
115 private static final DateTimeFieldType CLOCKHOUR_OF_HALFDAY_TYPE = new StandardDateTimeFieldType(
116 "clockhourOfHalfday", CLOCKHOUR_OF_HALFDAY, DurationFieldType.hours(), DurationFieldType.halfdays());
117 /** The clockhourOfDay field type. */
118 private static final DateTimeFieldType CLOCKHOUR_OF_DAY_TYPE = new StandardDateTimeFieldType(
119 "clockhourOfDay", CLOCKHOUR_OF_DAY, DurationFieldType.hours(), DurationFieldType.days());
120 /** The hourOfDay field type. */
121 private static final DateTimeFieldType HOUR_OF_DAY_TYPE = new StandardDateTimeFieldType(
122 "hourOfDay", HOUR_OF_DAY, DurationFieldType.hours(), DurationFieldType.days());
123 /** The minuteOfDay field type. */
124 private static final DateTimeFieldType MINUTE_OF_DAY_TYPE = new StandardDateTimeFieldType(
125 "minuteOfDay", MINUTE_OF_DAY, DurationFieldType.minutes(), DurationFieldType.days());
126 /** The minuteOfHour field type. */
127 private static final DateTimeFieldType MINUTE_OF_HOUR_TYPE = new StandardDateTimeFieldType(
128 "minuteOfHour", MINUTE_OF_HOUR, DurationFieldType.minutes(), DurationFieldType.hours());
129 /** The secondOfDay field type. */
130 private static final DateTimeFieldType SECOND_OF_DAY_TYPE = new StandardDateTimeFieldType(
131 "secondOfDay", SECOND_OF_DAY, DurationFieldType.seconds(), DurationFieldType.days());
132 /** The secondOfMinute field type. */
133 private static final DateTimeFieldType SECOND_OF_MINUTE_TYPE = new StandardDateTimeFieldType(
134 "secondOfMinute", SECOND_OF_MINUTE, DurationFieldType.seconds(), DurationFieldType.minutes());
135 /** The millisOfDay field type. */
136 private static final DateTimeFieldType MILLIS_OF_DAY_TYPE = new StandardDateTimeFieldType(
137 "millisOfDay", MILLIS_OF_DAY, DurationFieldType.millis(), DurationFieldType.days());
138 /** The millisOfSecond field type. */
139 private static final DateTimeFieldType MILLIS_OF_SECOND_TYPE = new StandardDateTimeFieldType(
140 "millisOfSecond", MILLIS_OF_SECOND, DurationFieldType.millis(), DurationFieldType.seconds());
141
142 /** The name of the field. */
143 private final String iName;
144
145 //-----------------------------------------------------------------------
146 /**
147 * Constructor.
148 *
149 * @param name the name to use
150 */
151 protected DateTimeFieldType(String name) {
152 super();
153 iName = name;
154 }
155
156 //-----------------------------------------------------------------------
157 /**
158 * Get the millis of second field type.
159 *
160 * @return the DateTimeFieldType constant
161 */
162 public static DateTimeFieldType millisOfSecond() {
163 return MILLIS_OF_SECOND_TYPE;
164 }
165
166 /**
167 * Get the millis of day field type.
168 *
169 * @return the DateTimeFieldType constant
170 */
171 public static DateTimeFieldType millisOfDay() {
172 return MILLIS_OF_DAY_TYPE;
173 }
174
175 /**
176 * Get the second of minute field type.
177 *
178 * @return the DateTimeFieldType constant
179 */
180 public static DateTimeFieldType secondOfMinute() {
181 return SECOND_OF_MINUTE_TYPE;
182 }
183
184 /**
185 * Get the second of day field type.
186 *
187 * @return the DateTimeFieldType constant
188 */
189 public static DateTimeFieldType secondOfDay() {
190 return SECOND_OF_DAY_TYPE;
191 }
192
193 /**
194 * Get the minute of hour field type.
195 *
196 * @return the DateTimeFieldType constant
197 */
198 public static DateTimeFieldType minuteOfHour() {
199 return MINUTE_OF_HOUR_TYPE;
200 }
201
202 /**
203 * Get the minute of day field type.
204 *
205 * @return the DateTimeFieldType constant
206 */
207 public static DateTimeFieldType minuteOfDay() {
208 return MINUTE_OF_DAY_TYPE;
209 }
210
211 /**
212 * Get the hour of day (0-23) field type.
213 *
214 * @return the DateTimeFieldType constant
215 */
216 public static DateTimeFieldType hourOfDay() {
217 return HOUR_OF_DAY_TYPE;
218 }
219
220 /**
221 * Get the hour of day (offset to 1-24) field type.
222 *
223 * @return the DateTimeFieldType constant
224 */
225 public static DateTimeFieldType clockhourOfDay() {
226 return CLOCKHOUR_OF_DAY_TYPE;
227 }
228
229 /**
230 * Get the hour of am/pm (0-11) field type.
231 *
232 * @return the DateTimeFieldType constant
233 */
234 public static DateTimeFieldType hourOfHalfday() {
235 return HOUR_OF_HALFDAY_TYPE;
236 }
237
238 /**
239 * Get the hour of am/pm (offset to 1-12) field type.
240 *
241 * @return the DateTimeFieldType constant
242 */
243 public static DateTimeFieldType clockhourOfHalfday() {
244 return CLOCKHOUR_OF_HALFDAY_TYPE;
245 }
246
247 /**
248 * Get the AM(0) PM(1) field type.
249 *
250 * @return the DateTimeFieldType constant
251 */
252 public static DateTimeFieldType halfdayOfDay() {
253 return HALFDAY_OF_DAY_TYPE;
254 }
255
256 //-----------------------------------------------------------------------
257 /**
258 * Get the day of week field type.
259 *
260 * @return the DateTimeFieldType constant
261 */
262 public static DateTimeFieldType dayOfWeek() {
263 return DAY_OF_WEEK_TYPE;
264 }
265
266 /**
267 * Get the day of month field type.
268 *
269 * @return the DateTimeFieldType constant
270 */
271 public static DateTimeFieldType dayOfMonth() {
272 return DAY_OF_MONTH_TYPE;
273 }
274
275 /**
276 * Get the day of year field type.
277 *
278 * @return the DateTimeFieldType constant
279 */
280 public static DateTimeFieldType dayOfYear() {
281 return DAY_OF_YEAR_TYPE;
282 }
283
284 /**
285 * Get the week of a week based year field type.
286 *
287 * @return the DateTimeFieldType constant
288 */
289 public static DateTimeFieldType weekOfWeekyear() {
290 return WEEK_OF_WEEKYEAR_TYPE;
291 }
292
293 /**
294 * Get the year of a week based year field type.
295 *
296 * @return the DateTimeFieldType constant
297 */
298 public static DateTimeFieldType weekyear() {
299 return WEEKYEAR_TYPE;
300 }
301
302 /**
303 * Get the year of a week based year within a century field type.
304 *
305 * @return the DateTimeFieldType constant
306 */
307 public static DateTimeFieldType weekyearOfCentury() {
308 return WEEKYEAR_OF_CENTURY_TYPE;
309 }
310
311 /**
312 * Get the month of year field type.
313 *
314 * @return the DateTimeFieldType constant
315 */
316 public static DateTimeFieldType monthOfYear() {
317 return MONTH_OF_YEAR_TYPE;
318 }
319
320 /**
321 * Get the year field type.
322 *
323 * @return the DateTimeFieldType constant
324 */
325 public static DateTimeFieldType year() {
326 return YEAR_TYPE;
327 }
328
329 /**
330 * Get the year of era field type.
331 *
332 * @return the DateTimeFieldType constant
333 */
334 public static DateTimeFieldType yearOfEra() {
335 return YEAR_OF_ERA_TYPE;
336 }
337
338 /**
339 * Get the year of century field type.
340 *
341 * @return the DateTimeFieldType constant
342 */
343 public static DateTimeFieldType yearOfCentury() {
344 return YEAR_OF_CENTURY_TYPE;
345 }
346
347 /**
348 * Get the century of era field type.
349 *
350 * @return the DateTimeFieldType constant
351 */
352 public static DateTimeFieldType centuryOfEra() {
353 return CENTURY_OF_ERA_TYPE;
354 }
355
356 /**
357 * Get the era field type.
358 *
359 * @return the DateTimeFieldType constant
360 */
361 public static DateTimeFieldType era() {
362 return ERA_TYPE;
363 }
364
365 //-----------------------------------------------------------------------
366 /**
367 * Get the name of the field.
368 * <p>
369 * By convention, names follow a pattern of "dddOfRrr", where "ddd" represents
370 * the (singular) duration unit field name and "Rrr" represents the (singular)
371 * duration range field name. If the range field is not applicable, then
372 * the name of the field is simply the (singular) duration field name.
373 *
374 * @return field name
375 */
376 public String getName() {
377 return iName;
378 }
379
380 /**
381 * Get the duration unit of the field.
382 *
383 * @return duration unit of the field, never null
384 */
385 public abstract DurationFieldType getDurationType();
386
387 /**
388 * Get the duration range of the field.
389 *
390 * @return duration range of the field, null if unbounded
391 */
392 public abstract DurationFieldType getRangeDurationType();
393
394 /**
395 * Gets a suitable field for this type from the given Chronology.
396 *
397 * @param chronology the chronology to use, null means ISOChronology in default zone
398 * @return a suitable field
399 */
400 public abstract DateTimeField getField(Chronology chronology);
401
402 /**
403 * Checks whether this field supported in the given Chronology.
404 *
405 * @param chronology the chronology to use, null means ISOChronology in default zone
406 * @return true if supported
407 */
408 public boolean isSupported(Chronology chronology) {
409 return getField(chronology).isSupported();
410 }
411
412 /**
413 * Get a suitable debug string.
414 *
415 * @return debug string
416 */
417 public String toString() {
418 return getName();
419 }
420
421 private static class StandardDateTimeFieldType extends DateTimeFieldType {
422 /** Serialization version */
423 private static final long serialVersionUID = -9937958251642L;
424
425 /** The ordinal of the standard field type, for switch statements */
426 private final byte iOrdinal;
427
428 /** The unit duration of the field. */
429 private final transient DurationFieldType iUnitType;
430 /** The range duration of the field. */
431 private final transient DurationFieldType iRangeType;
432
433 /**
434 * Constructor.
435 *
436 * @param name the name to use
437 * @param ordinal the byte value for the oridinal index
438 * @param unitType the unit duration type
439 * @param rangeType the range duration type
440 */
441 StandardDateTimeFieldType(String name, byte ordinal,
442 DurationFieldType unitType, DurationFieldType rangeType) {
443 super(name);
444 iOrdinal = ordinal;
445 iUnitType = unitType;
446 iRangeType = rangeType;
447 }
448
449 /** @inheritdoc */
450 public DurationFieldType getDurationType() {
451 return iUnitType;
452 }
453
454 /** @inheritdoc */
455 public DurationFieldType getRangeDurationType() {
456 return iRangeType;
457 }
458
459 /** @inheritdoc */
460 public DateTimeField getField(Chronology chronology) {
461 chronology = DateTimeUtils.getChronology(chronology);
462
463 switch (iOrdinal) {
464 case ERA:
465 return chronology.era();
466 case YEAR_OF_ERA:
467 return chronology.yearOfEra();
468 case CENTURY_OF_ERA:
469 return chronology.centuryOfEra();
470 case YEAR_OF_CENTURY:
471 return chronology.yearOfCentury();
472 case YEAR:
473 return chronology.year();
474 case DAY_OF_YEAR:
475 return chronology.dayOfYear();
476 case MONTH_OF_YEAR:
477 return chronology.monthOfYear();
478 case DAY_OF_MONTH:
479 return chronology.dayOfMonth();
480 case WEEKYEAR_OF_CENTURY:
481 return chronology.weekyearOfCentury();
482 case WEEKYEAR:
483 return chronology.weekyear();
484 case WEEK_OF_WEEKYEAR:
485 return chronology.weekOfWeekyear();
486 case DAY_OF_WEEK:
487 return chronology.dayOfWeek();
488 case HALFDAY_OF_DAY:
489 return chronology.halfdayOfDay();
490 case HOUR_OF_HALFDAY:
491 return chronology.hourOfHalfday();
492 case CLOCKHOUR_OF_HALFDAY:
493 return chronology.clockhourOfHalfday();
494 case CLOCKHOUR_OF_DAY:
495 return chronology.clockhourOfDay();
496 case HOUR_OF_DAY:
497 return chronology.hourOfDay();
498 case MINUTE_OF_DAY:
499 return chronology.minuteOfDay();
500 case MINUTE_OF_HOUR:
501 return chronology.minuteOfHour();
502 case SECOND_OF_DAY:
503 return chronology.secondOfDay();
504 case SECOND_OF_MINUTE:
505 return chronology.secondOfMinute();
506 case MILLIS_OF_DAY:
507 return chronology.millisOfDay();
508 case MILLIS_OF_SECOND:
509 return chronology.millisOfSecond();
510 default:
511 // Shouldn't happen.
512 throw new InternalError();
513 }
514 }
515
516 /**
517 * Ensure a singleton is returned.
518 *
519 * @return the singleton type
520 */
521 private Object readResolve() {
522 switch (iOrdinal) {
523 case ERA:
524 return ERA_TYPE;
525 case YEAR_OF_ERA:
526 return YEAR_OF_ERA_TYPE;
527 case CENTURY_OF_ERA:
528 return CENTURY_OF_ERA_TYPE;
529 case YEAR_OF_CENTURY:
530 return YEAR_OF_CENTURY_TYPE;
531 case YEAR:
532 return YEAR_TYPE;
533 case DAY_OF_YEAR:
534 return DAY_OF_YEAR_TYPE;
535 case MONTH_OF_YEAR:
536 return MONTH_OF_YEAR_TYPE;
537 case DAY_OF_MONTH:
538 return DAY_OF_MONTH_TYPE;
539 case WEEKYEAR_OF_CENTURY:
540 return WEEKYEAR_OF_CENTURY_TYPE;
541 case WEEKYEAR:
542 return WEEKYEAR_TYPE;
543 case WEEK_OF_WEEKYEAR:
544 return WEEK_OF_WEEKYEAR_TYPE;
545 case DAY_OF_WEEK:
546 return DAY_OF_WEEK_TYPE;
547 case HALFDAY_OF_DAY:
548 return HALFDAY_OF_DAY_TYPE;
549 case HOUR_OF_HALFDAY:
550 return HOUR_OF_HALFDAY_TYPE;
551 case CLOCKHOUR_OF_HALFDAY:
552 return CLOCKHOUR_OF_HALFDAY_TYPE;
553 case CLOCKHOUR_OF_DAY:
554 return CLOCKHOUR_OF_DAY_TYPE;
555 case HOUR_OF_DAY:
556 return HOUR_OF_DAY_TYPE;
557 case MINUTE_OF_DAY:
558 return MINUTE_OF_DAY_TYPE;
559 case MINUTE_OF_HOUR:
560 return MINUTE_OF_HOUR_TYPE;
561 case SECOND_OF_DAY:
562 return SECOND_OF_DAY_TYPE;
563 case SECOND_OF_MINUTE:
564 return SECOND_OF_MINUTE_TYPE;
565 case MILLIS_OF_DAY:
566 return MILLIS_OF_DAY_TYPE;
567 case MILLIS_OF_SECOND:
568 return MILLIS_OF_SECOND_TYPE;
569 default:
570 // Shouldn't happen.
571 return this;
572 }
573 }
574 }
575
576 }