< prev index next >

src/java.base/share/classes/java/text/SimpleDateFormat.java

Print this page
rev 56290 : 8230648: Replace @exception tag with @throws in java.base
Summary: Minor coding style update of javadoc tag in any file in java.base
Reviewed-by: prappo, lancea


 575     public SimpleDateFormat() {
 576         this("", Locale.getDefault(Locale.Category.FORMAT));
 577         applyPatternImpl(LocaleProviderAdapter.getResourceBundleBased().getLocaleResources(locale)
 578                          .getDateTimePattern(SHORT, SHORT, calendar));
 579     }
 580 
 581     /**
 582      * Constructs a <code>SimpleDateFormat</code> using the given pattern and
 583      * the default date format symbols for the default
 584      * {@link java.util.Locale.Category#FORMAT FORMAT} locale.
 585      * <b>Note:</b> This constructor may not support all locales.
 586      * For full coverage, use the factory methods in the {@link DateFormat}
 587      * class.
 588      * <p>This is equivalent to calling
 589      * {@link #SimpleDateFormat(String, Locale)
 590      *     SimpleDateFormat(pattern, Locale.getDefault(Locale.Category.FORMAT))}.
 591      *
 592      * @see java.util.Locale#getDefault(java.util.Locale.Category)
 593      * @see java.util.Locale.Category#FORMAT
 594      * @param pattern the pattern describing the date and time format
 595      * @exception NullPointerException if the given pattern is null
 596      * @exception IllegalArgumentException if the given pattern is invalid
 597      */
 598     public SimpleDateFormat(String pattern)
 599     {
 600         this(pattern, Locale.getDefault(Locale.Category.FORMAT));
 601     }
 602 
 603     /**
 604      * Constructs a <code>SimpleDateFormat</code> using the given pattern and
 605      * the default date format symbols for the given locale.
 606      * <b>Note:</b> This constructor may not support all locales.
 607      * For full coverage, use the factory methods in the {@link DateFormat}
 608      * class.
 609      *
 610      * @param pattern the pattern describing the date and time format
 611      * @param locale the locale whose date format symbols should be used
 612      * @exception NullPointerException if the given pattern or locale is null
 613      * @exception IllegalArgumentException if the given pattern is invalid
 614      */
 615     public SimpleDateFormat(String pattern, Locale locale)
 616     {
 617         if (pattern == null || locale == null) {
 618             throw new NullPointerException();
 619         }
 620 
 621         initializeCalendar(locale);
 622         this.pattern = pattern;
 623         this.formatData = DateFormatSymbols.getInstanceRef(locale);
 624         this.locale = locale;
 625         initialize(locale);
 626     }
 627 
 628     /**
 629      * Constructs a <code>SimpleDateFormat</code> using the given pattern and
 630      * date format symbols.
 631      *
 632      * @param pattern the pattern describing the date and time format
 633      * @param formatSymbols the date format symbols to be used for formatting
 634      * @exception NullPointerException if the given pattern or formatSymbols is null
 635      * @exception IllegalArgumentException if the given pattern is invalid
 636      */
 637     public SimpleDateFormat(String pattern, DateFormatSymbols formatSymbols)
 638     {
 639         if (pattern == null || formatSymbols == null) {
 640             throw new NullPointerException();
 641         }
 642 
 643         this.pattern = pattern;
 644         this.formatData = (DateFormatSymbols) formatSymbols.clone();
 645         this.locale = Locale.getDefault(Locale.Category.FORMAT);
 646         initializeCalendar(this.locale);
 647         initialize(this.locale);
 648         useDateFormatSymbols = true;
 649     }
 650 
 651     /* Initialize compiledPattern and numberFormat fields */
 652     private void initialize(Locale loc) {
 653         // Verify and compile the given pattern.
 654         compiledPattern = compile(pattern);
 655 


 722      * <blockquote>
 723      *     char[0] = (Tag << 8) | 255;
 724      *     char[1] = (char) (long_length >>> 16);
 725      *     char[2] = (char) (long_length & 0xffff);
 726      * </blockquote>
 727      * <p>
 728      * If Tag is a pattern_char_index, its Length is the number of
 729      * pattern characters. For example, if the given pattern is
 730      * "yyyy", Tag is 1 and Length is 4, followed by no data.
 731      * <p>
 732      * If Tag is TAG_QUOTE_CHARS, its Length is the number of char's
 733      * following the TagField. For example, if the given pattern is
 734      * "'o''clock'", Length is 7 followed by a char sequence of
 735      * <code>o&nbs;'&nbs;c&nbs;l&nbs;o&nbs;c&nbs;k</code>.
 736      * <p>
 737      * TAG_QUOTE_ASCII_CHAR is a special tag and has an ASCII
 738      * character in place of Length. For example, if the given pattern
 739      * is "'o'", the TaggedData entry is
 740      * <code>((TAG_QUOTE_ASCII_CHAR&nbs;<<&nbs;8)&nbs;|&nbs;'o')</code>.
 741      *
 742      * @exception NullPointerException if the given pattern is null
 743      * @exception IllegalArgumentException if the given pattern is invalid
 744      */
 745     private char[] compile(String pattern) {
 746         int length = pattern.length();
 747         boolean inQuote = false;
 748         StringBuilder compiledCode = new StringBuilder(length * 2);
 749         StringBuilder tmpBuffer = null;
 750         int count = 0, tagcount = 0;
 751         int lastTag = -1, prevTag = -1;
 752 
 753         for (int i = 0; i < length; i++) {
 754             char c = pattern.charAt(i);
 755 
 756             if (c == '\'') {
 757                 // '' is treated as a single quote regardless of being
 758                 // in a quoted section.
 759                 if ((i + 1) < length) {
 760                     c = pattern.charAt(i + 1);
 761                     if (c == '\'') {
 762                         i++;
 763                         if (count != 0) {


 941     /**
 942      * Formats the given <code>Date</code> into a date/time string and appends
 943      * the result to the given <code>StringBuffer</code>.
 944      *
 945      * @param date the date-time value to be formatted into a date-time string.
 946      * @param toAppendTo where the new date-time text is to be appended.
 947      * @param pos keeps track on the position of the field within
 948      * the returned string. For example, given a date-time text
 949      * {@code "1996.07.10 AD at 15:08:56 PDT"}, if the given {@code fieldPosition}
 950      * is {@link DateFormat#YEAR_FIELD}, the begin index and end index of
 951      * {@code fieldPosition} will be set to 0 and 4, respectively.
 952      * Notice that if the same date-time field appears more than once in a
 953      * pattern, the {@code fieldPosition} will be set for the first occurrence
 954      * of that date-time field. For instance, formatting a {@code Date} to the
 955      * date-time string {@code "1 PM PDT (Pacific Daylight Time)"} using the
 956      * pattern {@code "h a z (zzzz)"} and the alignment field
 957      * {@link DateFormat#TIMEZONE_FIELD}, the begin index and end index of
 958      * {@code fieldPosition} will be set to 5 and 8, respectively, for the
 959      * first occurrence of the timezone pattern character {@code 'z'}.
 960      * @return the formatted date-time string.
 961      * @exception NullPointerException if any of the parameters is {@code null}.
 962      */
 963     @Override
 964     public StringBuffer format(Date date, StringBuffer toAppendTo,
 965                                FieldPosition pos)
 966     {
 967         pos.beginIndex = pos.endIndex = 0;
 968         return format(date, toAppendTo, pos.getFieldDelegate());
 969     }
 970 
 971     // Called from Format after creating a FieldDelegate
 972     private StringBuffer format(Date date, StringBuffer toAppendTo,
 973                                 FieldDelegate delegate) {
 974         // Convert input date to time field list
 975         calendar.setTime(date);
 976 
 977         boolean useDateFormatSymbols = useDateFormatSymbols();
 978 
 979         for (int i = 0; i < compiledPattern.length; ) {
 980             int tag = compiledPattern[i] >>> 8;
 981             int count = compiledPattern[i++] & 0xff;


 995                 break;
 996 
 997             default:
 998                 subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols);
 999                 break;
1000             }
1001         }
1002         return toAppendTo;
1003     }
1004 
1005     /**
1006      * Formats an Object producing an <code>AttributedCharacterIterator</code>.
1007      * You can use the returned <code>AttributedCharacterIterator</code>
1008      * to build the resulting String, as well as to determine information
1009      * about the resulting String.
1010      * <p>
1011      * Each attribute key of the AttributedCharacterIterator will be of type
1012      * <code>DateFormat.Field</code>, with the corresponding attribute value
1013      * being the same as the attribute key.
1014      *
1015      * @exception NullPointerException if obj is null.
1016      * @exception IllegalArgumentException if the Format cannot format the
1017      *            given object, or if the Format's pattern string is invalid.
1018      * @param obj The object to format
1019      * @return AttributedCharacterIterator describing the formatted value.
1020      * @since 1.4
1021      */
1022     @Override
1023     public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
1024         StringBuffer sb = new StringBuffer();
1025         CharacterIteratorFieldDelegate delegate = new
1026                          CharacterIteratorFieldDelegate();
1027 
1028         if (obj instanceof Date) {
1029             format((Date)obj, sb, delegate);
1030         }
1031         else if (obj instanceof Number) {
1032             format(new Date(((Number)obj).longValue()), sb, delegate);
1033         }
1034         else if (obj == null) {
1035             throw new NullPointerException(
1036                    "formatToCharacterIterator must be passed non-null object");


1442      *
1443      * <p>This parsing operation uses the {@link DateFormat#calendar
1444      * calendar} to produce a {@code Date}. All of the {@code
1445      * calendar}'s date-time fields are {@linkplain Calendar#clear()
1446      * cleared} before parsing, and the {@code calendar}'s default
1447      * values of the date-time fields are used for any missing
1448      * date-time information. For example, the year value of the
1449      * parsed {@code Date} is 1970 with {@link GregorianCalendar} if
1450      * no year value is given from the parsing operation.  The {@code
1451      * TimeZone} value may be overwritten, depending on the given
1452      * pattern and the time zone value in {@code text}. Any {@code
1453      * TimeZone} value that has previously been set by a call to
1454      * {@link #setTimeZone(java.util.TimeZone) setTimeZone} may need
1455      * to be restored for further operations.
1456      *
1457      * @param text  A <code>String</code>, part of which should be parsed.
1458      * @param pos   A <code>ParsePosition</code> object with index and error
1459      *              index information as described above.
1460      * @return A <code>Date</code> parsed from the string. In case of
1461      *         error, returns null.
1462      * @exception NullPointerException if <code>text</code> or <code>pos</code> is null.
1463      */
1464     @Override
1465     public Date parse(String text, ParsePosition pos)
1466     {
1467         checkNegativeNumberExpression();
1468 
1469         int start = pos.index;
1470         int oldStart = start;
1471         int textLength = text.length();
1472 
1473         boolean[] ambiguousYear = {false};
1474 
1475         CalendarBuilder calb = new CalendarBuilder();
1476 
1477         for (int i = 0; i < compiledPattern.length; ) {
1478             int tag = compiledPattern[i] >>> 8;
1479             int count = compiledPattern[i++] & 0xff;
1480             if (count == 255) {
1481                 count = compiledPattern[i++] << 16;
1482                 count |= compiledPattern[i++];


2259             }
2260         }
2261 
2262         // Parsing failed.
2263         origPos.errorIndex = pos.index;
2264         return -1;
2265     }
2266 
2267     /**
2268      * Returns true if the DateFormatSymbols has been set explicitly or locale
2269      * is null.
2270      */
2271     private boolean useDateFormatSymbols() {
2272         return useDateFormatSymbols || locale == null;
2273     }
2274 
2275     /**
2276      * Translates a pattern, mapping each character in the from string to the
2277      * corresponding character in the to string.
2278      *
2279      * @exception IllegalArgumentException if the given pattern is invalid
2280      */
2281     private String translatePattern(String pattern, String from, String to) {
2282         StringBuilder result = new StringBuilder();
2283         boolean inQuote = false;
2284         for (int i = 0; i < pattern.length(); ++i) {
2285             char c = pattern.charAt(i);
2286             if (inQuote) {
2287                 if (c == '\'') {
2288                     inQuote = false;
2289                 }
2290             }
2291             else {
2292                 if (c == '\'') {
2293                     inQuote = true;
2294                 } else if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
2295                     int ci = from.indexOf(c);
2296                     if (ci >= 0) {
2297                         // patternChars is longer than localPatternChars due
2298                         // to serialization compatibility. The pattern letters
2299                         // unsupported by localPatternChars pass through.


2322      */
2323     public String toPattern() {
2324         return pattern;
2325     }
2326 
2327     /**
2328      * Returns a localized pattern string describing this date format.
2329      *
2330      * @return a localized pattern string describing this date format.
2331      */
2332     public String toLocalizedPattern() {
2333         return translatePattern(pattern,
2334                                 DateFormatSymbols.patternChars,
2335                                 formatData.getLocalPatternChars());
2336     }
2337 
2338     /**
2339      * Applies the given pattern string to this date format.
2340      *
2341      * @param pattern the new date and time pattern for this date format
2342      * @exception NullPointerException if the given pattern is null
2343      * @exception IllegalArgumentException if the given pattern is invalid
2344      */
2345     public void applyPattern(String pattern)
2346     {
2347         applyPatternImpl(pattern);
2348     }
2349 
2350     private void applyPatternImpl(String pattern) {
2351         compiledPattern = compile(pattern);
2352         this.pattern = pattern;
2353     }
2354 
2355     /**
2356      * Applies the given localized pattern string to this date format.
2357      *
2358      * @param pattern a String to be mapped to the new date and time format
2359      *        pattern for this format
2360      * @exception NullPointerException if the given pattern is null
2361      * @exception IllegalArgumentException if the given pattern is invalid
2362      */
2363     public void applyLocalizedPattern(String pattern) {
2364          String p = translatePattern(pattern,
2365                                      formatData.getLocalPatternChars(),
2366                                      DateFormatSymbols.patternChars);
2367          compiledPattern = compile(p);
2368          this.pattern = p;
2369     }
2370 
2371     /**
2372      * Gets a copy of the date and time format symbols of this date format.
2373      *
2374      * @return the date and time format symbols of this date format
2375      * @see #setDateFormatSymbols
2376      */
2377     public DateFormatSymbols getDateFormatSymbols()
2378     {
2379         return (DateFormatSymbols)formatData.clone();
2380     }
2381 
2382     /**
2383      * Sets the date and time format symbols of this date format.
2384      *
2385      * @param newFormatSymbols the new date and time format symbols
2386      * @exception NullPointerException if the given newFormatSymbols is null
2387      * @see #getDateFormatSymbols
2388      */
2389     public void setDateFormatSymbols(DateFormatSymbols newFormatSymbols)
2390     {
2391         this.formatData = (DateFormatSymbols)newFormatSymbols.clone();
2392         useDateFormatSymbols = true;
2393     }
2394 
2395     /**
2396      * Creates a copy of this <code>SimpleDateFormat</code>. This also
2397      * clones the format's date format symbols.
2398      *
2399      * @return a clone of this <code>SimpleDateFormat</code>
2400      */
2401     @Override
2402     public Object clone() {
2403         SimpleDateFormat other = (SimpleDateFormat) super.clone();
2404         other.formatData = (DateFormatSymbols) formatData.clone();
2405         return other;
2406     }


2453     /**
2454      * Obtains display names map, taking the context into account. Currently only
2455      * the month name pattern 'M' is context dependent.
2456      */
2457     private Map<String, Integer> getDisplayContextNamesMap(int field, Locale locale) {
2458         Map<String, Integer> map = calendar.getDisplayNames(field,
2459             forceStandaloneForm ? Calendar.SHORT_STANDALONE : Calendar.SHORT_FORMAT, locale);
2460         // Get the LONG style
2461         Map<String, Integer> m = calendar.getDisplayNames(field,
2462             forceStandaloneForm ? Calendar.LONG_STANDALONE : Calendar.LONG_FORMAT, locale);
2463         if (m != null) {
2464             map.putAll(m);
2465         }
2466         return map;
2467     }
2468 
2469     /**
2470      * After reading an object from the input stream, the format
2471      * pattern in the object is verified.
2472      *
2473      * @exception InvalidObjectException if the pattern is invalid
2474      */
2475     @java.io.Serial
2476     private void readObject(ObjectInputStream stream)
2477                          throws IOException, ClassNotFoundException {
2478         stream.defaultReadObject();
2479 
2480         try {
2481             compiledPattern = compile(pattern);
2482         } catch (Exception e) {
2483             throw new InvalidObjectException("invalid pattern");
2484         }
2485 
2486         if (serialVersionOnStream < 1) {
2487             // didn't have defaultCenturyStart field
2488             initializeDefaultCentury();
2489         }
2490         else {
2491             // fill in dependent transient field
2492             parseAmbiguousDatesAsAfter(defaultCenturyStart);
2493         }




 575     public SimpleDateFormat() {
 576         this("", Locale.getDefault(Locale.Category.FORMAT));
 577         applyPatternImpl(LocaleProviderAdapter.getResourceBundleBased().getLocaleResources(locale)
 578                          .getDateTimePattern(SHORT, SHORT, calendar));
 579     }
 580 
 581     /**
 582      * Constructs a <code>SimpleDateFormat</code> using the given pattern and
 583      * the default date format symbols for the default
 584      * {@link java.util.Locale.Category#FORMAT FORMAT} locale.
 585      * <b>Note:</b> This constructor may not support all locales.
 586      * For full coverage, use the factory methods in the {@link DateFormat}
 587      * class.
 588      * <p>This is equivalent to calling
 589      * {@link #SimpleDateFormat(String, Locale)
 590      *     SimpleDateFormat(pattern, Locale.getDefault(Locale.Category.FORMAT))}.
 591      *
 592      * @see java.util.Locale#getDefault(java.util.Locale.Category)
 593      * @see java.util.Locale.Category#FORMAT
 594      * @param pattern the pattern describing the date and time format
 595      * @throws    NullPointerException if the given pattern is null
 596      * @throws    IllegalArgumentException if the given pattern is invalid
 597      */
 598     public SimpleDateFormat(String pattern)
 599     {
 600         this(pattern, Locale.getDefault(Locale.Category.FORMAT));
 601     }
 602 
 603     /**
 604      * Constructs a <code>SimpleDateFormat</code> using the given pattern and
 605      * the default date format symbols for the given locale.
 606      * <b>Note:</b> This constructor may not support all locales.
 607      * For full coverage, use the factory methods in the {@link DateFormat}
 608      * class.
 609      *
 610      * @param pattern the pattern describing the date and time format
 611      * @param locale the locale whose date format symbols should be used
 612      * @throws    NullPointerException if the given pattern or locale is null
 613      * @throws    IllegalArgumentException if the given pattern is invalid
 614      */
 615     public SimpleDateFormat(String pattern, Locale locale)
 616     {
 617         if (pattern == null || locale == null) {
 618             throw new NullPointerException();
 619         }
 620 
 621         initializeCalendar(locale);
 622         this.pattern = pattern;
 623         this.formatData = DateFormatSymbols.getInstanceRef(locale);
 624         this.locale = locale;
 625         initialize(locale);
 626     }
 627 
 628     /**
 629      * Constructs a <code>SimpleDateFormat</code> using the given pattern and
 630      * date format symbols.
 631      *
 632      * @param pattern the pattern describing the date and time format
 633      * @param formatSymbols the date format symbols to be used for formatting
 634      * @throws    NullPointerException if the given pattern or formatSymbols is null
 635      * @throws    IllegalArgumentException if the given pattern is invalid
 636      */
 637     public SimpleDateFormat(String pattern, DateFormatSymbols formatSymbols)
 638     {
 639         if (pattern == null || formatSymbols == null) {
 640             throw new NullPointerException();
 641         }
 642 
 643         this.pattern = pattern;
 644         this.formatData = (DateFormatSymbols) formatSymbols.clone();
 645         this.locale = Locale.getDefault(Locale.Category.FORMAT);
 646         initializeCalendar(this.locale);
 647         initialize(this.locale);
 648         useDateFormatSymbols = true;
 649     }
 650 
 651     /* Initialize compiledPattern and numberFormat fields */
 652     private void initialize(Locale loc) {
 653         // Verify and compile the given pattern.
 654         compiledPattern = compile(pattern);
 655 


 722      * <blockquote>
 723      *     char[0] = (Tag << 8) | 255;
 724      *     char[1] = (char) (long_length >>> 16);
 725      *     char[2] = (char) (long_length & 0xffff);
 726      * </blockquote>
 727      * <p>
 728      * If Tag is a pattern_char_index, its Length is the number of
 729      * pattern characters. For example, if the given pattern is
 730      * "yyyy", Tag is 1 and Length is 4, followed by no data.
 731      * <p>
 732      * If Tag is TAG_QUOTE_CHARS, its Length is the number of char's
 733      * following the TagField. For example, if the given pattern is
 734      * "'o''clock'", Length is 7 followed by a char sequence of
 735      * <code>o&nbs;'&nbs;c&nbs;l&nbs;o&nbs;c&nbs;k</code>.
 736      * <p>
 737      * TAG_QUOTE_ASCII_CHAR is a special tag and has an ASCII
 738      * character in place of Length. For example, if the given pattern
 739      * is "'o'", the TaggedData entry is
 740      * <code>((TAG_QUOTE_ASCII_CHAR&nbs;<<&nbs;8)&nbs;|&nbs;'o')</code>.
 741      *
 742      * @throws    NullPointerException if the given pattern is null
 743      * @throws    IllegalArgumentException if the given pattern is invalid
 744      */
 745     private char[] compile(String pattern) {
 746         int length = pattern.length();
 747         boolean inQuote = false;
 748         StringBuilder compiledCode = new StringBuilder(length * 2);
 749         StringBuilder tmpBuffer = null;
 750         int count = 0, tagcount = 0;
 751         int lastTag = -1, prevTag = -1;
 752 
 753         for (int i = 0; i < length; i++) {
 754             char c = pattern.charAt(i);
 755 
 756             if (c == '\'') {
 757                 // '' is treated as a single quote regardless of being
 758                 // in a quoted section.
 759                 if ((i + 1) < length) {
 760                     c = pattern.charAt(i + 1);
 761                     if (c == '\'') {
 762                         i++;
 763                         if (count != 0) {


 941     /**
 942      * Formats the given <code>Date</code> into a date/time string and appends
 943      * the result to the given <code>StringBuffer</code>.
 944      *
 945      * @param date the date-time value to be formatted into a date-time string.
 946      * @param toAppendTo where the new date-time text is to be appended.
 947      * @param pos keeps track on the position of the field within
 948      * the returned string. For example, given a date-time text
 949      * {@code "1996.07.10 AD at 15:08:56 PDT"}, if the given {@code fieldPosition}
 950      * is {@link DateFormat#YEAR_FIELD}, the begin index and end index of
 951      * {@code fieldPosition} will be set to 0 and 4, respectively.
 952      * Notice that if the same date-time field appears more than once in a
 953      * pattern, the {@code fieldPosition} will be set for the first occurrence
 954      * of that date-time field. For instance, formatting a {@code Date} to the
 955      * date-time string {@code "1 PM PDT (Pacific Daylight Time)"} using the
 956      * pattern {@code "h a z (zzzz)"} and the alignment field
 957      * {@link DateFormat#TIMEZONE_FIELD}, the begin index and end index of
 958      * {@code fieldPosition} will be set to 5 and 8, respectively, for the
 959      * first occurrence of the timezone pattern character {@code 'z'}.
 960      * @return the formatted date-time string.
 961      * @throws    NullPointerException if any of the parameters is {@code null}.
 962      */
 963     @Override
 964     public StringBuffer format(Date date, StringBuffer toAppendTo,
 965                                FieldPosition pos)
 966     {
 967         pos.beginIndex = pos.endIndex = 0;
 968         return format(date, toAppendTo, pos.getFieldDelegate());
 969     }
 970 
 971     // Called from Format after creating a FieldDelegate
 972     private StringBuffer format(Date date, StringBuffer toAppendTo,
 973                                 FieldDelegate delegate) {
 974         // Convert input date to time field list
 975         calendar.setTime(date);
 976 
 977         boolean useDateFormatSymbols = useDateFormatSymbols();
 978 
 979         for (int i = 0; i < compiledPattern.length; ) {
 980             int tag = compiledPattern[i] >>> 8;
 981             int count = compiledPattern[i++] & 0xff;


 995                 break;
 996 
 997             default:
 998                 subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols);
 999                 break;
1000             }
1001         }
1002         return toAppendTo;
1003     }
1004 
1005     /**
1006      * Formats an Object producing an <code>AttributedCharacterIterator</code>.
1007      * You can use the returned <code>AttributedCharacterIterator</code>
1008      * to build the resulting String, as well as to determine information
1009      * about the resulting String.
1010      * <p>
1011      * Each attribute key of the AttributedCharacterIterator will be of type
1012      * <code>DateFormat.Field</code>, with the corresponding attribute value
1013      * being the same as the attribute key.
1014      *
1015      * @throws    NullPointerException if obj is null.
1016      * @throws    IllegalArgumentException if the Format cannot format the
1017      *            given object, or if the Format's pattern string is invalid.
1018      * @param obj The object to format
1019      * @return AttributedCharacterIterator describing the formatted value.
1020      * @since 1.4
1021      */
1022     @Override
1023     public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
1024         StringBuffer sb = new StringBuffer();
1025         CharacterIteratorFieldDelegate delegate = new
1026                          CharacterIteratorFieldDelegate();
1027 
1028         if (obj instanceof Date) {
1029             format((Date)obj, sb, delegate);
1030         }
1031         else if (obj instanceof Number) {
1032             format(new Date(((Number)obj).longValue()), sb, delegate);
1033         }
1034         else if (obj == null) {
1035             throw new NullPointerException(
1036                    "formatToCharacterIterator must be passed non-null object");


1442      *
1443      * <p>This parsing operation uses the {@link DateFormat#calendar
1444      * calendar} to produce a {@code Date}. All of the {@code
1445      * calendar}'s date-time fields are {@linkplain Calendar#clear()
1446      * cleared} before parsing, and the {@code calendar}'s default
1447      * values of the date-time fields are used for any missing
1448      * date-time information. For example, the year value of the
1449      * parsed {@code Date} is 1970 with {@link GregorianCalendar} if
1450      * no year value is given from the parsing operation.  The {@code
1451      * TimeZone} value may be overwritten, depending on the given
1452      * pattern and the time zone value in {@code text}. Any {@code
1453      * TimeZone} value that has previously been set by a call to
1454      * {@link #setTimeZone(java.util.TimeZone) setTimeZone} may need
1455      * to be restored for further operations.
1456      *
1457      * @param text  A <code>String</code>, part of which should be parsed.
1458      * @param pos   A <code>ParsePosition</code> object with index and error
1459      *              index information as described above.
1460      * @return A <code>Date</code> parsed from the string. In case of
1461      *         error, returns null.
1462      * @throws    NullPointerException if <code>text</code> or <code>pos</code> is null.
1463      */
1464     @Override
1465     public Date parse(String text, ParsePosition pos)
1466     {
1467         checkNegativeNumberExpression();
1468 
1469         int start = pos.index;
1470         int oldStart = start;
1471         int textLength = text.length();
1472 
1473         boolean[] ambiguousYear = {false};
1474 
1475         CalendarBuilder calb = new CalendarBuilder();
1476 
1477         for (int i = 0; i < compiledPattern.length; ) {
1478             int tag = compiledPattern[i] >>> 8;
1479             int count = compiledPattern[i++] & 0xff;
1480             if (count == 255) {
1481                 count = compiledPattern[i++] << 16;
1482                 count |= compiledPattern[i++];


2259             }
2260         }
2261 
2262         // Parsing failed.
2263         origPos.errorIndex = pos.index;
2264         return -1;
2265     }
2266 
2267     /**
2268      * Returns true if the DateFormatSymbols has been set explicitly or locale
2269      * is null.
2270      */
2271     private boolean useDateFormatSymbols() {
2272         return useDateFormatSymbols || locale == null;
2273     }
2274 
2275     /**
2276      * Translates a pattern, mapping each character in the from string to the
2277      * corresponding character in the to string.
2278      *
2279      * @throws    IllegalArgumentException if the given pattern is invalid
2280      */
2281     private String translatePattern(String pattern, String from, String to) {
2282         StringBuilder result = new StringBuilder();
2283         boolean inQuote = false;
2284         for (int i = 0; i < pattern.length(); ++i) {
2285             char c = pattern.charAt(i);
2286             if (inQuote) {
2287                 if (c == '\'') {
2288                     inQuote = false;
2289                 }
2290             }
2291             else {
2292                 if (c == '\'') {
2293                     inQuote = true;
2294                 } else if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
2295                     int ci = from.indexOf(c);
2296                     if (ci >= 0) {
2297                         // patternChars is longer than localPatternChars due
2298                         // to serialization compatibility. The pattern letters
2299                         // unsupported by localPatternChars pass through.


2322      */
2323     public String toPattern() {
2324         return pattern;
2325     }
2326 
2327     /**
2328      * Returns a localized pattern string describing this date format.
2329      *
2330      * @return a localized pattern string describing this date format.
2331      */
2332     public String toLocalizedPattern() {
2333         return translatePattern(pattern,
2334                                 DateFormatSymbols.patternChars,
2335                                 formatData.getLocalPatternChars());
2336     }
2337 
2338     /**
2339      * Applies the given pattern string to this date format.
2340      *
2341      * @param pattern the new date and time pattern for this date format
2342      * @throws    NullPointerException if the given pattern is null
2343      * @throws    IllegalArgumentException if the given pattern is invalid
2344      */
2345     public void applyPattern(String pattern)
2346     {
2347         applyPatternImpl(pattern);
2348     }
2349 
2350     private void applyPatternImpl(String pattern) {
2351         compiledPattern = compile(pattern);
2352         this.pattern = pattern;
2353     }
2354 
2355     /**
2356      * Applies the given localized pattern string to this date format.
2357      *
2358      * @param pattern a String to be mapped to the new date and time format
2359      *        pattern for this format
2360      * @throws    NullPointerException if the given pattern is null
2361      * @throws    IllegalArgumentException if the given pattern is invalid
2362      */
2363     public void applyLocalizedPattern(String pattern) {
2364          String p = translatePattern(pattern,
2365                                      formatData.getLocalPatternChars(),
2366                                      DateFormatSymbols.patternChars);
2367          compiledPattern = compile(p);
2368          this.pattern = p;
2369     }
2370 
2371     /**
2372      * Gets a copy of the date and time format symbols of this date format.
2373      *
2374      * @return the date and time format symbols of this date format
2375      * @see #setDateFormatSymbols
2376      */
2377     public DateFormatSymbols getDateFormatSymbols()
2378     {
2379         return (DateFormatSymbols)formatData.clone();
2380     }
2381 
2382     /**
2383      * Sets the date and time format symbols of this date format.
2384      *
2385      * @param newFormatSymbols the new date and time format symbols
2386      * @throws    NullPointerException if the given newFormatSymbols is null
2387      * @see #getDateFormatSymbols
2388      */
2389     public void setDateFormatSymbols(DateFormatSymbols newFormatSymbols)
2390     {
2391         this.formatData = (DateFormatSymbols)newFormatSymbols.clone();
2392         useDateFormatSymbols = true;
2393     }
2394 
2395     /**
2396      * Creates a copy of this <code>SimpleDateFormat</code>. This also
2397      * clones the format's date format symbols.
2398      *
2399      * @return a clone of this <code>SimpleDateFormat</code>
2400      */
2401     @Override
2402     public Object clone() {
2403         SimpleDateFormat other = (SimpleDateFormat) super.clone();
2404         other.formatData = (DateFormatSymbols) formatData.clone();
2405         return other;
2406     }


2453     /**
2454      * Obtains display names map, taking the context into account. Currently only
2455      * the month name pattern 'M' is context dependent.
2456      */
2457     private Map<String, Integer> getDisplayContextNamesMap(int field, Locale locale) {
2458         Map<String, Integer> map = calendar.getDisplayNames(field,
2459             forceStandaloneForm ? Calendar.SHORT_STANDALONE : Calendar.SHORT_FORMAT, locale);
2460         // Get the LONG style
2461         Map<String, Integer> m = calendar.getDisplayNames(field,
2462             forceStandaloneForm ? Calendar.LONG_STANDALONE : Calendar.LONG_FORMAT, locale);
2463         if (m != null) {
2464             map.putAll(m);
2465         }
2466         return map;
2467     }
2468 
2469     /**
2470      * After reading an object from the input stream, the format
2471      * pattern in the object is verified.
2472      *
2473      * @throws    InvalidObjectException if the pattern is invalid
2474      */
2475     @java.io.Serial
2476     private void readObject(ObjectInputStream stream)
2477                          throws IOException, ClassNotFoundException {
2478         stream.defaultReadObject();
2479 
2480         try {
2481             compiledPattern = compile(pattern);
2482         } catch (Exception e) {
2483             throw new InvalidObjectException("invalid pattern");
2484         }
2485 
2486         if (serialVersionOnStream < 1) {
2487             // didn't have defaultCenturyStart field
2488             initializeDefaultCentury();
2489         }
2490         else {
2491             // fill in dependent transient field
2492             parseAmbiguousDatesAsAfter(defaultCenturyStart);
2493         }


< prev index next >