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