1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package java.text; 19 20 import java.io.InvalidObjectException; 21 import java.util.Calendar; 22 import java.util.Date; 23 import java.util.Hashtable; 24 import java.util.Locale; 25 import java.util.TimeZone; 26 import libcore.icu.ICU; 27 import libcore.icu.LocaleData; 28 29 /** 30 * Formats or parses dates and times. 31 * 32 * <p>This class provides factories for obtaining instances configured for a specific locale. 33 * The most common subclass is {@link SimpleDateFormat}. 34 * 35 * <h4>Sample Code</h4> 36 * <p>This code: 37 * <pre> 38 * DateFormat[] formats = new DateFormat[] { 39 * DateFormat.getDateInstance(), 40 * DateFormat.getDateTimeInstance(), 41 * DateFormat.getTimeInstance(), 42 * }; 43 * for (DateFormat df : formats) { 44 * System.out.println(df.format(new Date(0))); 45 * df.setTimeZone(TimeZone.getTimeZone("UTC")); 46 * System.out.println(df.format(new Date(0))); 47 * } 48 * </pre> 49 * 50 * <p>Produces this output when run on an {@code en_US} device in the America/Los_Angeles time zone: 51 * <pre> 52 * Dec 31, 1969 53 * Jan 1, 1970 54 * Dec 31, 1969 4:00:00 PM 55 * Jan 1, 1970 12:00:00 AM 56 * 4:00:00 PM 57 * 12:00:00 AM 58 * </pre> 59 * And will produce similarly appropriate localized human-readable output on any user's system. 60 * Notice how the same point in time when formatted can appear to be a different time when rendered 61 * for a different time zone. This is one reason why formatting should be left until the data will 62 * only be presented to a human. Machines should interchange "Unix time" integers. 63 */ 64 public abstract class DateFormat extends Format { 65 66 private static final long serialVersionUID = 7218322306649953788L; 67 68 /** 69 * A tri-state boolean. If we're running stand-alone this will be null. 70 * If we're running in an app, the frameworks will have told us the user preference. 71 * @hide 72 */ 73 public static Boolean is24Hour; 74 75 /** 76 * The calendar that this {@code DateFormat} uses to format a number 77 * representing a date. 78 */ 79 protected Calendar calendar; 80 81 /** 82 * The number format used to format a number. 83 */ 84 protected NumberFormat numberFormat; 85 86 /** 87 * The format style constant defining the default format style. The default 88 * is MEDIUM. 89 */ 90 public static final int DEFAULT = 2; 91 92 /** 93 * The format style constant defining the full style. 94 */ 95 public static final int FULL = 0; 96 97 /** 98 * The format style constant defining the long style. 99 */ 100 public static final int LONG = 1; 101 102 /** 103 * The format style constant defining the medium style. 104 */ 105 public static final int MEDIUM = 2; 106 107 /** 108 * The format style constant defining the short style. 109 */ 110 public static final int SHORT = 3; 111 112 /** 113 * The {@code FieldPosition} selector for 'G' field alignment, corresponds 114 * to the {@link Calendar#ERA} field. 115 */ 116 public static final int ERA_FIELD = 0; 117 118 /** 119 * The {@code FieldPosition} selector for 'y' field alignment, corresponds 120 * to the {@link Calendar#YEAR} field. 121 */ 122 public static final int YEAR_FIELD = 1; 123 124 /** 125 * The {@code FieldPosition} selector for 'M' field alignment, corresponds 126 * to the {@link Calendar#MONTH} field. 127 */ 128 public static final int MONTH_FIELD = 2; 129 130 /** 131 * The {@code FieldPosition} selector for 'd' field alignment, corresponds 132 * to the {@link Calendar#DATE} field. 133 */ 134 public static final int DATE_FIELD = 3; 135 136 /** 137 * The {@code FieldPosition} selector for 'k' field alignment, corresponds 138 * to the {@link Calendar#HOUR_OF_DAY} field. {@code HOUR_OF_DAY1_FIELD} is 139 * used for the one-based 24-hour clock. For example, 23:59 + 01:00 results 140 * in 24:59. 141 */ 142 public static final int HOUR_OF_DAY1_FIELD = 4; 143 144 /** 145 * The {@code FieldPosition} selector for 'H' field alignment, corresponds 146 * to the {@link Calendar#HOUR_OF_DAY} field. {@code HOUR_OF_DAY0_FIELD} is 147 * used for the zero-based 24-hour clock. For example, 23:59 + 01:00 results 148 * in 00:59. 149 */ 150 public static final int HOUR_OF_DAY0_FIELD = 5; 151 152 /** 153 * FieldPosition selector for 'm' field alignment, corresponds to the 154 * {@link Calendar#MINUTE} field. 155 */ 156 public static final int MINUTE_FIELD = 6; 157 158 /** 159 * FieldPosition selector for 's' field alignment, corresponds to the 160 * {@link Calendar#SECOND} field. 161 */ 162 public static final int SECOND_FIELD = 7; 163 164 /** 165 * FieldPosition selector for 'S' field alignment, corresponds to the 166 * {@link Calendar#MILLISECOND} field. 167 */ 168 public static final int MILLISECOND_FIELD = 8; 169 170 /** 171 * FieldPosition selector for 'E' field alignment, corresponds to the 172 * {@link Calendar#DAY_OF_WEEK} field. 173 */ 174 public static final int DAY_OF_WEEK_FIELD = 9; 175 176 /** 177 * FieldPosition selector for 'D' field alignment, corresponds to the 178 * {@link Calendar#DAY_OF_YEAR} field. 179 */ 180 public static final int DAY_OF_YEAR_FIELD = 10; 181 182 /** 183 * FieldPosition selector for 'F' field alignment, corresponds to the 184 * {@link Calendar#DAY_OF_WEEK_IN_MONTH} field. 185 */ 186 public static final int DAY_OF_WEEK_IN_MONTH_FIELD = 11; 187 188 /** 189 * FieldPosition selector for 'w' field alignment, corresponds to the 190 * {@link Calendar#WEEK_OF_YEAR} field. 191 */ 192 public static final int WEEK_OF_YEAR_FIELD = 12; 193 194 /** 195 * FieldPosition selector for 'W' field alignment, corresponds to the 196 * {@link Calendar#WEEK_OF_MONTH} field. 197 */ 198 public static final int WEEK_OF_MONTH_FIELD = 13; 199 200 /** 201 * FieldPosition selector for 'a' field alignment, corresponds to the 202 * {@link Calendar#AM_PM} field. 203 */ 204 public static final int AM_PM_FIELD = 14; 205 206 /** 207 * FieldPosition selector for 'h' field alignment, corresponding to the 208 * {@link Calendar#HOUR} field. 209 */ 210 public static final int HOUR1_FIELD = 15; 211 212 /** 213 * The {@code FieldPosition} selector for 'K' field alignment, corresponding to the 214 * {@link Calendar#HOUR} field. 215 */ 216 public static final int HOUR0_FIELD = 16; 217 218 /** 219 * The {@code FieldPosition} selector for 'z' field alignment, corresponds 220 * to the {@link Calendar#ZONE_OFFSET} and {@link Calendar#DST_OFFSET} 221 * fields. 222 */ 223 public static final int TIMEZONE_FIELD = 17; 224 225 /** 226 * Constructs a new instance of {@code DateFormat}. 227 */ DateFormat()228 protected DateFormat() { 229 } 230 231 /** 232 * Returns a new instance of {@code DateFormat} with the same properties. 233 */ 234 @Override clone()235 public Object clone() { 236 DateFormat clone = (DateFormat) super.clone(); 237 clone.calendar = (Calendar) calendar.clone(); 238 clone.numberFormat = (NumberFormat) numberFormat.clone(); 239 return clone; 240 } 241 242 /** 243 * Compares this date format with the specified object and indicates if they 244 * are equal. 245 * 246 * @param object 247 * the object to compare with this date format. 248 * @return {@code true} if {@code object} is a {@code DateFormat} object and 249 * it has the same properties as this date format; {@code false} 250 * otherwise. 251 * @see #hashCode 252 */ 253 @Override equals(Object object)254 public boolean equals(Object object) { 255 if (this == object) { 256 return true; 257 } 258 if (!(object instanceof DateFormat)) { 259 return false; 260 } 261 DateFormat dateFormat = (DateFormat) object; 262 return numberFormat.equals(dateFormat.numberFormat) 263 && calendar.getTimeZone().equals( 264 dateFormat.calendar.getTimeZone()) 265 && calendar.getFirstDayOfWeek() == dateFormat.calendar 266 .getFirstDayOfWeek() 267 && calendar.getMinimalDaysInFirstWeek() == dateFormat.calendar 268 .getMinimalDaysInFirstWeek() 269 && calendar.isLenient() == dateFormat.calendar.isLenient(); 270 } 271 272 /** 273 * Formats the specified object as a string using the pattern of this date 274 * format and appends the string to the specified string buffer. 275 * <p> 276 * If the {@code field} member of {@code field} contains a value specifying 277 * a format field, then its {@code beginIndex} and {@code endIndex} members 278 * will be updated with the position of the first occurrence of this field 279 * in the formatted text. 280 * 281 * @param object 282 * the source object to format, must be a {@code Date} or a 283 * {@code Number}. If {@code object} is a number then a date is 284 * constructed using the {@code longValue()} of the number. 285 * @param buffer 286 * the target string buffer to append the formatted date/time to. 287 * @param field 288 * on input: an optional alignment field; on output: the offsets 289 * of the alignment field in the formatted text. 290 * @return the string buffer. 291 * @throws IllegalArgumentException 292 * if {@code object} is neither a {@code Date} nor a 293 * {@code Number} instance. 294 */ 295 @Override format(Object object, StringBuffer buffer, FieldPosition field)296 public final StringBuffer format(Object object, StringBuffer buffer, FieldPosition field) { 297 if (object instanceof Date) { 298 return format((Date) object, buffer, field); 299 } 300 if (object instanceof Number) { 301 return format(new Date(((Number) object).longValue()), buffer, field); 302 } 303 throw new IllegalArgumentException("Bad class: " + object.getClass()); 304 } 305 306 /** 307 * Formats the specified date using the rules of this date format. 308 * 309 * @param date 310 * the date to format. 311 * @return the formatted string. 312 */ format(Date date)313 public final String format(Date date) { 314 return format(date, new StringBuffer(), new FieldPosition(0)).toString(); 315 } 316 317 /** 318 * Formats the specified date as a string using the pattern of this date 319 * format and appends the string to the specified string buffer. 320 * <p> 321 * If the {@code field} member of {@code field} contains a value specifying 322 * a format field, then its {@code beginIndex} and {@code endIndex} members 323 * will be updated with the position of the first occurrence of this field 324 * in the formatted text. 325 * 326 * @param date 327 * the date to format. 328 * @param buffer 329 * the target string buffer to append the formatted date/time to. 330 * @param field 331 * on input: an optional alignment field; on output: the offsets 332 * of the alignment field in the formatted text. 333 * @return the string buffer. 334 */ format(Date date, StringBuffer buffer, FieldPosition field)335 public abstract StringBuffer format(Date date, StringBuffer buffer, FieldPosition field); 336 337 /** 338 * Returns an array of locales for which custom {@code DateFormat} instances 339 * are available. 340 * <p>Note that Android does not support user-supplied locale service providers. 341 */ getAvailableLocales()342 public static Locale[] getAvailableLocales() { 343 return ICU.getAvailableDateFormatLocales(); 344 } 345 346 /** 347 * Returns the calendar used by this {@code DateFormat}. 348 * 349 * @return the calendar used by this date format. 350 */ getCalendar()351 public Calendar getCalendar() { 352 return calendar; 353 } 354 355 /** 356 * Returns a {@code DateFormat} instance for formatting and parsing dates in 357 * the DEFAULT style for the default locale. 358 * 359 * @return the {@code DateFormat} instance for the default style and locale. 360 */ getDateInstance()361 public static final DateFormat getDateInstance() { 362 return getDateInstance(DEFAULT); 363 } 364 365 /** 366 * Returns a {@code DateFormat} instance for formatting and parsing dates in 367 * the specified style for the user's default locale. 368 * See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>". 369 * @param style 370 * one of SHORT, MEDIUM, LONG, FULL, or DEFAULT. 371 * @return the {@code DateFormat} instance for {@code style} and the default 372 * locale. 373 * @throws IllegalArgumentException 374 * if {@code style} is not one of SHORT, MEDIUM, LONG, FULL, or 375 * DEFAULT. 376 */ getDateInstance(int style)377 public static final DateFormat getDateInstance(int style) { 378 checkDateStyle(style); 379 return getDateInstance(style, Locale.getDefault()); 380 } 381 382 /** 383 * Returns a {@code DateFormat} instance for formatting and parsing dates in 384 * the specified style for the specified locale. 385 * 386 * @param style 387 * one of SHORT, MEDIUM, LONG, FULL, or DEFAULT. 388 * @param locale 389 * the locale. 390 * @throws IllegalArgumentException 391 * if {@code style} is not one of SHORT, MEDIUM, LONG, FULL, or 392 * DEFAULT. 393 * @return the {@code DateFormat} instance for {@code style} and 394 * {@code locale}. 395 */ getDateInstance(int style, Locale locale)396 public static final DateFormat getDateInstance(int style, Locale locale) { 397 checkDateStyle(style); 398 if (locale == null) { 399 throw new NullPointerException("locale == null"); 400 } 401 return new SimpleDateFormat(LocaleData.get(locale).getDateFormat(style), locale); 402 } 403 404 /** 405 * Returns a {@code DateFormat} instance for formatting and parsing dates 406 * and time values in the DEFAULT style for the default locale. 407 * 408 * @return the {@code DateFormat} instance for the default style and locale. 409 */ getDateTimeInstance()410 public static final DateFormat getDateTimeInstance() { 411 return getDateTimeInstance(DEFAULT, DEFAULT); 412 } 413 414 /** 415 * Returns a {@code DateFormat} instance for formatting and parsing of both 416 * dates and time values in the manner appropriate for the user's default locale. 417 * See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>". 418 * @param dateStyle 419 * one of SHORT, MEDIUM, LONG, FULL, or DEFAULT. 420 * @param timeStyle 421 * one of SHORT, MEDIUM, LONG, FULL, or DEFAULT. 422 * @return the {@code DateFormat} instance for {@code dateStyle}, 423 * {@code timeStyle} and the default locale. 424 * @throws IllegalArgumentException 425 * if {@code dateStyle} or {@code timeStyle} is not one of 426 * SHORT, MEDIUM, LONG, FULL, or DEFAULT. 427 */ getDateTimeInstance(int dateStyle, int timeStyle)428 public static final DateFormat getDateTimeInstance(int dateStyle, int timeStyle) { 429 checkTimeStyle(timeStyle); 430 checkDateStyle(dateStyle); 431 return getDateTimeInstance(dateStyle, timeStyle, Locale.getDefault()); 432 } 433 434 /** 435 * Returns a {@code DateFormat} instance for formatting and parsing dates 436 * and time values in the specified styles for the specified locale. 437 * 438 * @param dateStyle 439 * one of SHORT, MEDIUM, LONG, FULL, or DEFAULT. 440 * @param timeStyle 441 * one of SHORT, MEDIUM, LONG, FULL, or DEFAULT. 442 * @param locale 443 * the locale. 444 * @return the {@code DateFormat} instance for {@code dateStyle}, 445 * {@code timeStyle} and {@code locale}. 446 * @throws IllegalArgumentException 447 * if {@code dateStyle} or {@code timeStyle} is not one of 448 * SHORT, MEDIUM, LONG, FULL, or DEFAULT. 449 */ getDateTimeInstance(int dateStyle, int timeStyle, Locale locale)450 public static final DateFormat getDateTimeInstance(int dateStyle, int timeStyle, Locale locale) { 451 checkTimeStyle(timeStyle); 452 checkDateStyle(dateStyle); 453 if (locale == null) { 454 throw new NullPointerException("locale == null"); 455 } 456 LocaleData localeData = LocaleData.get(locale); 457 String pattern = localeData.getDateFormat(dateStyle) + " " + localeData.getTimeFormat(timeStyle); 458 return new SimpleDateFormat(pattern, locale); 459 } 460 461 /** 462 * Returns a {@code DateFormat} instance for formatting and parsing dates 463 * and times in the SHORT style for the default locale. 464 * 465 * @return the {@code DateFormat} instance for the SHORT style and default 466 * locale. 467 */ getInstance()468 public static final DateFormat getInstance() { 469 return getDateTimeInstance(SHORT, SHORT); 470 } 471 472 /** 473 * @hide for internal use only. 474 */ set24HourTimePref(boolean is24Hour)475 public static final void set24HourTimePref(boolean is24Hour) { 476 DateFormat.is24Hour = is24Hour; 477 } 478 479 /** 480 * Returns the {@code NumberFormat} used by this {@code DateFormat}. 481 * 482 * @return the {@code NumberFormat} used by this date format. 483 */ getNumberFormat()484 public NumberFormat getNumberFormat() { 485 return numberFormat; 486 } 487 488 /** 489 * Returns a {@code DateFormat} instance for formatting and parsing time 490 * values in the DEFAULT style for the default locale. 491 * 492 * @return the {@code DateFormat} instance for the default style and locale. 493 */ getTimeInstance()494 public static final DateFormat getTimeInstance() { 495 return getTimeInstance(DEFAULT); 496 } 497 498 /** 499 * Returns a {@code DateFormat} instance for formatting and parsing time 500 * values in the specified style for the user's default locale. 501 * See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>". 502 * @param style 503 * one of SHORT, MEDIUM, LONG, FULL, or DEFAULT. 504 * @return the {@code DateFormat} instance for {@code style} and the default 505 * locale. 506 * @throws IllegalArgumentException 507 * if {@code style} is not one of SHORT, MEDIUM, LONG, FULL, or 508 * DEFAULT. 509 */ getTimeInstance(int style)510 public static final DateFormat getTimeInstance(int style) { 511 checkTimeStyle(style); 512 return getTimeInstance(style, Locale.getDefault()); 513 } 514 515 /** 516 * Returns a {@code DateFormat} instance for formatting and parsing time 517 * values in the specified style for the specified locale. 518 * 519 * @param style 520 * one of SHORT, MEDIUM, LONG, FULL, or DEFAULT. 521 * @param locale 522 * the locale. 523 * @throws IllegalArgumentException 524 * if {@code style} is not one of SHORT, MEDIUM, LONG, FULL, or 525 * DEFAULT. 526 * @return the {@code DateFormat} instance for {@code style} and 527 * {@code locale}. 528 */ getTimeInstance(int style, Locale locale)529 public static final DateFormat getTimeInstance(int style, Locale locale) { 530 checkTimeStyle(style); 531 if (locale == null) { 532 throw new NullPointerException("locale == null"); 533 } 534 535 return new SimpleDateFormat(LocaleData.get(locale).getTimeFormat(style), locale); 536 } 537 538 /** 539 * Returns the time zone of this date format's calendar. 540 * 541 * @return the time zone of the calendar used by this date format. 542 */ getTimeZone()543 public TimeZone getTimeZone() { 544 return calendar.getTimeZone(); 545 } 546 547 @Override hashCode()548 public int hashCode() { 549 return calendar.getFirstDayOfWeek() 550 + calendar.getMinimalDaysInFirstWeek() 551 + calendar.getTimeZone().hashCode() 552 + (calendar.isLenient() ? 1231 : 1237) 553 + numberFormat.hashCode(); 554 } 555 556 /** 557 * Indicates whether the calendar used by this date format is lenient. 558 * 559 * @return {@code true} if the calendar is lenient; {@code false} otherwise. 560 */ isLenient()561 public boolean isLenient() { 562 return calendar.isLenient(); 563 } 564 565 /** 566 * Parses a date from the specified string using the rules of this date 567 * format. 568 * 569 * @param string 570 * the string to parse. 571 * @return the {@code Date} resulting from the parsing. 572 * @throws ParseException 573 * if an error occurs during parsing. 574 */ parse(String string)575 public Date parse(String string) throws ParseException { 576 ParsePosition position = new ParsePosition(0); 577 Date date = parse(string, position); 578 if (position.getIndex() == 0) { 579 throw new ParseException("Unparseable date: \"" + string + "\"", 580 position.getErrorIndex()); 581 } 582 return date; 583 } 584 585 /** 586 * Parses a date from the specified string starting at the index specified 587 * by {@code position}. If the string is successfully parsed then the index 588 * of the {@code ParsePosition} is updated to the index following the parsed 589 * text. On error, the index is unchanged and the error index of {@code 590 * ParsePosition} is set to the index where the error occurred. 591 * <p> 592 * By default, parsing is lenient: If the input is not in the form used by 593 * this object's format method but can still be parsed as a date, then the 594 * parse succeeds. Clients may insist on strict adherence to the format by 595 * calling {@code setLenient(false)}. 596 * 597 * @param string 598 * the string to parse. 599 * @param position 600 * input/output parameter, specifies the start index in {@code 601 * string} from where to start parsing. If parsing is successful, 602 * it is updated with the index following the parsed text; on 603 * error, the index is unchanged and the error index is set to 604 * the index where the error occurred. 605 * @return the date resulting from the parse, or {@code null} if there is an 606 * error. 607 */ parse(String string, ParsePosition position)608 public abstract Date parse(String string, ParsePosition position); 609 610 /** 611 * Parses a date from the specified string starting at the index specified 612 * by {@code position}. If the string is successfully parsed then the index 613 * of the {@code ParsePosition} is updated to the index following the parsed 614 * text. On error, the index is unchanged and the error index of 615 * {@code ParsePosition} is set to the index where the error occurred. 616 * <p> 617 * By default, parsing is lenient: If the input is not in the form used by 618 * this object's format method but can still be parsed as a date, then the 619 * parse succeeds. Clients may insist on strict adherence to the format by 620 * calling {@code setLenient(false)}. 621 * 622 * @param string 623 * the string to parse. 624 * @param position 625 * input/output parameter, specifies the start index in 626 * {@code string} from where to start parsing. If parsing is 627 * successful, it is updated with the index following the parsed 628 * text; on error, the index is unchanged and the error index 629 * is set to the index where the error occurred. 630 * @return the date resulting from the parsing, or {@code null} if there is 631 * an error. 632 */ 633 @Override parseObject(String string, ParsePosition position)634 public Object parseObject(String string, ParsePosition position) { 635 return parse(string, position); 636 } 637 638 /** 639 * Sets the calendar used by this date format. 640 * 641 * @param cal 642 * the new calendar. 643 */ setCalendar(Calendar cal)644 public void setCalendar(Calendar cal) { 645 calendar = cal; 646 } 647 648 /** 649 * Specifies whether or not date/time parsing shall be lenient. With lenient 650 * parsing, the parser may use heuristics to interpret inputs that do not 651 * precisely match this object's format. With strict parsing, inputs must 652 * match this object's format. 653 * 654 * @param value 655 * {@code true} to set the calendar to be lenient, {@code false} 656 * otherwise. 657 */ setLenient(boolean value)658 public void setLenient(boolean value) { 659 calendar.setLenient(value); 660 } 661 662 /** 663 * Sets the {@code NumberFormat} used by this date format. 664 * 665 * @param format 666 * the new number format. 667 */ setNumberFormat(NumberFormat format)668 public void setNumberFormat(NumberFormat format) { 669 numberFormat = format; 670 } 671 672 /** 673 * Sets the time zone of the calendar used by this date format. 674 * 675 * @param timezone 676 * the new time zone. 677 */ setTimeZone(TimeZone timezone)678 public void setTimeZone(TimeZone timezone) { 679 calendar.setTimeZone(timezone); 680 } 681 682 /** 683 * The instances of this inner class are used as attribute keys and values 684 * in {@code AttributedCharacterIterator} that the 685 * {@link SimpleDateFormat#formatToCharacterIterator(Object)} method returns. 686 * <p> 687 * There is no public constructor in this class, the only instances are the 688 * constants defined here. 689 */ 690 public static class Field extends Format.Field { 691 692 private static final long serialVersionUID = 7441350119349544720L; 693 694 private static Hashtable<Integer, Field> table = new Hashtable<Integer, Field>(); 695 696 /** 697 * Marks the era part of a date. 698 */ 699 public static final Field ERA = new Field("era", Calendar.ERA); 700 701 /** 702 * Marks the year part of a date. 703 */ 704 public static final Field YEAR = new Field("year", Calendar.YEAR); 705 706 /** 707 * Marks the month part of a date. 708 */ 709 public static final Field MONTH = new Field("month", Calendar.MONTH); 710 711 /** 712 * Marks the hour of the day part of a date (0-11). 713 */ 714 public static final Field HOUR_OF_DAY0 = new Field("hour of day", Calendar.HOUR_OF_DAY); 715 716 /** 717 * Marks the hour of the day part of a date (1-12). 718 */ 719 public static final Field HOUR_OF_DAY1 = new Field("hour of day 1", -1); 720 721 /** 722 * Marks the minute part of a time. 723 */ 724 public static final Field MINUTE = new Field("minute", Calendar.MINUTE); 725 726 /** 727 * Marks the second part of a time. 728 */ 729 public static final Field SECOND = new Field("second", Calendar.SECOND); 730 731 /** 732 * Marks the millisecond part of a time. 733 */ 734 public static final Field MILLISECOND = new Field("millisecond", Calendar.MILLISECOND); 735 736 /** 737 * Marks the day of the week part of a date. 738 */ 739 public static final Field DAY_OF_WEEK = new Field("day of week", Calendar.DAY_OF_WEEK); 740 741 /** 742 * Marks the day of the month part of a date. 743 */ 744 public static final Field DAY_OF_MONTH = new Field("day of month", Calendar.DAY_OF_MONTH); 745 746 /** 747 * Marks the day of the year part of a date. 748 */ 749 public static final Field DAY_OF_YEAR = new Field("day of year", Calendar.DAY_OF_YEAR); 750 751 /** 752 * Marks the day of the week in the month part of a date. 753 */ 754 public static final Field DAY_OF_WEEK_IN_MONTH = new Field("day of week in month", 755 Calendar.DAY_OF_WEEK_IN_MONTH); 756 757 /** 758 * Marks the week of the year part of a date. 759 */ 760 public static final Field WEEK_OF_YEAR = new Field("week of year", 761 Calendar.WEEK_OF_YEAR); 762 763 /** 764 * Marks the week of the month part of a date. 765 */ 766 public static final Field WEEK_OF_MONTH = new Field("week of month", 767 Calendar.WEEK_OF_MONTH); 768 769 /** 770 * Marks the time indicator part of a date. 771 */ 772 public static final Field AM_PM = new Field("am pm", Calendar.AM_PM); 773 774 /** 775 * Marks the hour part of a date (0-11). 776 */ 777 public static final Field HOUR0 = new Field("hour", Calendar.HOUR); 778 779 /** 780 * Marks the hour part of a date (1-12). 781 */ 782 public static final Field HOUR1 = new Field("hour 1", -1); 783 784 /** 785 * Marks the time zone part of a date. 786 */ 787 public static final Field TIME_ZONE = new Field("time zone", -1); 788 789 /** 790 * The calendar field that this field represents. 791 */ 792 private int calendarField = -1; 793 794 /** 795 * Constructs a new instance of {@code DateFormat.Field} with the given 796 * fieldName and calendar field. 797 * 798 * @param fieldName 799 * the field name. 800 * @param calendarField 801 * the calendar field type of the field. 802 */ Field(String fieldName, int calendarField)803 protected Field(String fieldName, int calendarField) { 804 super(fieldName); 805 this.calendarField = calendarField; 806 if (calendarField != -1 && table.get(Integer.valueOf(calendarField)) == null) { 807 table.put(Integer.valueOf(calendarField), this); 808 } 809 } 810 811 /** 812 * Returns the Calendar field that this field represents. 813 * 814 * @return the calendar field. 815 */ getCalendarField()816 public int getCalendarField() { 817 return calendarField; 818 } 819 820 /** 821 * Returns the {@code DateFormat.Field} instance for the given calendar 822 * field. 823 * 824 * @param calendarField 825 * a calendar field constant. 826 * @return the {@code DateFormat.Field} corresponding to 827 * {@code calendarField}. 828 * @throws IllegalArgumentException 829 * if {@code calendarField} is negative or greater than the 830 * field count of {@code Calendar}. 831 */ ofCalendarField(int calendarField)832 public static Field ofCalendarField(int calendarField) { 833 if (calendarField < 0 || calendarField >= Calendar.FIELD_COUNT) { 834 throw new IllegalArgumentException("Field out of range: " + calendarField); 835 } 836 return table.get(Integer.valueOf(calendarField)); 837 } 838 } 839 checkDateStyle(int style)840 private static void checkDateStyle(int style) { 841 if (!(style == SHORT || style == MEDIUM || style == LONG 842 || style == FULL || style == DEFAULT)) { 843 throw new IllegalArgumentException("Illegal date style: " + style); 844 } 845 } 846 checkTimeStyle(int style)847 private static void checkTimeStyle(int style) { 848 if (!(style == SHORT || style == MEDIUM || style == LONG 849 || style == FULL || style == DEFAULT)) { 850 throw new IllegalArgumentException("Illegal time style: " + style); 851 } 852 } 853 } 854