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 }