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 duration field, such as years or minutes, in a chronology-neutral way. 022 * <p> 023 * A duration field type defines the type of the field, such as hours. 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 * <p> 028 * Instances of <code>DurationFieldType</code> are singletons. 029 * They can be compared using <code>==</code>. 030 * <p> 031 * If required, you can create your own field, for example a quarters. 032 * You must create a subclass of <code>DurationFieldType</code> that defines the field type. 033 * This class returns the actual calculation engine from {@link #getField(Chronology)}. 034 * 035 * @author Stephen Colebourne 036 * @author Brian S O'Neill 037 * @since 1.0 038 */ 039 public abstract class DurationFieldType implements Serializable { 040 041 /** Serialization version */ 042 private static final long serialVersionUID = 8765135187319L; 043 044 // Ordinals for standard field types. 045 static final byte 046 ERAS = 1, 047 CENTURIES = 2, 048 WEEKYEARS = 3, 049 YEARS = 4, 050 MONTHS = 5, 051 WEEKS = 6, 052 DAYS = 7, 053 HALFDAYS = 8, 054 HOURS = 9, 055 MINUTES = 10, 056 SECONDS = 11, 057 MILLIS = 12; 058 059 /** The eras field type. */ 060 static final DurationFieldType ERAS_TYPE = new StandardDurationFieldType("eras", ERAS); 061 /** The centuries field type. */ 062 static final DurationFieldType CENTURIES_TYPE = new StandardDurationFieldType("centuries", CENTURIES); 063 /** The weekyears field type. */ 064 static final DurationFieldType WEEKYEARS_TYPE = new StandardDurationFieldType("weekyears", WEEKYEARS); 065 /** The years field type. */ 066 static final DurationFieldType YEARS_TYPE = new StandardDurationFieldType("years", YEARS); 067 /** The months field type. */ 068 static final DurationFieldType MONTHS_TYPE = new StandardDurationFieldType("months", MONTHS); 069 /** The weeks field type. */ 070 static final DurationFieldType WEEKS_TYPE = new StandardDurationFieldType("weeks", WEEKS); 071 /** The days field type. */ 072 static final DurationFieldType DAYS_TYPE = new StandardDurationFieldType("days", DAYS); 073 /** The halfdays field type. */ 074 static final DurationFieldType HALFDAYS_TYPE = new StandardDurationFieldType("halfdays", HALFDAYS); 075 /** The hours field type. */ 076 static final DurationFieldType HOURS_TYPE = new StandardDurationFieldType("hours", HOURS); 077 /** The minutes field type. */ 078 static final DurationFieldType MINUTES_TYPE = new StandardDurationFieldType("minutes", MINUTES); 079 /** The seconds field type. */ 080 static final DurationFieldType SECONDS_TYPE = new StandardDurationFieldType("seconds", SECONDS); 081 /** The millis field type. */ 082 static final DurationFieldType MILLIS_TYPE = new StandardDurationFieldType("millis", MILLIS); 083 084 /** The name of the field type. */ 085 private final String iName; 086 087 //----------------------------------------------------------------------- 088 /** 089 * Constructor. 090 * 091 * @param name the name to use, which by convention, are plural. 092 */ 093 protected DurationFieldType(String name) { 094 super(); 095 iName = name; 096 } 097 098 //----------------------------------------------------------------------- 099 /** 100 * Get the millis field type. 101 * 102 * @return the DateTimeFieldType constant 103 */ 104 public static DurationFieldType millis() { 105 return MILLIS_TYPE; 106 } 107 108 /** 109 * Get the seconds field type. 110 * 111 * @return the DateTimeFieldType constant 112 */ 113 public static DurationFieldType seconds() { 114 return SECONDS_TYPE; 115 } 116 117 /** 118 * Get the minutes field type. 119 * 120 * @return the DateTimeFieldType constant 121 */ 122 public static DurationFieldType minutes() { 123 return MINUTES_TYPE; 124 } 125 126 /** 127 * Get the hours field type. 128 * 129 * @return the DateTimeFieldType constant 130 */ 131 public static DurationFieldType hours() { 132 return HOURS_TYPE; 133 } 134 135 /** 136 * Get the halfdays field type. 137 * 138 * @return the DateTimeFieldType constant 139 */ 140 public static DurationFieldType halfdays() { 141 return HALFDAYS_TYPE; 142 } 143 144 //----------------------------------------------------------------------- 145 /** 146 * Get the days field type. 147 * 148 * @return the DateTimeFieldType constant 149 */ 150 public static DurationFieldType days() { 151 return DAYS_TYPE; 152 } 153 154 /** 155 * Get the weeks field type. 156 * 157 * @return the DateTimeFieldType constant 158 */ 159 public static DurationFieldType weeks() { 160 return WEEKS_TYPE; 161 } 162 163 /** 164 * Get the weekyears field type. 165 * 166 * @return the DateTimeFieldType constant 167 */ 168 public static DurationFieldType weekyears() { 169 return WEEKYEARS_TYPE; 170 } 171 172 /** 173 * Get the months field type. 174 * 175 * @return the DateTimeFieldType constant 176 */ 177 public static DurationFieldType months() { 178 return MONTHS_TYPE; 179 } 180 181 /** 182 * Get the years field type. 183 * 184 * @return the DateTimeFieldType constant 185 */ 186 public static DurationFieldType years() { 187 return YEARS_TYPE; 188 } 189 190 /** 191 * Get the centuries field type. 192 * 193 * @return the DateTimeFieldType constant 194 */ 195 public static DurationFieldType centuries() { 196 return CENTURIES_TYPE; 197 } 198 199 /** 200 * Get the eras field type. 201 * 202 * @return the DateTimeFieldType constant 203 */ 204 public static DurationFieldType eras() { 205 return ERAS_TYPE; 206 } 207 208 //----------------------------------------------------------------------- 209 /** 210 * Get the name of the field. 211 * By convention, names are plural. 212 * 213 * @return field name 214 */ 215 public String getName() { 216 return iName; 217 } 218 219 /** 220 * Gets a suitable field for this type from the given Chronology. 221 * 222 * @param chronology the chronology to use, null means ISOChronology in default zone 223 * @return a suitable field 224 */ 225 public abstract DurationField getField(Chronology chronology); 226 227 /** 228 * Checks whether this field supported in the given Chronology. 229 * 230 * @param chronology the chronology to use, null means ISOChronology in default zone 231 * @return true if supported 232 */ 233 public boolean isSupported(Chronology chronology) { 234 return getField(chronology).isSupported(); 235 } 236 237 /** 238 * Get a suitable debug string. 239 * 240 * @return debug string 241 */ 242 public String toString() { 243 return getName(); 244 } 245 246 private static class StandardDurationFieldType extends DurationFieldType { 247 /** Serialization version */ 248 private static final long serialVersionUID = 31156755687123L; 249 250 /** The ordinal of the standard field type, for switch statements */ 251 private final byte iOrdinal; 252 253 /** 254 * Constructor. 255 * 256 * @param name the name to use 257 */ 258 StandardDurationFieldType(String name, byte ordinal) { 259 super(name); 260 iOrdinal = ordinal; 261 } 262 263 /** @inheritdoc */ 264 @Override 265 public boolean equals(Object obj) { 266 if (this == obj) { 267 return true; 268 } 269 if (obj instanceof StandardDurationFieldType) { 270 return iOrdinal == ((StandardDurationFieldType) obj).iOrdinal; 271 } 272 return false; 273 } 274 275 /** @inheritdoc */ 276 @Override 277 public int hashCode() { 278 return (1 << iOrdinal); 279 } 280 281 public DurationField getField(Chronology chronology) { 282 chronology = DateTimeUtils.getChronology(chronology); 283 284 switch (iOrdinal) { 285 case ERAS: 286 return chronology.eras(); 287 case CENTURIES: 288 return chronology.centuries(); 289 case WEEKYEARS: 290 return chronology.weekyears(); 291 case YEARS: 292 return chronology.years(); 293 case MONTHS: 294 return chronology.months(); 295 case WEEKS: 296 return chronology.weeks(); 297 case DAYS: 298 return chronology.days(); 299 case HALFDAYS: 300 return chronology.halfdays(); 301 case HOURS: 302 return chronology.hours(); 303 case MINUTES: 304 return chronology.minutes(); 305 case SECONDS: 306 return chronology.seconds(); 307 case MILLIS: 308 return chronology.millis(); 309 default: 310 // Shouldn't happen. 311 throw new InternalError(); 312 } 313 } 314 315 /** 316 * Ensure a singleton is returned. 317 * 318 * @return the singleton type 319 */ 320 private Object readResolve() { 321 switch (iOrdinal) { 322 case ERAS: 323 return ERAS_TYPE; 324 case CENTURIES: 325 return CENTURIES_TYPE; 326 case WEEKYEARS: 327 return WEEKYEARS_TYPE; 328 case YEARS: 329 return YEARS_TYPE; 330 case MONTHS: 331 return MONTHS_TYPE; 332 case WEEKS: 333 return WEEKS_TYPE; 334 case DAYS: 335 return DAYS_TYPE; 336 case HALFDAYS: 337 return HALFDAYS_TYPE; 338 case HOURS: 339 return HOURS_TYPE; 340 case MINUTES: 341 return MINUTES_TYPE; 342 case SECONDS: 343 return SECONDS_TYPE; 344 case MILLIS: 345 return MILLIS_TYPE; 346 default: 347 // Shouldn't happen. 348 return this; 349 } 350 } 351 } 352 }