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