1 16 package org.joda.time.format; 17 18 import java.util.Arrays ; 19 import java.util.Locale ; 20 21 import org.joda.time.Chronology; 22 import org.joda.time.DateTimeField; 23 import org.joda.time.DateTimeFieldType; 24 import org.joda.time.DateTimeUtils; 25 import org.joda.time.DateTimeZone; 26 import org.joda.time.DurationField; 27 import org.joda.time.IllegalFieldValueException; 28 29 54 public class DateTimeParserBucket { 55 56 57 private final Chronology iChrono; 58 private final long iMillis; 59 60 private DateTimeZone iZone; 62 private int iOffset; 63 64 private Locale iLocale; 65 66 private Integer iPivotYear; 67 68 private SavedField[] iSavedFields = new SavedField[8]; 69 private int iSavedFieldsCount; 70 private boolean iSavedFieldsShared; 71 72 private Object iSavedState; 73 74 81 public DateTimeParserBucket(long instantLocal, Chronology chrono, Locale locale) { 82 this(instantLocal, chrono, locale, null); 83 } 84 85 95 public DateTimeParserBucket(long instantLocal, Chronology chrono, Locale locale, Integer pivotYear) { 96 super(); 97 chrono = DateTimeUtils.getChronology(chrono); 98 iMillis = instantLocal; 99 iChrono = chrono.withUTC(); 100 iLocale = (locale == null ? Locale.getDefault() : locale); 101 setZone(chrono.getZone()); 102 iPivotYear = pivotYear; 103 } 104 105 109 public Chronology getChronology() { 110 return iChrono; 111 } 112 113 119 public Locale getLocale() { 120 return iLocale; 121 } 122 123 128 public DateTimeZone getZone() { 129 return iZone; 130 } 131 132 138 public void setZone(DateTimeZone zone) { 139 iSavedState = null; 140 iZone = zone == DateTimeZone.UTC ? null : zone; 141 iOffset = 0; 142 } 143 144 149 public int getOffset() { 150 return iOffset; 151 } 152 153 157 public void setOffset(int offset) { 158 iSavedState = null; 159 iOffset = offset; 160 iZone = null; 161 } 162 163 172 public Integer getPivotYear() { 173 return iPivotYear; 174 } 175 176 185 public void setPivotYear(Integer pivotYear) { 186 iPivotYear = pivotYear; 187 } 188 189 196 public void saveField(DateTimeField field, int value) { 197 saveField(new SavedField(field, value)); 198 } 199 200 206 public void saveField(DateTimeFieldType fieldType, int value) { 207 saveField(new SavedField(fieldType.getField(iChrono), value)); 208 } 209 210 217 public void saveField(DateTimeFieldType fieldType, String text, Locale locale) { 218 saveField(new SavedField(fieldType.getField(iChrono), text, locale)); 219 } 220 221 private void saveField(SavedField field) { 222 SavedField[] savedFields = iSavedFields; 223 int savedFieldsCount = iSavedFieldsCount; 224 225 if (savedFieldsCount == savedFields.length || iSavedFieldsShared) { 226 SavedField[] newArray = new SavedField 228 [savedFieldsCount == savedFields.length ? savedFieldsCount * 2 : savedFields.length]; 229 System.arraycopy(savedFields, 0, newArray, 0, savedFieldsCount); 230 iSavedFields = savedFields = newArray; 231 iSavedFieldsShared = false; 232 } 233 234 iSavedState = null; 235 savedFields[savedFieldsCount] = field; 236 iSavedFieldsCount = savedFieldsCount + 1; 237 } 238 239 246 public Object saveState() { 247 if (iSavedState == null) { 248 iSavedState = new SavedState(); 249 } 250 return iSavedState; 251 } 252 253 261 public boolean restoreState(Object savedState) { 262 if (savedState instanceof SavedState) { 263 if (((SavedState) savedState).restoreState(this)) { 264 iSavedState = savedState; 265 return true; 266 } 267 } 268 return false; 269 } 270 271 278 public long computeMillis() { 279 return computeMillis(false, null); 280 } 281 282 290 public long computeMillis(boolean resetFields) { 291 return computeMillis(resetFields, null); 292 } 293 294 304 public long computeMillis(boolean resetFields, String text) { 305 SavedField[] savedFields = iSavedFields; 306 int count = iSavedFieldsCount; 307 if (iSavedFieldsShared) { 308 iSavedFields = savedFields = (SavedField[])iSavedFields.clone(); 309 iSavedFieldsShared = false; 310 } 311 sort(savedFields, count); 312 313 long millis = iMillis; 314 try { 315 for (int i=0; i<count; i++) { 316 millis = savedFields[i].set(millis, resetFields); 317 } 318 } catch (IllegalFieldValueException e) { 319 if (text != null) { 320 e.prependMessage("Cannot parse \"" + text + '"'); 321 } 322 throw e; 323 } 324 325 if (iZone == null) { 326 millis -= iOffset; 327 } else { 328 int offset = iZone.getOffsetFromLocal(millis); 329 millis -= offset; 330 if (offset != iZone.getOffset(millis)) { 331 String message = 332 "Illegal instant due to time zone offset transition (" + iZone + ')'; 333 if (text != null) { 334 message = "Cannot parse \"" + text + "\": " + message; 335 } 336 throw new IllegalArgumentException (message); 337 } 338 } 339 340 return millis; 341 } 342 343 361 private static void sort(Comparable [] array, int high) { 362 if (high > 10) { 363 Arrays.sort(array, 0, high); 364 } else { 365 for (int i=0; i<high; i++) { 366 for (int j=i; j>0 && (array[j-1]).compareTo(array[j])>0; j--) { 367 Comparable t = array[j]; 368 array[j] = array[j-1]; 369 array[j-1] = t; 370 } 371 } 372 } 373 } 374 375 class SavedState { 376 final DateTimeZone iZone; 377 final int iOffset; 378 final SavedField[] iSavedFields; 379 final int iSavedFieldsCount; 380 381 SavedState() { 382 this.iZone = DateTimeParserBucket.this.iZone; 383 this.iOffset = DateTimeParserBucket.this.iOffset; 384 this.iSavedFields = DateTimeParserBucket.this.iSavedFields; 385 this.iSavedFieldsCount = DateTimeParserBucket.this.iSavedFieldsCount; 386 } 387 388 boolean restoreState(DateTimeParserBucket enclosing) { 389 if (enclosing != DateTimeParserBucket.this) { 390 return false; 391 } 392 enclosing.iZone = this.iZone; 393 enclosing.iOffset = this.iOffset; 394 enclosing.iSavedFields = this.iSavedFields; 395 if (this.iSavedFieldsCount < enclosing.iSavedFieldsCount) { 396 enclosing.iSavedFieldsShared = true; 401 } 402 enclosing.iSavedFieldsCount = this.iSavedFieldsCount; 403 return true; 404 } 405 } 406 407 static class SavedField implements Comparable { 408 final DateTimeField iField; 409 final int iValue; 410 final String iText; 411 final Locale iLocale; 412 413 SavedField(DateTimeField field, int value) { 414 iField = field; 415 iValue = value; 416 iText = null; 417 iLocale = null; 418 } 419 420 SavedField(DateTimeField field, String text, Locale locale) { 421 iField = field; 422 iValue = 0; 423 iText = text; 424 iLocale = locale; 425 } 426 427 long set(long millis, boolean reset) { 428 if (iText == null) { 429 millis = iField.set(millis, iValue); 430 } else { 431 millis = iField.set(millis, iText, iLocale); 432 } 433 if (reset) { 434 millis = iField.roundFloor(millis); 435 } 436 return millis; 437 } 438 439 444 public int compareTo(Object obj) { 445 DateTimeField other = ((SavedField)obj).iField; 446 int result = compareReverse 447 (iField.getRangeDurationField(), other.getRangeDurationField()); 448 if (result != 0) { 449 return result; 450 } 451 return compareReverse 452 (iField.getDurationField(), other.getDurationField()); 453 } 454 455 private int compareReverse(DurationField a, DurationField b) { 456 if (a == null || !a.isSupported()) { 457 if (b == null || !b.isSupported()) { 458 return 0; 459 } 460 return -1; 461 } 462 if (b == null || !b.isSupported()) { 463 return 1; 464 } 465 return -a.compareTo(b); 466 } 467 } 468 } 469 | Popular Tags |