• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 only, as
8  * published by the Free Software Foundation.  Oracle designates this
9  * particular file as subject to the "Classpath" exception as provided
10  * by Oracle in the LICENSE file that accompanied this code.
11  *
12  * This code is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15  * version 2 for more details (a copy is included in the LICENSE file that
16  * accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License version
19  * 2 along with this work; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21  *
22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23  * or visit www.oracle.com if you need additional information or have any
24  * questions.
25  */
26 
27 package java.util;
28 
29 import java.io.BufferedWriter;
30 import java.io.Closeable;
31 import java.io.IOException;
32 import java.io.File;
33 import java.io.FileOutputStream;
34 import java.io.FileNotFoundException;
35 import java.io.Flushable;
36 import java.io.OutputStream;
37 import java.io.OutputStreamWriter;
38 import java.io.PrintStream;
39 import java.io.UnsupportedEncodingException;
40 import java.math.BigDecimal;
41 import java.math.BigInteger;
42 import java.math.MathContext;
43 import java.math.RoundingMode;
44 import java.nio.charset.Charset;
45 import java.nio.charset.IllegalCharsetNameException;
46 import java.nio.charset.UnsupportedCharsetException;
47 import java.text.DateFormatSymbols;
48 import java.text.DecimalFormat;
49 import java.text.DecimalFormatSymbols;
50 import java.text.NumberFormat;
51 import java.time.DateTimeException;
52 import java.time.Instant;
53 import java.time.ZoneId;
54 import java.time.ZoneOffset;
55 import java.time.temporal.ChronoField;
56 import java.time.temporal.TemporalAccessor;
57 import java.time.temporal.TemporalQueries;
58 
59 import libcore.icu.DecimalFormatData;
60 import libcore.icu.LocaleData;
61 import jdk.internal.math.DoubleConsts;
62 import jdk.internal.math.FormattedFloatingDecimal;
63 
64 // Android-changed: Use localized exponent separator for %e.
65 /**
66  * An interpreter for printf-style format strings.  This class provides support
67  * for layout justification and alignment, common formats for numeric, string,
68  * and date/time data, and locale-specific output.  Common Java types such as
69  * {@code byte}, {@link java.math.BigDecimal BigDecimal}, and {@link Calendar}
70  * are supported.  Limited formatting customization for arbitrary user types is
71  * provided through the {@link Formattable} interface.
72  *
73  * <p> Formatters are not necessarily safe for multithreaded access.  Thread
74  * safety is optional and is the responsibility of users of methods in this
75  * class.
76  *
77  * <p> Formatted printing for the Java language is heavily inspired by C's
78  * {@code printf}.  Although the format strings are similar to C, some
79  * customizations have been made to accommodate the Java language and exploit
80  * some of its features.  Also, Java formatting is more strict than C's; for
81  * example, if a conversion is incompatible with a flag, an exception will be
82  * thrown.  In C inapplicable flags are silently ignored.  The format strings
83  * are thus intended to be recognizable to C programmers but not necessarily
84  * completely compatible with those in C.
85  *
86  * <p> Examples of expected usage:
87  *
88  * <blockquote><pre>
89  *   StringBuilder sb = new StringBuilder();
90  *   // Send all output to the Appendable object sb
91  *   Formatter formatter = new Formatter(sb, Locale.US);
92  *
93  *   // Explicit argument indices may be used to re-order output.
94  *   formatter.format("%4$2s %3$2s %2$2s %1$2s", "a", "b", "c", "d")
95  *   // -&gt; " d  c  b  a"
96  *
97  *   // Optional locale as the first argument can be used to get
98  *   // locale-specific formatting of numbers.  The precision and width can be
99  *   // given to round and align the value.
100  *   formatter.format(Locale.FRANCE, "e = %+10.4f", Math.E);
101  *   // -&gt; "e =    +2,7183"
102  *
103  *   // The '(' numeric flag may be used to format negative numbers with
104  *   // parentheses rather than a minus sign.  Group separators are
105  *   // automatically inserted.
106  *   formatter.format("Amount gained or lost since last statement: $ %(,.2f",
107  *                    balanceDelta);
108  *   // -&gt; "Amount gained or lost since last statement: $ (6,217.58)"
109  * </pre></blockquote>
110  *
111  * <p> Convenience methods for common formatting requests exist as illustrated
112  * by the following invocations:
113  *
114  * <blockquote><pre>
115  *   // Writes a formatted string to System.out.
116  *   System.out.format("Local time: %tT", Calendar.getInstance());
117  *   // -&gt; "Local time: 13:34:18"
118  *
119  *   // Writes formatted output to System.err.
120  *   System.err.printf("Unable to open file '%1$s': %2$s",
121  *                     fileName, exception.getMessage());
122  *   // -&gt; "Unable to open file 'food': No such file or directory"
123  * </pre></blockquote>
124  *
125  * <p> Like C's {@code sprintf(3)}, Strings may be formatted using the static
126  * method {@link String#format(String,Object...) String.format}:
127  *
128  * <blockquote><pre>
129  *   // Format a string containing a date.
130  *   import java.util.Calendar;
131  *   import java.util.GregorianCalendar;
132  *   import static java.util.Calendar.*;
133  *
134  *   Calendar c = new GregorianCalendar(1995, MAY, 23);
135  *   String s = String.format("Duke's Birthday: %1$tb %1$te, %1$tY", c);
136  *   // -&gt; s == "Duke's Birthday: May 23, 1995"
137  * </pre></blockquote>
138  *
139  * <h3><a name="org">Organization</a></h3>
140  *
141  * <p> This specification is divided into two sections.  The first section, <a
142  * href="#summary">Summary</a>, covers the basic formatting concepts.  This
143  * section is intended for users who want to get started quickly and are
144  * familiar with formatted printing in other programming languages.  The second
145  * section, <a href="#detail">Details</a>, covers the specific implementation
146  * details.  It is intended for users who want more precise specification of
147  * formatting behavior.
148  *
149  * <h3><a name="summary">Summary</a></h3>
150  *
151  * <p> This section is intended to provide a brief overview of formatting
152  * concepts.  For precise behavioral details, refer to the <a
153  * href="#detail">Details</a> section.
154  *
155  * <h4><a name="syntax">Format String Syntax</a></h4>
156  *
157  * <p> Every method which produces formatted output requires a <i>format
158  * string</i> and an <i>argument list</i>.  The format string is a {@link
159  * String} which may contain fixed text and one or more embedded <i>format
160  * specifiers</i>.  Consider the following example:
161  *
162  * <blockquote><pre>
163  *   Calendar c = ...;
164  *   String s = String.format("Duke's Birthday: %1$tm %1$te,%1$tY", c);
165  * </pre></blockquote>
166  *
167  * This format string is the first argument to the {@code format} method.  It
168  * contains three format specifiers "{@code %1$tm}", "{@code %1$te}", and
169  * "{@code %1$tY}" which indicate how the arguments should be processed and
170  * where they should be inserted in the text.  The remaining portions of the
171  * format string are fixed text including {@code "Dukes Birthday: "} and any
172  * other spaces or punctuation.
173  *
174  * The argument list consists of all arguments passed to the method after the
175  * format string.  In the above example, the argument list is of size one and
176  * consists of the {@link java.util.Calendar Calendar} object {@code c}.
177  *
178  * <ul>
179  *
180  * <li> The format specifiers for general, character, and numeric types have
181  * the following syntax:
182  *
183  * <blockquote><pre>
184  *   %[argument_index$][flags][width][.precision]conversion
185  * </pre></blockquote>
186  *
187  * <p> The optional <i>argument_index</i> is a decimal integer indicating the
188  * position of the argument in the argument list.  The first argument is
189  * referenced by "{@code 1$}", the second by "{@code 2$}", etc.
190  *
191  * <p> The optional <i>flags</i> is a set of characters that modify the output
192  * format.  The set of valid flags depends on the conversion.
193  *
194  * <p> The optional <i>width</i> is a positive decimal integer indicating
195  * the minimum number of characters to be written to the output.
196  *
197  * <p> The optional <i>precision</i> is a non-negative decimal integer usually
198  * used to restrict the number of characters.  The specific behavior depends on
199  * the conversion.
200  *
201  * <p> The required <i>conversion</i> is a character indicating how the
202  * argument should be formatted.  The set of valid conversions for a given
203  * argument depends on the argument's data type.
204  *
205  * <li> The format specifiers for types which are used to represents dates and
206  * times have the following syntax:
207  *
208  * <blockquote><pre>
209  *   %[argument_index$][flags][width]conversion
210  * </pre></blockquote>
211  *
212  * <p> The optional <i>argument_index</i>, <i>flags</i> and <i>width</i> are
213  * defined as above.
214  *
215  * <p> The required <i>conversion</i> is a two character sequence.  The first
216  * character is {@code 't'} or {@code 'T'}.  The second character indicates
217  * the format to be used.  These characters are similar to but not completely
218  * identical to those defined by GNU {@code date} and POSIX
219  * {@code strftime(3c)}.
220  *
221  * <li> The format specifiers which do not correspond to arguments have the
222  * following syntax:
223  *
224  * <blockquote><pre>
225  *   %[flags][width]conversion
226  * </pre></blockquote>
227  *
228  * <p> The optional <i>flags</i> and <i>width</i> is defined as above.
229  *
230  * <p> The required <i>conversion</i> is a character indicating content to be
231  * inserted in the output.
232  *
233  * </ul>
234  *
235  * <h4> Conversions </h4>
236  *
237  * <p> Conversions are divided into the following categories:
238  *
239  * <ol>
240  *
241  * <li> <b>General</b> - may be applied to any argument
242  * type
243  *
244  * <li> <b>Character</b> - may be applied to basic types which represent
245  * Unicode characters: {@code char}, {@link Character}, {@code byte}, {@link
246  * Byte}, {@code short}, and {@link Short}. This conversion may also be
247  * applied to the types {@code int} and {@link Integer} when {@link
248  * Character#isValidCodePoint} returns {@code true}
249  *
250  * <li> <b>Numeric</b>
251  *
252  * <ol>
253  *
254  * <li> <b>Integral</b> - may be applied to Java integral types: {@code byte},
255  * {@link Byte}, {@code short}, {@link Short}, {@code int} and {@link
256  * Integer}, {@code long}, {@link Long}, and {@link java.math.BigInteger
257  * BigInteger} (but not {@code char} or {@link Character})
258  *
259  * <li><b>Floating Point</b> - may be applied to Java floating-point types:
260  * {@code float}, {@link Float}, {@code double}, {@link Double}, and {@link
261  * java.math.BigDecimal BigDecimal}
262  *
263  * </ol>
264  *
265  * <li> <b>Date/Time</b> - may be applied to Java types which are capable of
266  * encoding a date or time: {@code long}, {@link Long}, {@link Calendar},
267  * {@link Date} and {@link TemporalAccessor TemporalAccessor}
268  *
269  * <li> <b>Percent</b> - produces a literal {@code '%'}
270  * (<tt>'&#92;u0025'</tt>)
271  *
272  * <li> <b>Line Separator</b> - produces the platform-specific line separator
273  *
274  * </ol>
275  *
276  * <p> The following table summarizes the supported conversions.  Conversions
277  * denoted by an upper-case character (i.e. {@code 'B'}, {@code 'H'},
278  * {@code 'S'}, {@code 'C'}, {@code 'X'}, {@code 'E'}, {@code 'G'},
279  * {@code 'A'}, and {@code 'T'}) are the same as those for the corresponding
280  * lower-case conversion characters except that the result is converted to
281  * upper case according to the rules of the prevailing {@link java.util.Locale
282  * Locale}.  The result is equivalent to the following invocation of {@link
283  * String#toUpperCase()}
284  *
285  * <pre>
286  *    out.toUpperCase() </pre>
287  *
288  * <table cellpadding=5 summary="genConv">
289  *
290  * <tr><th valign="bottom"> Conversion
291  *     <th valign="bottom"> Argument Category
292  *     <th valign="bottom"> Description
293  *
294  * <tr><td valign="top"> {@code 'b'}, {@code 'B'}
295  *     <td valign="top"> general
296  *     <td> If the argument <i>arg</i> is {@code null}, then the result is
297  *     "{@code false}".  If <i>arg</i> is a {@code boolean} or {@link
298  *     Boolean}, then the result is the string returned by {@link
299  *     String#valueOf(boolean) String.valueOf(arg)}.  Otherwise, the result is
300  *     "true".
301  *
302  * <tr><td valign="top"> {@code 'h'}, {@code 'H'}
303  *     <td valign="top"> general
304  *     <td> If the argument <i>arg</i> is {@code null}, then the result is
305  *     "{@code null}".  Otherwise, the result is obtained by invoking
306  *     {@code Integer.toHexString(arg.hashCode())}.
307  *
308  * <tr><td valign="top"> {@code 's'}, {@code 'S'}
309  *     <td valign="top"> general
310  *     <td> If the argument <i>arg</i> is {@code null}, then the result is
311  *     "{@code null}".  If <i>arg</i> implements {@link Formattable}, then
312  *     {@link Formattable#formatTo arg.formatTo} is invoked. Otherwise, the
313  *     result is obtained by invoking {@code arg.toString()}.
314  *
315  * <tr><td valign="top">{@code 'c'}, {@code 'C'}
316  *     <td valign="top"> character
317  *     <td> The result is a Unicode character
318  *
319  * <tr><td valign="top">{@code 'd'}
320  *     <td valign="top"> integral
321  *     <td> The result is formatted as a decimal integer
322  *
323  * <tr><td valign="top">{@code 'o'}
324  *     <td valign="top"> integral
325  *     <td> The result is formatted as an octal integer
326  *
327  * <tr><td valign="top">{@code 'x'}, {@code 'X'}
328  *     <td valign="top"> integral
329  *     <td> The result is formatted as a hexadecimal integer
330  *
331  * <tr><td valign="top">{@code 'e'}, {@code 'E'}
332  *     <td valign="top"> floating point
333  *     <td> The result is formatted as a decimal number in computerized
334  *     scientific notation
335  *
336  * <tr><td valign="top">{@code 'f'}
337  *     <td valign="top"> floating point
338  *     <td> The result is formatted as a decimal number
339  *
340  * <tr><td valign="top">{@code 'g'}, {@code 'G'}
341  *     <td valign="top"> floating point
342  *     <td> The result is formatted using computerized scientific notation or
343  *     decimal format, depending on the precision and the value after rounding.
344  *
345  * <tr><td valign="top">{@code 'a'}, {@code 'A'}
346  *     <td valign="top"> floating point
347  *     <td> The result is formatted as a hexadecimal floating-point number with
348  *     a significand and an exponent. This conversion is <b>not</b> supported
349  *     for the {@code BigDecimal} type despite the latter's being in the
350  *     <i>floating point</i> argument category.
351  *
352  * <tr><td valign="top">{@code 't'}, {@code 'T'}
353  *     <td valign="top"> date/time
354  *     <td> Prefix for date and time conversion characters.  See <a
355  *     href="#dt">Date/Time Conversions</a>.
356  *
357  * <tr><td valign="top">{@code '%'}
358  *     <td valign="top"> percent
359  *     <td> The result is a literal {@code '%'} (<tt>'&#92;u0025'</tt>)
360  *
361  * <tr><td valign="top">{@code 'n'}
362  *     <td valign="top"> line separator
363  *     <td> The result is the platform-specific line separator
364  *
365  * </table>
366  *
367  * <p> Any characters not explicitly defined as conversions are illegal and are
368  * reserved for future extensions.
369  *
370  * <h4><a name="dt">Date/Time Conversions</a></h4>
371  *
372  * <p> The following date and time conversion suffix characters are defined for
373  * the {@code 't'} and {@code 'T'} conversions.  The types are similar to but
374  * not completely identical to those defined by GNU {@code date} and POSIX
375  * {@code strftime(3c)}.  Additional conversion types are provided to access
376  * Java-specific functionality (e.g. {@code 'L'} for milliseconds within the
377  * second).
378  *
379  * <p> The following conversion characters are used for formatting times:
380  *
381  * <table cellpadding=5 summary="time">
382  *
383  * <tr><td valign="top"> {@code 'H'}
384  *     <td> Hour of the day for the 24-hour clock, formatted as two digits with
385  *     a leading zero as necessary i.e. {@code 00 - 23}.
386  *
387  * <tr><td valign="top">{@code 'I'}
388  *     <td> Hour for the 12-hour clock, formatted as two digits with a leading
389  *     zero as necessary, i.e.  {@code 01 - 12}.
390  *
391  * <tr><td valign="top">{@code 'k'}
392  *     <td> Hour of the day for the 24-hour clock, i.e. {@code 0 - 23}.
393  *
394  * <tr><td valign="top">{@code 'l'}
395  *     <td> Hour for the 12-hour clock, i.e. {@code 1 - 12}.
396  *
397  * <tr><td valign="top">{@code 'M'}
398  *     <td> Minute within the hour formatted as two digits with a leading zero
399  *     as necessary, i.e.  {@code 00 - 59}.
400  *
401  * <tr><td valign="top">{@code 'S'}
402  *     <td> Seconds within the minute, formatted as two digits with a leading
403  *     zero as necessary, i.e. {@code 00 - 60} ("{@code 60}" is a special
404  *     value required to support leap seconds).
405  *
406  * <tr><td valign="top">{@code 'L'}
407  *     <td> Millisecond within the second formatted as three digits with
408  *     leading zeros as necessary, i.e. {@code 000 - 999}.
409  *
410  * <tr><td valign="top">{@code 'N'}
411  *     <td> Nanosecond within the second, formatted as nine digits with leading
412  *     zeros as necessary, i.e. {@code 000000000 - 999999999}.
413  *
414  * <tr><td valign="top">{@code 'p'}
415  *     <td> Locale-specific {@linkplain
416  *     java.text.DateFormatSymbols#getAmPmStrings morning or afternoon} marker
417  *     in lower case, e.g."{@code am}" or "{@code pm}". Use of the conversion
418  *     prefix {@code 'T'} forces this output to upper case.
419  *
420  * <tr><td valign="top">{@code 'z'}
421  *     <td> <a href="http://www.ietf.org/rfc/rfc0822.txt">RFC&nbsp;822</a>
422  *     style numeric time zone offset from GMT, e.g. {@code -0800}.  This
423  *     value will be adjusted as necessary for Daylight Saving Time.  For
424  *     {@code long}, {@link Long}, and {@link Date} the time zone used is
425  *     the {@linkplain TimeZone#getDefault() default time zone} for this
426  *     instance of the Java virtual machine.
427  *
428  * <tr><td valign="top">{@code 'Z'}
429  *     <td> A string representing the abbreviation for the time zone.  This
430  *     value will be adjusted as necessary for Daylight Saving Time.  For
431  *     {@code long}, {@link Long}, and {@link Date} the  time zone used is
432  *     the {@linkplain TimeZone#getDefault() default time zone} for this
433  *     instance of the Java virtual machine.  The Formatter's locale will
434  *     supersede the locale of the argument (if any).
435  *
436  * <tr><td valign="top">{@code 's'}
437  *     <td> Seconds since the beginning of the epoch starting at 1 January 1970
438  *     {@code 00:00:00} UTC, i.e. {@code Long.MIN_VALUE/1000} to
439  *     {@code Long.MAX_VALUE/1000}.
440  *
441  * <tr><td valign="top">{@code 'Q'}
442  *     <td> Milliseconds since the beginning of the epoch starting at 1 January
443  *     1970 {@code 00:00:00} UTC, i.e. {@code Long.MIN_VALUE} to
444  *     {@code Long.MAX_VALUE}.
445  *
446  * </table>
447  *
448  * <p> The following conversion characters are used for formatting dates:
449  *
450  * <table cellpadding=5 summary="date">
451  *
452  * <tr><td valign="top">{@code 'B'}
453  *     <td> Locale-specific {@linkplain java.text.DateFormatSymbols#getMonths
454  *     full month name}, e.g. {@code "January"}, {@code "February"}.
455  *
456  * <tr><td valign="top">{@code 'b'}
457  *     <td> Locale-specific {@linkplain
458  *     java.text.DateFormatSymbols#getShortMonths abbreviated month name},
459  *     e.g. {@code "Jan"}, {@code "Feb"}.
460  *
461  * <tr><td valign="top">{@code 'h'}
462  *     <td> Same as {@code 'b'}.
463  *
464  * <tr><td valign="top">{@code 'A'}
465  *     <td> Locale-specific full name of the {@linkplain
466  *     java.text.DateFormatSymbols#getWeekdays day of the week},
467  *     e.g. {@code "Sunday"}, {@code "Monday"}
468  *
469  * <tr><td valign="top">{@code 'a'}
470  *     <td> Locale-specific short name of the {@linkplain
471  *     java.text.DateFormatSymbols#getShortWeekdays day of the week},
472  *     e.g. {@code "Sun"}, {@code "Mon"}
473  *
474  * <tr><td valign="top">{@code 'C'}
475  *     <td> Four-digit year divided by {@code 100}, formatted as two digits
476  *     with leading zero as necessary, i.e. {@code 00 - 99}
477  *
478  * <tr><td valign="top">{@code 'Y'}
479  *     <td> Year, formatted as at least four digits with leading zeros as
480  *     necessary, e.g. {@code 0092} equals {@code 92} CE for the Gregorian
481  *     calendar.
482  *
483  * <tr><td valign="top">{@code 'y'}
484  *     <td> Last two digits of the year, formatted with leading zeros as
485  *     necessary, i.e. {@code 00 - 99}.
486  *
487  * <tr><td valign="top">{@code 'j'}
488  *     <td> Day of year, formatted as three digits with leading zeros as
489  *     necessary, e.g. {@code 001 - 366} for the Gregorian calendar.
490  *
491  * <tr><td valign="top">{@code 'm'}
492  *     <td> Month, formatted as two digits with leading zeros as necessary,
493  *     i.e. {@code 01 - 13}.
494  *
495  * <tr><td valign="top">{@code 'd'}
496  *     <td> Day of month, formatted as two digits with leading zeros as
497  *     necessary, i.e. {@code 01 - 31}
498  *
499  * <tr><td valign="top">{@code 'e'}
500  *     <td> Day of month, formatted as two digits, i.e. {@code 1 - 31}.
501  *
502  * </table>
503  *
504  * <p> The following conversion characters are used for formatting common
505  * date/time compositions.
506  *
507  * <table cellpadding=5 summary="composites">
508  *
509  * <tr><td valign="top">{@code 'R'}
510  *     <td> Time formatted for the 24-hour clock as {@code "%tH:%tM"}
511  *
512  * <tr><td valign="top">{@code 'T'}
513  *     <td> Time formatted for the 24-hour clock as {@code "%tH:%tM:%tS"}.
514  *
515  * <tr><td valign="top">{@code 'r'}
516  *     <td> Time formatted for the 12-hour clock as {@code "%tI:%tM:%tS %Tp"}.
517  *     The location of the morning or afternoon marker ({@code '%Tp'}) may be
518  *     locale-dependent.
519  *
520  * <tr><td valign="top">{@code 'D'}
521  *     <td> Date formatted as {@code "%tm/%td/%ty"}.
522  *
523  * <tr><td valign="top">{@code 'F'}
524  *     <td> <a href="http://www.w3.org/TR/NOTE-datetime">ISO&nbsp;8601</a>
525  *     complete date formatted as {@code "%tY-%tm-%td"}.
526  *
527  * <tr><td valign="top">{@code 'c'}
528  *     <td> Date and time formatted as {@code "%ta %tb %td %tT %tZ %tY"},
529  *     e.g. {@code "Sun Jul 20 16:17:00 EDT 1969"}.
530  *
531  * </table>
532  *
533  * <p> Any characters not explicitly defined as date/time conversion suffixes
534  * are illegal and are reserved for future extensions.
535  *
536  * <h4> Flags </h4>
537  *
538  * <p> The following table summarizes the supported flags.  <i>y</i> means the
539  * flag is supported for the indicated argument types.
540  *
541  * <table cellpadding=5 summary="genConv">
542  *
543  * <tr><th valign="bottom"> Flag <th valign="bottom"> General
544  *     <th valign="bottom"> Character <th valign="bottom"> Integral
545  *     <th valign="bottom"> Floating Point
546  *     <th valign="bottom"> Date/Time
547  *     <th valign="bottom"> Description
548  *
549  * <tr><td> '-' <td align="center" valign="top"> y
550  *     <td align="center" valign="top"> y
551  *     <td align="center" valign="top"> y
552  *     <td align="center" valign="top"> y
553  *     <td align="center" valign="top"> y
554  *     <td> The result will be left-justified.
555  *
556  * <tr><td> '#' <td align="center" valign="top"> y<sup>1</sup>
557  *     <td align="center" valign="top"> -
558  *     <td align="center" valign="top"> y<sup>3</sup>
559  *     <td align="center" valign="top"> y
560  *     <td align="center" valign="top"> -
561  *     <td> The result should use a conversion-dependent alternate form
562  *
563  * <tr><td> '+' <td align="center" valign="top"> -
564  *     <td align="center" valign="top"> -
565  *     <td align="center" valign="top"> y<sup>4</sup>
566  *     <td align="center" valign="top"> y
567  *     <td align="center" valign="top"> -
568  *     <td> The result will always include a sign
569  *
570  * <tr><td> '&nbsp;&nbsp;' <td align="center" valign="top"> -
571  *     <td align="center" valign="top"> -
572  *     <td align="center" valign="top"> y<sup>4</sup>
573  *     <td align="center" valign="top"> y
574  *     <td align="center" valign="top"> -
575  *     <td> The result will include a leading space for positive values
576  *
577  * <tr><td> '0' <td align="center" valign="top"> -
578  *     <td align="center" valign="top"> -
579  *     <td align="center" valign="top"> y
580  *     <td align="center" valign="top"> y
581  *     <td align="center" valign="top"> -
582  *     <td> The result will be zero-padded
583  *
584  * <tr><td> ',' <td align="center" valign="top"> -
585  *     <td align="center" valign="top"> -
586  *     <td align="center" valign="top"> y<sup>2</sup>
587  *     <td align="center" valign="top"> y<sup>5</sup>
588  *     <td align="center" valign="top"> -
589  *     <td> The result will include locale-specific {@linkplain
590  *     java.text.DecimalFormatSymbols#getGroupingSeparator grouping separators}
591  *
592  * <tr><td> '(' <td align="center" valign="top"> -
593  *     <td align="center" valign="top"> -
594  *     <td align="center" valign="top"> y<sup>4</sup>
595  *     <td align="center" valign="top"> y<sup>5</sup>
596  *     <td align="center"> -
597  *     <td> The result will enclose negative numbers in parentheses
598  *
599  * </table>
600  *
601  * <p> <sup>1</sup> Depends on the definition of {@link Formattable}.
602  *
603  * <p> <sup>2</sup> For {@code 'd'} conversion only.
604  *
605  * <p> <sup>3</sup> For {@code 'o'}, {@code 'x'}, and {@code 'X'}
606  * conversions only.
607  *
608  * <p> <sup>4</sup> For {@code 'd'}, {@code 'o'}, {@code 'x'}, and
609  * {@code 'X'} conversions applied to {@link java.math.BigInteger BigInteger}
610  * or {@code 'd'} applied to {@code byte}, {@link Byte}, {@code short}, {@link
611  * Short}, {@code int} and {@link Integer}, {@code long}, and {@link Long}.
612  *
613  * <p> <sup>5</sup> For {@code 'e'}, {@code 'E'}, {@code 'f'},
614  * {@code 'g'}, and {@code 'G'} conversions only.
615  *
616  * <p> Any characters not explicitly defined as flags are illegal and are
617  * reserved for future extensions.
618  *
619  * <h4> Width </h4>
620  *
621  * <p> The width is the minimum number of characters to be written to the
622  * output.  For the line separator conversion, width is not applicable; if it
623  * is provided, an exception will be thrown.
624  *
625  * <h4> Precision </h4>
626  *
627  * <p> For general argument types, the precision is the maximum number of
628  * characters to be written to the output.
629  *
630  * <p> For the floating-point conversions {@code 'a'}, {@code 'A'}, {@code 'e'},
631  * {@code 'E'}, and {@code 'f'} the precision is the number of digits after the
632  * radix point.  If the conversion is {@code 'g'} or {@code 'G'}, then the
633  * precision is the total number of digits in the resulting magnitude after
634  * rounding.
635  *
636  * <p> For character, integral, and date/time argument types and the percent
637  * and line separator conversions, the precision is not applicable; if a
638  * precision is provided, an exception will be thrown.
639  *
640  * <h4> Argument Index </h4>
641  *
642  * <p> The argument index is a decimal integer indicating the position of the
643  * argument in the argument list.  The first argument is referenced by
644  * "{@code 1$}", the second by "{@code 2$}", etc.
645  *
646  * <p> Another way to reference arguments by position is to use the
647  * {@code '<'} (<tt>'&#92;u003c'</tt>) flag, which causes the argument for
648  * the previous format specifier to be re-used.  For example, the following two
649  * statements would produce identical strings:
650  *
651  * <blockquote><pre>
652  *   Calendar c = ...;
653  *   String s1 = String.format("Duke's Birthday: %1$tm %1$te,%1$tY", c);
654  *
655  *   String s2 = String.format("Duke's Birthday: %1$tm %&lt;te,%&lt;tY", c);
656  * </pre></blockquote>
657  *
658  * <hr>
659  * <h3><a name="detail">Details</a></h3>
660  *
661  * <p> This section is intended to provide behavioral details for formatting,
662  * including conditions and exceptions, supported data types, localization, and
663  * interactions between flags, conversions, and data types.  For an overview of
664  * formatting concepts, refer to the <a href="#summary">Summary</a>
665  *
666  * <p> Any characters not explicitly defined as conversions, date/time
667  * conversion suffixes, or flags are illegal and are reserved for
668  * future extensions.  Use of such a character in a format string will
669  * cause an {@link UnknownFormatConversionException} or {@link
670  * UnknownFormatFlagsException} to be thrown.
671  *
672  * <p> If the format specifier contains a width or precision with an invalid
673  * value or which is otherwise unsupported, then a {@link
674  * IllegalFormatWidthException} or {@link IllegalFormatPrecisionException}
675  * respectively will be thrown.
676  *
677  * <p> If a format specifier contains a conversion character that is not
678  * applicable to the corresponding argument, then an {@link
679  * IllegalFormatConversionException} will be thrown.
680  *
681  * <p> All specified exceptions may be thrown by any of the {@code format}
682  * methods of {@code Formatter} as well as by any {@code format} convenience
683  * methods such as {@link String#format(String,Object...) String.format} and
684  * {@link java.io.PrintStream#printf(String,Object...) PrintStream.printf}.
685  *
686  * <p> Conversions denoted by an upper-case character (i.e. {@code 'B'},
687  * {@code 'H'}, {@code 'S'}, {@code 'C'}, {@code 'X'}, {@code 'E'},
688  * {@code 'G'}, {@code 'A'}, and {@code 'T'}) are the same as those for the
689  * corresponding lower-case conversion characters except that the result is
690  * converted to upper case according to the rules of the prevailing {@link
691  * java.util.Locale Locale}.  The result is equivalent to the following
692  * invocation of {@link String#toUpperCase()}
693  *
694  * <pre>
695  *    out.toUpperCase() </pre>
696  *
697  * <h4><a name="dgen">General</a></h4>
698  *
699  * <p> The following general conversions may be applied to any argument type:
700  *
701  * <table cellpadding=5 summary="dgConv">
702  *
703  * <tr><td valign="top"> {@code 'b'}
704  *     <td valign="top"> <tt>'&#92;u0062'</tt>
705  *     <td> Produces either "{@code true}" or "{@code false}" as returned by
706  *     {@link Boolean#toString(boolean)}.
707  *
708  *     <p> If the argument is {@code null}, then the result is
709  *     "{@code false}".  If the argument is a {@code boolean} or {@link
710  *     Boolean}, then the result is the string returned by {@link
711  *     String#valueOf(boolean) String.valueOf()}.  Otherwise, the result is
712  *     "{@code true}".
713  *
714  *     <p> If the {@code '#'} flag is given, then a {@link
715  *     FormatFlagsConversionMismatchException} will be thrown.
716  *
717  * <tr><td valign="top"> {@code 'B'}
718  *     <td valign="top"> <tt>'&#92;u0042'</tt>
719  *     <td> The upper-case variant of {@code 'b'}.
720  *
721  * <tr><td valign="top"> {@code 'h'}
722  *     <td valign="top"> <tt>'&#92;u0068'</tt>
723  *     <td> Produces a string representing the hash code value of the object.
724  *
725  *     <p> If the argument, <i>arg</i> is {@code null}, then the
726  *     result is "{@code null}".  Otherwise, the result is obtained
727  *     by invoking {@code Integer.toHexString(arg.hashCode())}.
728  *
729  *     <p> If the {@code '#'} flag is given, then a {@link
730  *     FormatFlagsConversionMismatchException} will be thrown.
731  *
732  * <tr><td valign="top"> {@code 'H'}
733  *     <td valign="top"> <tt>'&#92;u0048'</tt>
734  *     <td> The upper-case variant of {@code 'h'}.
735  *
736  * <tr><td valign="top"> {@code 's'}
737  *     <td valign="top"> <tt>'&#92;u0073'</tt>
738  *     <td> Produces a string.
739  *
740  *     <p> If the argument is {@code null}, then the result is
741  *     "{@code null}".  If the argument implements {@link Formattable}, then
742  *     its {@link Formattable#formatTo formatTo} method is invoked.
743  *     Otherwise, the result is obtained by invoking the argument's
744  *     {@code toString()} method.
745  *
746  *     <p> If the {@code '#'} flag is given and the argument is not a {@link
747  *     Formattable} , then a {@link FormatFlagsConversionMismatchException}
748  *     will be thrown.
749  *
750  * <tr><td valign="top"> {@code 'S'}
751  *     <td valign="top"> <tt>'&#92;u0053'</tt>
752  *     <td> The upper-case variant of {@code 's'}.
753  *
754  * </table>
755  *
756  * <p> The following <a name="dFlags">flags</a> apply to general conversions:
757  *
758  * <table cellpadding=5 summary="dFlags">
759  *
760  * <tr><td valign="top"> {@code '-'}
761  *     <td valign="top"> <tt>'&#92;u002d'</tt>
762  *     <td> Left justifies the output.  Spaces (<tt>'&#92;u0020'</tt>) will be
763  *     added at the end of the converted value as required to fill the minimum
764  *     width of the field.  If the width is not provided, then a {@link
765  *     MissingFormatWidthException} will be thrown.  If this flag is not given
766  *     then the output will be right-justified.
767  *
768  * <tr><td valign="top"> {@code '#'}
769  *     <td valign="top"> <tt>'&#92;u0023'</tt>
770  *     <td> Requires the output use an alternate form.  The definition of the
771  *     form is specified by the conversion.
772  *
773  * </table>
774  *
775  * <p> The <a name="genWidth">width</a> is the minimum number of characters to
776  * be written to the
777  * output.  If the length of the converted value is less than the width then
778  * the output will be padded by <tt>'&nbsp;&nbsp;'</tt> (<tt>'&#92;u0020'</tt>)
779  * until the total number of characters equals the width.  The padding is on
780  * the left by default.  If the {@code '-'} flag is given, then the padding
781  * will be on the right.  If the width is not specified then there is no
782  * minimum.
783  *
784  * <p> The precision is the maximum number of characters to be written to the
785  * output.  The precision is applied before the width, thus the output will be
786  * truncated to {@code precision} characters even if the width is greater than
787  * the precision.  If the precision is not specified then there is no explicit
788  * limit on the number of characters.
789  *
790  * <h4><a name="dchar">Character</a></h4>
791  *
792  * This conversion may be applied to {@code char} and {@link Character}.  It
793  * may also be applied to the types {@code byte}, {@link Byte},
794  * {@code short}, and {@link Short}, {@code int} and {@link Integer} when
795  * {@link Character#isValidCodePoint} returns {@code true}.  If it returns
796  * {@code false} then an {@link IllegalFormatCodePointException} will be
797  * thrown.
798  *
799  * <table cellpadding=5 summary="charConv">
800  *
801  * <tr><td valign="top"> {@code 'c'}
802  *     <td valign="top"> <tt>'&#92;u0063'</tt>
803  *     <td> Formats the argument as a Unicode character as described in <a
804  *     href="../lang/Character.html#unicode">Unicode Character
805  *     Representation</a>.  This may be more than one 16-bit {@code char} in
806  *     the case where the argument represents a supplementary character.
807  *
808  *     <p> If the {@code '#'} flag is given, then a {@link
809  *     FormatFlagsConversionMismatchException} will be thrown.
810  *
811  * <tr><td valign="top"> {@code 'C'}
812  *     <td valign="top"> <tt>'&#92;u0043'</tt>
813  *     <td> The upper-case variant of {@code 'c'}.
814  *
815  * </table>
816  *
817  * <p> The {@code '-'} flag defined for <a href="#dFlags">General
818  * conversions</a> applies.  If the {@code '#'} flag is given, then a {@link
819  * FormatFlagsConversionMismatchException} will be thrown.
820  *
821  * <p> The width is defined as for <a href="#genWidth">General conversions</a>.
822  *
823  * <p> The precision is not applicable.  If the precision is specified then an
824  * {@link IllegalFormatPrecisionException} will be thrown.
825  *
826  * <h4><a name="dnum">Numeric</a></h4>
827  *
828  * <p> Numeric conversions are divided into the following categories:
829  *
830  * <ol>
831  *
832  * <li> <a href="#dnint"><b>Byte, Short, Integer, and Long</b></a>
833  *
834  * <li> <a href="#dnbint"><b>BigInteger</b></a>
835  *
836  * <li> <a href="#dndec"><b>Float and Double</b></a>
837  *
838  * <li> <a href="#dnbdec"><b>BigDecimal</b></a>
839  *
840  * </ol>
841  *
842  * <p> Numeric types will be formatted according to the following algorithm:
843  *
844  * <p><b><a name="L10nAlgorithm"> Number Localization Algorithm</a></b>
845  *
846  * <p> After digits are obtained for the integer part, fractional part, and
847  * exponent (as appropriate for the data type), the following transformation
848  * is applied:
849  *
850  * <ol>
851  *
852  * <li> Each digit character <i>d</i> in the string is replaced by a
853  * locale-specific digit computed relative to the current locale's
854  * {@linkplain java.text.DecimalFormatSymbols#getZeroDigit() zero digit}
855  * <i>z</i>; that is <i>d&nbsp;-&nbsp;</i> {@code '0'}
856  * <i>&nbsp;+&nbsp;z</i>.
857  *
858  * <li> If a decimal separator is present, a locale-specific {@linkplain
859  * java.text.DecimalFormatSymbols#getDecimalSeparator decimal separator} is
860  * substituted.
861  *
862  * <li> If the {@code ','} (<tt>'&#92;u002c'</tt>)
863  * <a name="L10nGroup">flag</a> is given, then the locale-specific {@linkplain
864  * java.text.DecimalFormatSymbols#getGroupingSeparator grouping separator} is
865  * inserted by scanning the integer part of the string from least significant
866  * to most significant digits and inserting a separator at intervals defined by
867  * the locale's {@linkplain java.text.DecimalFormat#getGroupingSize() grouping
868  * size}.
869  *
870  * <li> If the {@code '0'} flag is given, then the locale-specific {@linkplain
871  * java.text.DecimalFormatSymbols#getZeroDigit() zero digits} are inserted
872  * after the sign character, if any, and before the first non-zero digit, until
873  * the length of the string is equal to the requested field width.
874  *
875  * <li> If the value is negative and the {@code '('} flag is given, then a
876  * {@code '('} (<tt>'&#92;u0028'</tt>) is prepended and a {@code ')'}
877  * (<tt>'&#92;u0029'</tt>) is appended.
878  *
879  * <li> If the value is negative (or floating-point negative zero) and
880  * {@code '('} flag is not given, then a {@code '-'} (<tt>'&#92;u002d'</tt>)
881  * is prepended.
882  *
883  * <li> If the {@code '+'} flag is given and the value is positive or zero (or
884  * floating-point positive zero), then a {@code '+'} (<tt>'&#92;u002b'</tt>)
885  * will be prepended.
886  *
887  * </ol>
888  *
889  * <p> If the value is NaN or positive infinity the literal strings "NaN" or
890  * "Infinity" respectively, will be output.  If the value is negative infinity,
891  * then the output will be "(Infinity)" if the {@code '('} flag is given
892  * otherwise the output will be "-Infinity".  These values are not localized.
893  *
894  * <p><a name="dnint"><b> Byte, Short, Integer, and Long </b></a>
895  *
896  * <p> The following conversions may be applied to {@code byte}, {@link Byte},
897  * {@code short}, {@link Short}, {@code int} and {@link Integer},
898  * {@code long}, and {@link Long}.
899  *
900  * <table cellpadding=5 summary="IntConv">
901  *
902  * <tr><td valign="top"> {@code 'd'}
903  *     <td valign="top"> <tt>'&#92;u0064'</tt>
904  *     <td> Formats the argument as a decimal integer. The <a
905  *     href="#L10nAlgorithm">localization algorithm</a> is applied.
906  *
907  *     <p> If the {@code '0'} flag is given and the value is negative, then
908  *     the zero padding will occur after the sign.
909  *
910  *     <p> If the {@code '#'} flag is given then a {@link
911  *     FormatFlagsConversionMismatchException} will be thrown.
912  *
913  * <tr><td valign="top"> {@code 'o'}
914  *     <td valign="top"> <tt>'&#92;u006f'</tt>
915  *     <td> Formats the argument as an integer in base eight.  No localization
916  *     is applied.
917  *
918  *     <p> If <i>x</i> is negative then the result will be an unsigned value
919  *     generated by adding 2<sup>n</sup> to the value where {@code n} is the
920  *     number of bits in the type as returned by the static {@code SIZE} field
921  *     in the {@linkplain Byte#SIZE Byte}, {@linkplain Short#SIZE Short},
922  *     {@linkplain Integer#SIZE Integer}, or {@linkplain Long#SIZE Long}
923  *     classes as appropriate.
924  *
925  *     <p> If the {@code '#'} flag is given then the output will always begin
926  *     with the radix indicator {@code '0'}.
927  *
928  *     <p> If the {@code '0'} flag is given then the output will be padded
929  *     with leading zeros to the field width following any indication of sign.
930  *
931  *     <p> If {@code '('}, {@code '+'}, '&nbsp;&nbsp;', or {@code ','} flags
932  *     are given then a {@link FormatFlagsConversionMismatchException} will be
933  *     thrown.
934  *
935  * <tr><td valign="top"> {@code 'x'}
936  *     <td valign="top"> <tt>'&#92;u0078'</tt>
937  *     <td> Formats the argument as an integer in base sixteen. No
938  *     localization is applied.
939  *
940  *     <p> If <i>x</i> is negative then the result will be an unsigned value
941  *     generated by adding 2<sup>n</sup> to the value where {@code n} is the
942  *     number of bits in the type as returned by the static {@code SIZE} field
943  *     in the {@linkplain Byte#SIZE Byte}, {@linkplain Short#SIZE Short},
944  *     {@linkplain Integer#SIZE Integer}, or {@linkplain Long#SIZE Long}
945  *     classes as appropriate.
946  *
947  *     <p> If the {@code '#'} flag is given then the output will always begin
948  *     with the radix indicator {@code "0x"}.
949  *
950  *     <p> If the {@code '0'} flag is given then the output will be padded to
951  *     the field width with leading zeros after the radix indicator or sign (if
952  *     present).
953  *
954  *     <p> If {@code '('}, <tt>'&nbsp;&nbsp;'</tt>, {@code '+'}, or
955  *     {@code ','} flags are given then a {@link
956  *     FormatFlagsConversionMismatchException} will be thrown.
957  *
958  * <tr><td valign="top"> {@code 'X'}
959  *     <td valign="top"> <tt>'&#92;u0058'</tt>
960  *     <td> The upper-case variant of {@code 'x'}.  The entire string
961  *     representing the number will be converted to {@linkplain
962  *     String#toUpperCase upper case} including the {@code 'x'} (if any) and
963  *     all hexadecimal digits {@code 'a'} - {@code 'f'}
964  *     (<tt>'&#92;u0061'</tt> -  <tt>'&#92;u0066'</tt>).
965  *
966  * </table>
967  *
968  * <p> If the conversion is {@code 'o'}, {@code 'x'}, or {@code 'X'} and
969  * both the {@code '#'} and the {@code '0'} flags are given, then result will
970  * contain the radix indicator ({@code '0'} for octal and {@code "0x"} or
971  * {@code "0X"} for hexadecimal), some number of zeros (based on the width),
972  * and the value.
973  *
974  * <p> If the {@code '-'} flag is not given, then the space padding will occur
975  * before the sign.
976  *
977  * <p> The following <a name="intFlags">flags</a> apply to numeric integral
978  * conversions:
979  *
980  * <table cellpadding=5 summary="intFlags">
981  *
982  * <tr><td valign="top"> {@code '+'}
983  *     <td valign="top"> <tt>'&#92;u002b'</tt>
984  *     <td> Requires the output to include a positive sign for all positive
985  *     numbers.  If this flag is not given then only negative values will
986  *     include a sign.
987  *
988  *     <p> If both the {@code '+'} and <tt>'&nbsp;&nbsp;'</tt> flags are given
989  *     then an {@link IllegalFormatFlagsException} will be thrown.
990  *
991  * <tr><td valign="top"> <tt>'&nbsp;&nbsp;'</tt>
992  *     <td valign="top"> <tt>'&#92;u0020'</tt>
993  *     <td> Requires the output to include a single extra space
994  *     (<tt>'&#92;u0020'</tt>) for non-negative values.
995  *
996  *     <p> If both the {@code '+'} and <tt>'&nbsp;&nbsp;'</tt> flags are given
997  *     then an {@link IllegalFormatFlagsException} will be thrown.
998  *
999  * <tr><td valign="top"> {@code '0'}
1000  *     <td valign="top"> <tt>'&#92;u0030'</tt>
1001  *     <td> Requires the output to be padded with leading {@linkplain
1002  *     java.text.DecimalFormatSymbols#getZeroDigit zeros} to the minimum field
1003  *     width following any sign or radix indicator except when converting NaN
1004  *     or infinity.  If the width is not provided, then a {@link
1005  *     MissingFormatWidthException} will be thrown.
1006  *
1007  *     <p> If both the {@code '-'} and {@code '0'} flags are given then an
1008  *     {@link IllegalFormatFlagsException} will be thrown.
1009  *
1010  * <tr><td valign="top"> {@code ','}
1011  *     <td valign="top"> <tt>'&#92;u002c'</tt>
1012  *     <td> Requires the output to include the locale-specific {@linkplain
1013  *     java.text.DecimalFormatSymbols#getGroupingSeparator group separators} as
1014  *     described in the <a href="#L10nGroup">"group" section</a> of the
1015  *     localization algorithm.
1016  *
1017  * <tr><td valign="top"> {@code '('}
1018  *     <td valign="top"> <tt>'&#92;u0028'</tt>
1019  *     <td> Requires the output to prepend a {@code '('}
1020  *     (<tt>'&#92;u0028'</tt>) and append a {@code ')'}
1021  *     (<tt>'&#92;u0029'</tt>) to negative values.
1022  *
1023  * </table>
1024  *
1025  * <p> If no <a name="intdFlags">flags</a> are given the default formatting is
1026  * as follows:
1027  *
1028  * <ul>
1029  *
1030  * <li> The output is right-justified within the {@code width}
1031  *
1032  * <li> Negative numbers begin with a {@code '-'} (<tt>'&#92;u002d'</tt>)
1033  *
1034  * <li> Positive numbers and zero do not include a sign or extra leading
1035  * space
1036  *
1037  * <li> No grouping separators are included
1038  *
1039  * </ul>
1040  *
1041  * <p> The <a name="intWidth">width</a> is the minimum number of characters to
1042  * be written to the output.  This includes any signs, digits, grouping
1043  * separators, radix indicator, and parentheses.  If the length of the
1044  * converted value is less than the width then the output will be padded by
1045  * spaces (<tt>'&#92;u0020'</tt>) until the total number of characters equals
1046  * width.  The padding is on the left by default.  If {@code '-'} flag is
1047  * given then the padding will be on the right.  If width is not specified then
1048  * there is no minimum.
1049  *
1050  * <p> The precision is not applicable.  If precision is specified then an
1051  * {@link IllegalFormatPrecisionException} will be thrown.
1052  *
1053  * <p><a name="dnbint"><b> BigInteger </b></a>
1054  *
1055  * <p> The following conversions may be applied to {@link
1056  * java.math.BigInteger}.
1057  *
1058  * <table cellpadding=5 summary="BIntConv">
1059  *
1060  * <tr><td valign="top"> {@code 'd'}
1061  *     <td valign="top"> <tt>'&#92;u0064'</tt>
1062  *     <td> Requires the output to be formatted as a decimal integer. The <a
1063  *     href="#L10nAlgorithm">localization algorithm</a> is applied.
1064  *
1065  *     <p> If the {@code '#'} flag is given {@link
1066  *     FormatFlagsConversionMismatchException} will be thrown.
1067  *
1068  * <tr><td valign="top"> {@code 'o'}
1069  *     <td valign="top"> <tt>'&#92;u006f'</tt>
1070  *     <td> Requires the output to be formatted as an integer in base eight.
1071  *     No localization is applied.
1072  *
1073  *     <p> If <i>x</i> is negative then the result will be a signed value
1074  *     beginning with {@code '-'} (<tt>'&#92;u002d'</tt>).  Signed output is
1075  *     allowed for this type because unlike the primitive types it is not
1076  *     possible to create an unsigned equivalent without assuming an explicit
1077  *     data-type size.
1078  *
1079  *     <p> If <i>x</i> is positive or zero and the {@code '+'} flag is given
1080  *     then the result will begin with {@code '+'} (<tt>'&#92;u002b'</tt>).
1081  *
1082  *     <p> If the {@code '#'} flag is given then the output will always begin
1083  *     with {@code '0'} prefix.
1084  *
1085  *     <p> If the {@code '0'} flag is given then the output will be padded
1086  *     with leading zeros to the field width following any indication of sign.
1087  *
1088  *     <p> If the {@code ','} flag is given then a {@link
1089  *     FormatFlagsConversionMismatchException} will be thrown.
1090  *
1091  * <tr><td valign="top"> {@code 'x'}
1092  *     <td valign="top"> <tt>'&#92;u0078'</tt>
1093  *     <td> Requires the output to be formatted as an integer in base
1094  *     sixteen.  No localization is applied.
1095  *
1096  *     <p> If <i>x</i> is negative then the result will be a signed value
1097  *     beginning with {@code '-'} (<tt>'&#92;u002d'</tt>).  Signed output is
1098  *     allowed for this type because unlike the primitive types it is not
1099  *     possible to create an unsigned equivalent without assuming an explicit
1100  *     data-type size.
1101  *
1102  *     <p> If <i>x</i> is positive or zero and the {@code '+'} flag is given
1103  *     then the result will begin with {@code '+'} (<tt>'&#92;u002b'</tt>).
1104  *
1105  *     <p> If the {@code '#'} flag is given then the output will always begin
1106  *     with the radix indicator {@code "0x"}.
1107  *
1108  *     <p> If the {@code '0'} flag is given then the output will be padded to
1109  *     the field width with leading zeros after the radix indicator or sign (if
1110  *     present).
1111  *
1112  *     <p> If the {@code ','} flag is given then a {@link
1113  *     FormatFlagsConversionMismatchException} will be thrown.
1114  *
1115  * <tr><td valign="top"> {@code 'X'}
1116  *     <td valign="top"> <tt>'&#92;u0058'</tt>
1117  *     <td> The upper-case variant of {@code 'x'}.  The entire string
1118  *     representing the number will be converted to {@linkplain
1119  *     String#toUpperCase upper case} including the {@code 'x'} (if any) and
1120  *     all hexadecimal digits {@code 'a'} - {@code 'f'}
1121  *     (<tt>'&#92;u0061'</tt> - <tt>'&#92;u0066'</tt>).
1122  *
1123  * </table>
1124  *
1125  * <p> If the conversion is {@code 'o'}, {@code 'x'}, or {@code 'X'} and
1126  * both the {@code '#'} and the {@code '0'} flags are given, then result will
1127  * contain the base indicator ({@code '0'} for octal and {@code "0x"} or
1128  * {@code "0X"} for hexadecimal), some number of zeros (based on the width),
1129  * and the value.
1130  *
1131  * <p> If the {@code '0'} flag is given and the value is negative, then the
1132  * zero padding will occur after the sign.
1133  *
1134  * <p> If the {@code '-'} flag is not given, then the space padding will occur
1135  * before the sign.
1136  *
1137  * <p> All <a href="#intFlags">flags</a> defined for Byte, Short, Integer, and
1138  * Long apply.  The <a href="#intdFlags">default behavior</a> when no flags are
1139  * given is the same as for Byte, Short, Integer, and Long.
1140  *
1141  * <p> The specification of <a href="#intWidth">width</a> is the same as
1142  * defined for Byte, Short, Integer, and Long.
1143  *
1144  * <p> The precision is not applicable.  If precision is specified then an
1145  * {@link IllegalFormatPrecisionException} will be thrown.
1146  *
1147  * <p><a name="dndec"><b> Float and Double</b></a>
1148  *
1149  * <p> The following conversions may be applied to {@code float}, {@link
1150  * Float}, {@code double} and {@link Double}.
1151  *
1152  * <table cellpadding=5 summary="floatConv">
1153  *
1154  * <tr><td valign="top"> {@code 'e'}
1155  *     <td valign="top"> <tt>'&#92;u0065'</tt>
1156  *     <td> Requires the output to be formatted using <a
1157  *     name="scientific">computerized scientific notation</a>.  The <a
1158  *     href="#L10nAlgorithm">localization algorithm</a> is applied.
1159  *
1160  *     <p> The formatting of the magnitude <i>m</i> depends upon its value.
1161  *
1162  *     <p> If <i>m</i> is NaN or infinite, the literal strings "NaN" or
1163  *     "Infinity", respectively, will be output.  These values are not
1164  *     localized.
1165  *
1166  *     <p> If <i>m</i> is positive-zero or negative-zero, then the exponent
1167  *     will be {@code "+00"}.
1168  *
1169  *     <p> Otherwise, the result is a string that represents the sign and
1170  *     magnitude (absolute value) of the argument.  The formatting of the sign
1171  *     is described in the <a href="#L10nAlgorithm">localization
1172  *     algorithm</a>. The formatting of the magnitude <i>m</i> depends upon its
1173  *     value.
1174  *
1175  *     <p> Let <i>n</i> be the unique integer such that 10<sup><i>n</i></sup>
1176  *     &lt;= <i>m</i> &lt; 10<sup><i>n</i>+1</sup>; then let <i>a</i> be the
1177  *     mathematically exact quotient of <i>m</i> and 10<sup><i>n</i></sup> so
1178  *     that 1 &lt;= <i>a</i> &lt; 10. The magnitude is then represented as the
1179  *     integer part of <i>a</i>, as a single decimal digit, followed by the
1180  *     decimal separator followed by decimal digits representing the fractional
1181  *     part of <i>a</i>, followed by the lower-case locale-specific {@linkplain
1182  *     java.text.DecimalFormatSymbols#getExponentSeparator exponent separator}
1183  *     (e.g. {@code 'e'}), followed by the sign of the exponent, followed
1184  *     by a representation of <i>n</i> as a decimal integer, as produced by the
1185  *     method {@link Long#toString(long, int)}, and zero-padded to include at
1186  *     least two digits.
1187  *
1188  *     <p> The number of digits in the result for the fractional part of
1189  *     <i>m</i> or <i>a</i> is equal to the precision.  If the precision is not
1190  *     specified then the default value is {@code 6}. If the precision is less
1191  *     than the number of digits which would appear after the decimal point in
1192  *     the string returned by {@link Float#toString(float)} or {@link
1193  *     Double#toString(double)} respectively, then the value will be rounded
1194  *     using the {@linkplain java.math.BigDecimal#ROUND_HALF_UP round half up
1195  *     algorithm}.  Otherwise, zeros may be appended to reach the precision.
1196  *     For a canonical representation of the value, use {@link
1197  *     Float#toString(float)} or {@link Double#toString(double)} as
1198  *     appropriate.
1199  *
1200  *     <p>If the {@code ','} flag is given, then an {@link
1201  *     FormatFlagsConversionMismatchException} will be thrown.
1202  *
1203  * <tr><td valign="top"> {@code 'E'}
1204  *     <td valign="top"> <tt>'&#92;u0045'</tt>
1205  *     <td> The upper-case variant of {@code 'e'}.  The exponent symbol
1206  *     will be the upper-case locale-specific {@linkplain
1207  *     java.text.DecimalFormatSymbols#getExponentSeparator exponent separator}
1208  *     (e.g. {@code 'E'}).
1209  *
1210  * <tr><td valign="top"> {@code 'g'}
1211  *     <td valign="top"> <tt>'&#92;u0067'</tt>
1212  *     <td> Requires the output to be formatted in general scientific notation
1213  *     as described below. The <a href="#L10nAlgorithm">localization
1214  *     algorithm</a> is applied.
1215  *
1216  *     <p> After rounding for the precision, the formatting of the resulting
1217  *     magnitude <i>m</i> depends on its value.
1218  *
1219  *     <p> If <i>m</i> is greater than or equal to 10<sup>-4</sup> but less
1220  *     than 10<sup>precision</sup> then it is represented in <i><a
1221  *     href="#decimal">decimal format</a></i>.
1222  *
1223  *     <p> If <i>m</i> is less than 10<sup>-4</sup> or greater than or equal to
1224  *     10<sup>precision</sup>, then it is represented in <i><a
1225  *     href="#scientific">computerized scientific notation</a></i>.
1226  *
1227  *     <p> The total number of significant digits in <i>m</i> is equal to the
1228  *     precision.  If the precision is not specified, then the default value is
1229  *     {@code 6}.  If the precision is {@code 0}, then it is taken to be
1230  *     {@code 1}.
1231  *
1232  *     <p> If the {@code '#'} flag is given then an {@link
1233  *     FormatFlagsConversionMismatchException} will be thrown.
1234  *
1235  * <tr><td valign="top"> {@code 'G'}
1236  *     <td valign="top"> <tt>'&#92;u0047'</tt>
1237  *     <td> The upper-case variant of {@code 'g'}.
1238  *
1239  * <tr><td valign="top"> {@code 'f'}
1240  *     <td valign="top"> <tt>'&#92;u0066'</tt>
1241  *     <td> Requires the output to be formatted using <a name="decimal">decimal
1242  *     format</a>.  The <a href="#L10nAlgorithm">localization algorithm</a> is
1243  *     applied.
1244  *
1245  *     <p> The result is a string that represents the sign and magnitude
1246  *     (absolute value) of the argument.  The formatting of the sign is
1247  *     described in the <a href="#L10nAlgorithm">localization
1248  *     algorithm</a>. The formatting of the magnitude <i>m</i> depends upon its
1249  *     value.
1250  *
1251  *     <p> If <i>m</i> NaN or infinite, the literal strings "NaN" or
1252  *     "Infinity", respectively, will be output.  These values are not
1253  *     localized.
1254  *
1255  *     <p> The magnitude is formatted as the integer part of <i>m</i>, with no
1256  *     leading zeroes, followed by the decimal separator followed by one or
1257  *     more decimal digits representing the fractional part of <i>m</i>.
1258  *
1259  *     <p> The number of digits in the result for the fractional part of
1260  *     <i>m</i> or <i>a</i> is equal to the precision.  If the precision is not
1261  *     specified then the default value is {@code 6}. If the precision is less
1262  *     than the number of digits which would appear after the decimal point in
1263  *     the string returned by {@link Float#toString(float)} or {@link
1264  *     Double#toString(double)} respectively, then the value will be rounded
1265  *     using the {@linkplain java.math.BigDecimal#ROUND_HALF_UP round half up
1266  *     algorithm}.  Otherwise, zeros may be appended to reach the precision.
1267  *     For a canonical representation of the value, use {@link
1268  *     Float#toString(float)} or {@link Double#toString(double)} as
1269  *     appropriate.
1270  *
1271  * <tr><td valign="top"> {@code 'a'}
1272  *     <td valign="top"> <tt>'&#92;u0061'</tt>
1273  *     <td> Requires the output to be formatted in hexadecimal exponential
1274  *     form.  No localization is applied.
1275  *
1276  *     <p> The result is a string that represents the sign and magnitude
1277  *     (absolute value) of the argument <i>x</i>.
1278  *
1279  *     <p> If <i>x</i> is negative or a negative-zero value then the result
1280  *     will begin with {@code '-'} (<tt>'&#92;u002d'</tt>).
1281  *
1282  *     <p> If <i>x</i> is positive or a positive-zero value and the
1283  *     {@code '+'} flag is given then the result will begin with {@code '+'}
1284  *     (<tt>'&#92;u002b'</tt>).
1285  *
1286  *     <p> The formatting of the magnitude <i>m</i> depends upon its value.
1287  *
1288  *     <ul>
1289  *
1290  *     <li> If the value is NaN or infinite, the literal strings "NaN" or
1291  *     "Infinity", respectively, will be output.
1292  *
1293  *     <li> If <i>m</i> is zero then it is represented by the string
1294  *     {@code "0x0.0p0"}.
1295  *
1296  *     <li> If <i>m</i> is a {@code double} value with a normalized
1297  *     representation then substrings are used to represent the significand and
1298  *     exponent fields.  The significand is represented by the characters
1299  *     {@code "0x1."} followed by the hexadecimal representation of the rest
1300  *     of the significand as a fraction.  The exponent is represented by
1301  *     {@code 'p'} (<tt>'&#92;u0070'</tt>) followed by a decimal string of the
1302  *     unbiased exponent as if produced by invoking {@link
1303  *     Integer#toString(int) Integer.toString} on the exponent value.  If the
1304  *     precision is specified, the value is rounded to the given number of
1305  *     hexadecimal digits.
1306  *
1307  *     <li> If <i>m</i> is a {@code double} value with a subnormal
1308  *     representation then, unless the precision is specified to be in the range
1309  *     1 through 12, inclusive, the significand is represented by the characters
1310  *     {@code '0x0.'} followed by the hexadecimal representation of the rest of
1311  *     the significand as a fraction, and the exponent represented by
1312  *     {@code 'p-1022'}.  If the precision is in the interval
1313  *     [1,&nbsp;12], the subnormal value is normalized such that it
1314  *     begins with the characters {@code '0x1.'}, rounded to the number of
1315  *     hexadecimal digits of precision, and the exponent adjusted
1316  *     accordingly.  Note that there must be at least one nonzero digit in a
1317  *     subnormal significand.
1318  *
1319  *     </ul>
1320  *
1321  *     <p> If the {@code '('} or {@code ','} flags are given, then a {@link
1322  *     FormatFlagsConversionMismatchException} will be thrown.
1323  *
1324  * <tr><td valign="top"> {@code 'A'}
1325  *     <td valign="top"> <tt>'&#92;u0041'</tt>
1326  *     <td> The upper-case variant of {@code 'a'}.  The entire string
1327  *     representing the number will be converted to upper case including the
1328  *     {@code 'x'} (<tt>'&#92;u0078'</tt>) and {@code 'p'}
1329  *     (<tt>'&#92;u0070'</tt> and all hexadecimal digits {@code 'a'} -
1330  *     {@code 'f'} (<tt>'&#92;u0061'</tt> - <tt>'&#92;u0066'</tt>).
1331  *
1332  * </table>
1333  *
1334  * <p> All <a href="#intFlags">flags</a> defined for Byte, Short, Integer, and
1335  * Long apply.
1336  *
1337  * <p> If the {@code '#'} flag is given, then the decimal separator will
1338  * always be present.
1339  *
1340  * <p> If no <a name="floatdFlags">flags</a> are given the default formatting
1341  * is as follows:
1342  *
1343  * <ul>
1344  *
1345  * <li> The output is right-justified within the {@code width}
1346  *
1347  * <li> Negative numbers begin with a {@code '-'}
1348  *
1349  * <li> Positive numbers and positive zero do not include a sign or extra
1350  * leading space
1351  *
1352  * <li> No grouping separators are included
1353  *
1354  * <li> The decimal separator will only appear if a digit follows it
1355  *
1356  * </ul>
1357  *
1358  * <p> The <a name="floatDWidth">width</a> is the minimum number of characters
1359  * to be written to the output.  This includes any signs, digits, grouping
1360  * separators, decimal separators, exponential symbol, radix indicator,
1361  * parentheses, and strings representing infinity and NaN as applicable.  If
1362  * the length of the converted value is less than the width then the output
1363  * will be padded by spaces (<tt>'&#92;u0020'</tt>) until the total number of
1364  * characters equals width.  The padding is on the left by default.  If the
1365  * {@code '-'} flag is given then the padding will be on the right.  If width
1366  * is not specified then there is no minimum.
1367  *
1368  * <p> If the <a name="floatDPrec">conversion</a> is {@code 'e'},
1369  * {@code 'E'} or {@code 'f'}, then the precision is the number of digits
1370  * after the decimal separator.  If the precision is not specified, then it is
1371  * assumed to be {@code 6}.
1372  *
1373  * <p> If the conversion is {@code 'g'} or {@code 'G'}, then the precision is
1374  * the total number of significant digits in the resulting magnitude after
1375  * rounding.  If the precision is not specified, then the default value is
1376  * {@code 6}.  If the precision is {@code 0}, then it is taken to be
1377  * {@code 1}.
1378  *
1379  * <p> If the conversion is {@code 'a'} or {@code 'A'}, then the precision
1380  * is the number of hexadecimal digits after the radix point.  If the
1381  * precision is not provided, then all of the digits as returned by {@link
1382  * Double#toHexString(double)} will be output.
1383  *
1384  * <p><a name="dnbdec"><b> BigDecimal </b></a>
1385  *
1386  * <p> The following conversions may be applied {@link java.math.BigDecimal
1387  * BigDecimal}.
1388  *
1389  * <table cellpadding=5 summary="floatConv">
1390  *
1391  * <tr><td valign="top"> {@code 'e'}
1392  *     <td valign="top"> <tt>'&#92;u0065'</tt>
1393  *     <td> Requires the output to be formatted using <a
1394  *     name="bscientific">computerized scientific notation</a>.  The <a
1395  *     href="#L10nAlgorithm">localization algorithm</a> is applied.
1396  *
1397  *     <p> The formatting of the magnitude <i>m</i> depends upon its value.
1398  *
1399  *     <p> If <i>m</i> is positive-zero or negative-zero, then the exponent
1400  *     will be {@code "+00"}.
1401  *
1402  *     <p> Otherwise, the result is a string that represents the sign and
1403  *     magnitude (absolute value) of the argument.  The formatting of the sign
1404  *     is described in the <a href="#L10nAlgorithm">localization
1405  *     algorithm</a>. The formatting of the magnitude <i>m</i> depends upon its
1406  *     value.
1407  *
1408  *     <p> Let <i>n</i> be the unique integer such that 10<sup><i>n</i></sup>
1409  *     &lt;= <i>m</i> &lt; 10<sup><i>n</i>+1</sup>; then let <i>a</i> be the
1410  *     mathematically exact quotient of <i>m</i> and 10<sup><i>n</i></sup> so
1411  *     that 1 &lt;= <i>a</i> &lt; 10. The magnitude is then represented as the
1412  *     integer part of <i>a</i>, as a single decimal digit, followed by the
1413  *     decimal separator followed by decimal digits representing the fractional
1414  *     part of <i>a</i>, followed by the exponent symbol {@code 'e'}
1415  *     (<tt>'&#92;u0065'</tt>), followed by the sign of the exponent, followed
1416  *     by a representation of <i>n</i> as a decimal integer, as produced by the
1417  *     method {@link Long#toString(long, int)}, and zero-padded to include at
1418  *     least two digits.
1419  *
1420  *     <p> The number of digits in the result for the fractional part of
1421  *     <i>m</i> or <i>a</i> is equal to the precision.  If the precision is not
1422  *     specified then the default value is {@code 6}.  If the precision is
1423  *     less than the number of digits to the right of the decimal point then
1424  *     the value will be rounded using the
1425  *     {@linkplain java.math.BigDecimal#ROUND_HALF_UP round half up
1426  *     algorithm}.  Otherwise, zeros may be appended to reach the precision.
1427  *     For a canonical representation of the value, use {@link
1428  *     BigDecimal#toString()}.
1429  *
1430  *     <p> If the {@code ','} flag is given, then an {@link
1431  *     FormatFlagsConversionMismatchException} will be thrown.
1432  *
1433  * <tr><td valign="top"> {@code 'E'}
1434  *     <td valign="top"> <tt>'&#92;u0045'</tt>
1435  *     <td> The upper-case variant of {@code 'e'}.  The exponent symbol
1436  *     will be {@code 'E'} (<tt>'&#92;u0045'</tt>).
1437  *
1438  * <tr><td valign="top"> {@code 'g'}
1439  *     <td valign="top"> <tt>'&#92;u0067'</tt>
1440  *     <td> Requires the output to be formatted in general scientific notation
1441  *     as described below. The <a href="#L10nAlgorithm">localization
1442  *     algorithm</a> is applied.
1443  *
1444  *     <p> After rounding for the precision, the formatting of the resulting
1445  *     magnitude <i>m</i> depends on its value.
1446  *
1447  *     <p> If <i>m</i> is greater than or equal to 10<sup>-4</sup> but less
1448  *     than 10<sup>precision</sup> then it is represented in <i><a
1449  *     href="#bdecimal">decimal format</a></i>.
1450  *
1451  *     <p> If <i>m</i> is less than 10<sup>-4</sup> or greater than or equal to
1452  *     10<sup>precision</sup>, then it is represented in <i><a
1453  *     href="#bscientific">computerized scientific notation</a></i>.
1454  *
1455  *     <p> The total number of significant digits in <i>m</i> is equal to the
1456  *     precision.  If the precision is not specified, then the default value is
1457  *     {@code 6}.  If the precision is {@code 0}, then it is taken to be
1458  *     {@code 1}.
1459  *
1460  *     <p> If the {@code '#'} flag is given then an {@link
1461  *     FormatFlagsConversionMismatchException} will be thrown.
1462  *
1463  * <tr><td valign="top"> {@code 'G'}
1464  *     <td valign="top"> <tt>'&#92;u0047'</tt>
1465  *     <td> The upper-case variant of {@code 'g'}.
1466  *
1467  * <tr><td valign="top"> {@code 'f'}
1468  *     <td valign="top"> <tt>'&#92;u0066'</tt>
1469  *     <td> Requires the output to be formatted using <a name="bdecimal">decimal
1470  *     format</a>.  The <a href="#L10nAlgorithm">localization algorithm</a> is
1471  *     applied.
1472  *
1473  *     <p> The result is a string that represents the sign and magnitude
1474  *     (absolute value) of the argument.  The formatting of the sign is
1475  *     described in the <a href="#L10nAlgorithm">localization
1476  *     algorithm</a>. The formatting of the magnitude <i>m</i> depends upon its
1477  *     value.
1478  *
1479  *     <p> The magnitude is formatted as the integer part of <i>m</i>, with no
1480  *     leading zeroes, followed by the decimal separator followed by one or
1481  *     more decimal digits representing the fractional part of <i>m</i>.
1482  *
1483  *     <p> The number of digits in the result for the fractional part of
1484  *     <i>m</i> or <i>a</i> is equal to the precision. If the precision is not
1485  *     specified then the default value is {@code 6}.  If the precision is
1486  *     less than the number of digits to the right of the decimal point
1487  *     then the value will be rounded using the
1488  *     {@linkplain java.math.BigDecimal#ROUND_HALF_UP round half up
1489  *     algorithm}.  Otherwise, zeros may be appended to reach the precision.
1490  *     For a canonical representation of the value, use {@link
1491  *     BigDecimal#toString()}.
1492  *
1493  * </table>
1494  *
1495  * <p> All <a href="#intFlags">flags</a> defined for Byte, Short, Integer, and
1496  * Long apply.
1497  *
1498  * <p> If the {@code '#'} flag is given, then the decimal separator will
1499  * always be present.
1500  *
1501  * <p> The <a href="#floatdFlags">default behavior</a> when no flags are
1502  * given is the same as for Float and Double.
1503  *
1504  * <p> The specification of <a href="#floatDWidth">width</a> and <a
1505  * href="#floatDPrec">precision</a> is the same as defined for Float and
1506  * Double.
1507  *
1508  * <h4><a name="ddt">Date/Time</a></h4>
1509  *
1510  * <p> This conversion may be applied to {@code long}, {@link Long}, {@link
1511  * Calendar}, {@link Date} and {@link TemporalAccessor TemporalAccessor}
1512  *
1513  * <table cellpadding=5 summary="DTConv">
1514  *
1515  * <tr><td valign="top"> {@code 't'}
1516  *     <td valign="top"> <tt>'&#92;u0074'</tt>
1517  *     <td> Prefix for date and time conversion characters.
1518  * <tr><td valign="top"> {@code 'T'}
1519  *     <td valign="top"> <tt>'&#92;u0054'</tt>
1520  *     <td> The upper-case variant of {@code 't'}.
1521  *
1522  * </table>
1523  *
1524  * <p> The following date and time conversion character suffixes are defined
1525  * for the {@code 't'} and {@code 'T'} conversions.  The types are similar to
1526  * but not completely identical to those defined by GNU {@code date} and
1527  * POSIX {@code strftime(3c)}.  Additional conversion types are provided to
1528  * access Java-specific functionality (e.g. {@code 'L'} for milliseconds
1529  * within the second).
1530  *
1531  * <p> The following conversion characters are used for formatting times:
1532  *
1533  * <table cellpadding=5 summary="time">
1534  *
1535  * <tr><td valign="top"> {@code 'H'}
1536  *     <td valign="top"> <tt>'&#92;u0048'</tt>
1537  *     <td> Hour of the day for the 24-hour clock, formatted as two digits with
1538  *     a leading zero as necessary i.e. {@code 00 - 23}. {@code 00}
1539  *     corresponds to midnight.
1540  *
1541  * <tr><td valign="top">{@code 'I'}
1542  *     <td valign="top"> <tt>'&#92;u0049'</tt>
1543  *     <td> Hour for the 12-hour clock, formatted as two digits with a leading
1544  *     zero as necessary, i.e.  {@code 01 - 12}.  {@code 01} corresponds to
1545  *     one o'clock (either morning or afternoon).
1546  *
1547  * <tr><td valign="top">{@code 'k'}
1548  *     <td valign="top"> <tt>'&#92;u006b'</tt>
1549  *     <td> Hour of the day for the 24-hour clock, i.e. {@code 0 - 23}.
1550  *     {@code 0} corresponds to midnight.
1551  *
1552  * <tr><td valign="top">{@code 'l'}
1553  *     <td valign="top"> <tt>'&#92;u006c'</tt>
1554  *     <td> Hour for the 12-hour clock, i.e. {@code 1 - 12}.  {@code 1}
1555  *     corresponds to one o'clock (either morning or afternoon).
1556  *
1557  * <tr><td valign="top">{@code 'M'}
1558  *     <td valign="top"> <tt>'&#92;u004d'</tt>
1559  *     <td> Minute within the hour formatted as two digits with a leading zero
1560  *     as necessary, i.e.  {@code 00 - 59}.
1561  *
1562  * <tr><td valign="top">{@code 'S'}
1563  *     <td valign="top"> <tt>'&#92;u0053'</tt>
1564  *     <td> Seconds within the minute, formatted as two digits with a leading
1565  *     zero as necessary, i.e. {@code 00 - 60} ("{@code 60}" is a special
1566  *     value required to support leap seconds).
1567  *
1568  * <tr><td valign="top">{@code 'L'}
1569  *     <td valign="top"> <tt>'&#92;u004c'</tt>
1570  *     <td> Millisecond within the second formatted as three digits with
1571  *     leading zeros as necessary, i.e. {@code 000 - 999}.
1572  *
1573  * <tr><td valign="top">{@code 'N'}
1574  *     <td valign="top"> <tt>'&#92;u004e'</tt>
1575  *     <td> Nanosecond within the second, formatted as nine digits with leading
1576  *     zeros as necessary, i.e. {@code 000000000 - 999999999}.  The precision
1577  *     of this value is limited by the resolution of the underlying operating
1578  *     system or hardware.
1579  *
1580  * <tr><td valign="top">{@code 'p'}
1581  *     <td valign="top"> <tt>'&#92;u0070'</tt>
1582  *     <td> Locale-specific {@linkplain
1583  *     java.text.DateFormatSymbols#getAmPmStrings morning or afternoon} marker
1584  *     in lower case, e.g."{@code am}" or "{@code pm}".  Use of the
1585  *     conversion prefix {@code 'T'} forces this output to upper case.  (Note
1586  *     that {@code 'p'} produces lower-case output.  This is different from
1587  *     GNU {@code date} and POSIX {@code strftime(3c)} which produce
1588  *     upper-case output.)
1589  *
1590  * <tr><td valign="top">{@code 'z'}
1591  *     <td valign="top"> <tt>'&#92;u007a'</tt>
1592  *     <td> <a href="http://www.ietf.org/rfc/rfc0822.txt">RFC&nbsp;822</a>
1593  *     style numeric time zone offset from GMT, e.g. {@code -0800}.  This
1594  *     value will be adjusted as necessary for Daylight Saving Time.  For
1595  *     {@code long}, {@link Long}, and {@link Date} the time zone used is
1596  *     the {@linkplain TimeZone#getDefault() default time zone} for this
1597  *     instance of the Java virtual machine.
1598  *
1599  * <tr><td valign="top">{@code 'Z'}
1600  *     <td valign="top"> <tt>'&#92;u005a'</tt>
1601  *     <td> A string representing the abbreviation for the time zone.  This
1602  *     value will be adjusted as necessary for Daylight Saving Time.  For
1603  *     {@code long}, {@link Long}, and {@link Date} the time zone used is
1604  *     the {@linkplain TimeZone#getDefault() default time zone} for this
1605  *     instance of the Java virtual machine.  The Formatter's locale will
1606  *     supersede the locale of the argument (if any).
1607  *
1608  * <tr><td valign="top">{@code 's'}
1609  *     <td valign="top"> <tt>'&#92;u0073'</tt>
1610  *     <td> Seconds since the beginning of the epoch starting at 1 January 1970
1611  *     {@code 00:00:00} UTC, i.e. {@code Long.MIN_VALUE/1000} to
1612  *     {@code Long.MAX_VALUE/1000}.
1613  *
1614  * <tr><td valign="top">{@code 'Q'}
1615  *     <td valign="top"> <tt>'&#92;u004f'</tt>
1616  *     <td> Milliseconds since the beginning of the epoch starting at 1 January
1617  *     1970 {@code 00:00:00} UTC, i.e. {@code Long.MIN_VALUE} to
1618  *     {@code Long.MAX_VALUE}. The precision of this value is limited by
1619  *     the resolution of the underlying operating system or hardware.
1620  *
1621  * </table>
1622  *
1623  * <p> The following conversion characters are used for formatting dates:
1624  *
1625  * <table cellpadding=5 summary="date">
1626  *
1627  * <tr><td valign="top">{@code 'B'}
1628  *     <td valign="top"> <tt>'&#92;u0042'</tt>
1629  *     <td> Locale-specific {@linkplain java.text.DateFormatSymbols#getMonths
1630  *     full month name}, e.g. {@code "January"}, {@code "February"}.
1631  *
1632  * <tr><td valign="top">{@code 'b'}
1633  *     <td valign="top"> <tt>'&#92;u0062'</tt>
1634  *     <td> Locale-specific {@linkplain
1635  *     java.text.DateFormatSymbols#getShortMonths abbreviated month name},
1636  *     e.g. {@code "Jan"}, {@code "Feb"}.
1637  *
1638  * <tr><td valign="top">{@code 'h'}
1639  *     <td valign="top"> <tt>'&#92;u0068'</tt>
1640  *     <td> Same as {@code 'b'}.
1641  *
1642  * <tr><td valign="top">{@code 'A'}
1643  *     <td valign="top"> <tt>'&#92;u0041'</tt>
1644  *     <td> Locale-specific full name of the {@linkplain
1645  *     java.text.DateFormatSymbols#getWeekdays day of the week},
1646  *     e.g. {@code "Sunday"}, {@code "Monday"}
1647  *
1648  * <tr><td valign="top">{@code 'a'}
1649  *     <td valign="top"> <tt>'&#92;u0061'</tt>
1650  *     <td> Locale-specific short name of the {@linkplain
1651  *     java.text.DateFormatSymbols#getShortWeekdays day of the week},
1652  *     e.g. {@code "Sun"}, {@code "Mon"}
1653  *
1654  * <tr><td valign="top">{@code 'C'}
1655  *     <td valign="top"> <tt>'&#92;u0043'</tt>
1656  *     <td> Four-digit year divided by {@code 100}, formatted as two digits
1657  *     with leading zero as necessary, i.e. {@code 00 - 99}
1658  *
1659  * <tr><td valign="top">{@code 'Y'}
1660  *     <td valign="top"> <tt>'&#92;u0059'</tt> <td> Year, formatted to at least
1661  *     four digits with leading zeros as necessary, e.g. {@code 0092} equals
1662  *     {@code 92} CE for the Gregorian calendar.
1663  *
1664  * <tr><td valign="top">{@code 'y'}
1665  *     <td valign="top"> <tt>'&#92;u0079'</tt>
1666  *     <td> Last two digits of the year, formatted with leading zeros as
1667  *     necessary, i.e. {@code 00 - 99}.
1668  *
1669  * <tr><td valign="top">{@code 'j'}
1670  *     <td valign="top"> <tt>'&#92;u006a'</tt>
1671  *     <td> Day of year, formatted as three digits with leading zeros as
1672  *     necessary, e.g. {@code 001 - 366} for the Gregorian calendar.
1673  *     {@code 001} corresponds to the first day of the year.
1674  *
1675  * <tr><td valign="top">{@code 'm'}
1676  *     <td valign="top"> <tt>'&#92;u006d'</tt>
1677  *     <td> Month, formatted as two digits with leading zeros as necessary,
1678  *     i.e. {@code 01 - 13}, where "{@code 01}" is the first month of the
1679  *     year and ("{@code 13}" is a special value required to support lunar
1680  *     calendars).
1681  *
1682  * <tr><td valign="top">{@code 'd'}
1683  *     <td valign="top"> <tt>'&#92;u0064'</tt>
1684  *     <td> Day of month, formatted as two digits with leading zeros as
1685  *     necessary, i.e. {@code 01 - 31}, where "{@code 01}" is the first day
1686  *     of the month.
1687  *
1688  * <tr><td valign="top">{@code 'e'}
1689  *     <td valign="top"> <tt>'&#92;u0065'</tt>
1690  *     <td> Day of month, formatted as two digits, i.e. {@code 1 - 31} where
1691  *     "{@code 1}" is the first day of the month.
1692  *
1693  * </table>
1694  *
1695  * <p> The following conversion characters are used for formatting common
1696  * date/time compositions.
1697  *
1698  * <table cellpadding=5 summary="composites">
1699  *
1700  * <tr><td valign="top">{@code 'R'}
1701  *     <td valign="top"> <tt>'&#92;u0052'</tt>
1702  *     <td> Time formatted for the 24-hour clock as {@code "%tH:%tM"}
1703  *
1704  * <tr><td valign="top">{@code 'T'}
1705  *     <td valign="top"> <tt>'&#92;u0054'</tt>
1706  *     <td> Time formatted for the 24-hour clock as {@code "%tH:%tM:%tS"}.
1707  *
1708  * <tr><td valign="top">{@code 'r'}
1709  *     <td valign="top"> <tt>'&#92;u0072'</tt>
1710  *     <td> Time formatted for the 12-hour clock as {@code "%tI:%tM:%tS
1711  *     %Tp"}.  The location of the morning or afternoon marker
1712  *     ({@code '%Tp'}) may be locale-dependent.
1713  *
1714  * <tr><td valign="top">{@code 'D'}
1715  *     <td valign="top"> <tt>'&#92;u0044'</tt>
1716  *     <td> Date formatted as {@code "%tm/%td/%ty"}.
1717  *
1718  * <tr><td valign="top">{@code 'F'}
1719  *     <td valign="top"> <tt>'&#92;u0046'</tt>
1720  *     <td> <a href="http://www.w3.org/TR/NOTE-datetime">ISO&nbsp;8601</a>
1721  *     complete date formatted as {@code "%tY-%tm-%td"}.
1722  *
1723  * <tr><td valign="top">{@code 'c'}
1724  *     <td valign="top"> <tt>'&#92;u0063'</tt>
1725  *     <td> Date and time formatted as {@code "%ta %tb %td %tT %tZ %tY"},
1726  *     e.g. {@code "Sun Jul 20 16:17:00 EDT 1969"}.
1727  *
1728  * </table>
1729  *
1730  * <p> The {@code '-'} flag defined for <a href="#dFlags">General
1731  * conversions</a> applies.  If the {@code '#'} flag is given, then a {@link
1732  * FormatFlagsConversionMismatchException} will be thrown.
1733  *
1734  * <p> The width is the minimum number of characters to
1735  * be written to the output.  If the length of the converted value is less than
1736  * the {@code width} then the output will be padded by spaces
1737  * (<tt>'&#92;u0020'</tt>) until the total number of characters equals width.
1738  * The padding is on the left by default.  If the {@code '-'} flag is given
1739  * then the padding will be on the right.  If width is not specified then there
1740  * is no minimum.
1741  *
1742  * <p> The precision is not applicable.  If the precision is specified then an
1743  * {@link IllegalFormatPrecisionException} will be thrown.
1744  *
1745  * <h4><a name="dper">Percent</a></h4>
1746  *
1747  * <p> The conversion does not correspond to any argument.
1748  *
1749  * <table cellpadding=5 summary="DTConv">
1750  *
1751  * <tr><td valign="top">{@code '%'}
1752  *     <td> The result is a literal {@code '%'} (<tt>'&#92;u0025'</tt>)
1753  *
1754  * <p> The width is the minimum number of characters to
1755  * be written to the output including the {@code '%'}.  If the length of the
1756  * converted value is less than the {@code width} then the output will be
1757  * padded by spaces (<tt>'&#92;u0020'</tt>) until the total number of
1758  * characters equals width.  The padding is on the left.  If width is not
1759  * specified then just the {@code '%'} is output.
1760  *
1761  * <p> The {@code '-'} flag defined for <a href="#dFlags">General
1762  * conversions</a> applies.  If any other flags are provided, then a
1763  * {@link FormatFlagsConversionMismatchException} will be thrown.
1764  *
1765  * <p> The precision is not applicable.  If the precision is specified an
1766  * {@link IllegalFormatPrecisionException} will be thrown.
1767  *
1768  * </table>
1769  *
1770  * <h4><a name="dls">Line Separator</a></h4>
1771  *
1772  * <p> The conversion does not correspond to any argument.
1773  *
1774  * <table cellpadding=5 summary="DTConv">
1775  *
1776  * <tr><td valign="top">{@code 'n'}
1777  *     <td> the platform-specific line separator as returned by {@link
1778  *     System#getProperty System.getProperty("line.separator")}.
1779  *
1780  * </table>
1781  *
1782  * <p> Flags, width, and precision are not applicable.  If any are provided an
1783  * {@link IllegalFormatFlagsException}, {@link IllegalFormatWidthException},
1784  * and {@link IllegalFormatPrecisionException}, respectively will be thrown.
1785  *
1786  * <h4><a name="dpos">Argument Index</a></h4>
1787  *
1788  * <p> Format specifiers can reference arguments in three ways:
1789  *
1790  * <ul>
1791  *
1792  * <li> <i>Explicit indexing</i> is used when the format specifier contains an
1793  * argument index.  The argument index is a decimal integer indicating the
1794  * position of the argument in the argument list.  The first argument is
1795  * referenced by "{@code 1$}", the second by "{@code 2$}", etc.  An argument
1796  * may be referenced more than once.
1797  *
1798  * <p> For example:
1799  *
1800  * <blockquote><pre>
1801  *   formatter.format("%4$s %3$s %2$s %1$s %4$s %3$s %2$s %1$s",
1802  *                    "a", "b", "c", "d")
1803  *   // -&gt; "d c b a d c b a"
1804  * </pre></blockquote>
1805  *
1806  * <li> <i>Relative indexing</i> is used when the format specifier contains a
1807  * {@code '<'} (<tt>'&#92;u003c'</tt>) flag which causes the argument for
1808  * the previous format specifier to be re-used.  If there is no previous
1809  * argument, then a {@link MissingFormatArgumentException} is thrown.
1810  *
1811  * <blockquote><pre>
1812  *    formatter.format("%s %s %&lt;s %&lt;s", "a", "b", "c", "d")
1813  *    // -&gt; "a b b b"
1814  *    // "c" and "d" are ignored because they are not referenced
1815  * </pre></blockquote>
1816  *
1817  * <li> <i>Ordinary indexing</i> is used when the format specifier contains
1818  * neither an argument index nor a {@code '<'} flag.  Each format specifier
1819  * which uses ordinary indexing is assigned a sequential implicit index into
1820  * argument list which is independent of the indices used by explicit or
1821  * relative indexing.
1822  *
1823  * <blockquote><pre>
1824  *   formatter.format("%s %s %s %s", "a", "b", "c", "d")
1825  *   // -&gt; "a b c d"
1826  * </pre></blockquote>
1827  *
1828  * </ul>
1829  *
1830  * <p> It is possible to have a format string which uses all forms of indexing,
1831  * for example:
1832  *
1833  * <blockquote><pre>
1834  *   formatter.format("%2$s %s %&lt;s %s", "a", "b", "c", "d")
1835  *   // -&gt; "b a a b"
1836  *   // "c" and "d" are ignored because they are not referenced
1837  * </pre></blockquote>
1838  *
1839  * <p> The maximum number of arguments is limited by the maximum dimension of a
1840  * Java array as defined by
1841  * <cite>The Java&trade; Virtual Machine Specification</cite>.
1842  * If the argument index is does not correspond to an
1843  * available argument, then a {@link MissingFormatArgumentException} is thrown.
1844  *
1845  * <p> If there are more arguments than format specifiers, the extra arguments
1846  * are ignored.
1847  *
1848  * <p> Unless otherwise specified, passing a {@code null} argument to any
1849  * method or constructor in this class will cause a {@link
1850  * NullPointerException} to be thrown.
1851  *
1852  * @author  Iris Clark
1853  * @since 1.5
1854  */
1855 public final class Formatter implements Closeable, Flushable {
1856     private Appendable a;
1857     private final Locale l;
1858 
1859     private IOException lastException;
1860 
1861     private final char zero;
1862     private static double scaleUp;
1863 
1864     // 1 (sign) + 19 (max # sig digits) + 1 ('.') + 1 ('e') + 1 (sign)
1865     // + 3 (max # exp digits) + 4 (error) = 30
1866     private static final int MAX_FD_CHARS = 30;
1867 
1868     /**
1869      * Returns a charset object for the given charset name.
1870      * @throws NullPointerException          is csn is null
1871      * @throws UnsupportedEncodingException  if the charset is not supported
1872      */
toCharset(String csn)1873     private static Charset toCharset(String csn)
1874         throws UnsupportedEncodingException
1875     {
1876         Objects.requireNonNull(csn, "charsetName");
1877         try {
1878             return Charset.forName(csn);
1879         } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) {
1880             // UnsupportedEncodingException should be thrown
1881             throw new UnsupportedEncodingException(csn);
1882         }
1883     }
1884 
nonNullAppendable(Appendable a)1885     private static final Appendable nonNullAppendable(Appendable a) {
1886         if (a == null)
1887             return new StringBuilder();
1888 
1889         return a;
1890     }
1891 
1892     /* Private constructors */
Formatter(Locale l, Appendable a)1893     private Formatter(Locale l, Appendable a) {
1894         this.a = a;
1895         this.l = l;
1896         this.zero = getZero(l);
1897     }
1898 
Formatter(Charset charset, Locale l, File file)1899     private Formatter(Charset charset, Locale l, File file)
1900         throws FileNotFoundException
1901     {
1902         this(l,
1903              new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), charset)));
1904     }
1905 
1906     /**
1907      * Constructs a new formatter.
1908      *
1909      * <p> The destination of the formatted output is a {@link StringBuilder}
1910      * which may be retrieved by invoking {@link #out out()} and whose
1911      * current content may be converted into a string by invoking {@link
1912      * #toString toString()}.  The locale used is the {@linkplain
1913      * Locale#getDefault(Locale.Category) default locale} for
1914      * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java
1915      * virtual machine.
1916      */
Formatter()1917     public Formatter() {
1918         this(Locale.getDefault(Locale.Category.FORMAT), new StringBuilder());
1919     }
1920 
1921     /**
1922      * Constructs a new formatter with the specified destination.
1923      *
1924      * <p> The locale used is the {@linkplain
1925      * Locale#getDefault(Locale.Category) default locale} for
1926      * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java
1927      * virtual machine.
1928      *
1929      * @param  a
1930      *         Destination for the formatted output.  If {@code a} is
1931      *         {@code null} then a {@link StringBuilder} will be created.
1932      */
Formatter(Appendable a)1933     public Formatter(Appendable a) {
1934         this(Locale.getDefault(Locale.Category.FORMAT), nonNullAppendable(a));
1935     }
1936 
1937     /**
1938      * Constructs a new formatter with the specified locale.
1939      *
1940      * <p> The destination of the formatted output is a {@link StringBuilder}
1941      * which may be retrieved by invoking {@link #out out()} and whose current
1942      * content may be converted into a string by invoking {@link #toString
1943      * toString()}.
1944      *
1945      * @param  l
1946      *         The {@linkplain java.util.Locale locale} to apply during
1947      *         formatting.  If {@code l} is {@code null} then no localization
1948      *         is applied.
1949      */
Formatter(Locale l)1950     public Formatter(Locale l) {
1951         this(l, new StringBuilder());
1952     }
1953 
1954     /**
1955      * Constructs a new formatter with the specified destination and locale.
1956      *
1957      * @param  a
1958      *         Destination for the formatted output.  If {@code a} is
1959      *         {@code null} then a {@link StringBuilder} will be created.
1960      *
1961      * @param  l
1962      *         The {@linkplain java.util.Locale locale} to apply during
1963      *         formatting.  If {@code l} is {@code null} then no localization
1964      *         is applied.
1965      */
Formatter(Appendable a, Locale l)1966     public Formatter(Appendable a, Locale l) {
1967         this(l, nonNullAppendable(a));
1968     }
1969 
1970     /**
1971      * Constructs a new formatter with the specified file name.
1972      *
1973      * <p> The charset used is the {@linkplain
1974      * java.nio.charset.Charset#defaultCharset() default charset} for this
1975      * instance of the Java virtual machine.
1976      *
1977      * <p> The locale used is the {@linkplain
1978      * Locale#getDefault(Locale.Category) default locale} for
1979      * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java
1980      * virtual machine.
1981      *
1982      * @param  fileName
1983      *         The name of the file to use as the destination of this
1984      *         formatter.  If the file exists then it will be truncated to
1985      *         zero size; otherwise, a new file will be created.  The output
1986      *         will be written to the file and is buffered.
1987      *
1988      * @throws  SecurityException
1989      *          If a security manager is present and {@link
1990      *          SecurityManager#checkWrite checkWrite(fileName)} denies write
1991      *          access to the file
1992      *
1993      * @throws  FileNotFoundException
1994      *          If the given file name does not denote an existing, writable
1995      *          regular file and a new regular file of that name cannot be
1996      *          created, or if some other error occurs while opening or
1997      *          creating the file
1998      */
Formatter(String fileName)1999     public Formatter(String fileName) throws FileNotFoundException {
2000         this(Locale.getDefault(Locale.Category.FORMAT),
2001              new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))));
2002     }
2003 
2004     /**
2005      * Constructs a new formatter with the specified file name and charset.
2006      *
2007      * <p> The locale used is the {@linkplain
2008      * Locale#getDefault(Locale.Category) default locale} for
2009      * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java
2010      * virtual machine.
2011      *
2012      * @param  fileName
2013      *         The name of the file to use as the destination of this
2014      *         formatter.  If the file exists then it will be truncated to
2015      *         zero size; otherwise, a new file will be created.  The output
2016      *         will be written to the file and is buffered.
2017      *
2018      * @param  csn
2019      *         The name of a supported {@linkplain java.nio.charset.Charset
2020      *         charset}
2021      *
2022      * @throws  FileNotFoundException
2023      *          If the given file name does not denote an existing, writable
2024      *          regular file and a new regular file of that name cannot be
2025      *          created, or if some other error occurs while opening or
2026      *          creating the file
2027      *
2028      * @throws  SecurityException
2029      *          If a security manager is present and {@link
2030      *          SecurityManager#checkWrite checkWrite(fileName)} denies write
2031      *          access to the file
2032      *
2033      * @throws  UnsupportedEncodingException
2034      *          If the named charset is not supported
2035      */
Formatter(String fileName, String csn)2036     public Formatter(String fileName, String csn)
2037         throws FileNotFoundException, UnsupportedEncodingException
2038     {
2039         this(fileName, csn, Locale.getDefault(Locale.Category.FORMAT));
2040     }
2041 
2042     /**
2043      * Constructs a new formatter with the specified file name, charset, and
2044      * locale.
2045      *
2046      * @param  fileName
2047      *         The name of the file to use as the destination of this
2048      *         formatter.  If the file exists then it will be truncated to
2049      *         zero size; otherwise, a new file will be created.  The output
2050      *         will be written to the file and is buffered.
2051      *
2052      * @param  csn
2053      *         The name of a supported {@linkplain java.nio.charset.Charset
2054      *         charset}
2055      *
2056      * @param  l
2057      *         The {@linkplain java.util.Locale locale} to apply during
2058      *         formatting.  If {@code l} is {@code null} then no localization
2059      *         is applied.
2060      *
2061      * @throws  FileNotFoundException
2062      *          If the given file name does not denote an existing, writable
2063      *          regular file and a new regular file of that name cannot be
2064      *          created, or if some other error occurs while opening or
2065      *          creating the file
2066      *
2067      * @throws  SecurityException
2068      *          If a security manager is present and {@link
2069      *          SecurityManager#checkWrite checkWrite(fileName)} denies write
2070      *          access to the file
2071      *
2072      * @throws  UnsupportedEncodingException
2073      *          If the named charset is not supported
2074      */
Formatter(String fileName, String csn, Locale l)2075     public Formatter(String fileName, String csn, Locale l)
2076         throws FileNotFoundException, UnsupportedEncodingException
2077     {
2078         this(toCharset(csn), l, new File(fileName));
2079     }
2080 
2081     /**
2082      * Constructs a new formatter with the specified file.
2083      *
2084      * <p> The charset used is the {@linkplain
2085      * java.nio.charset.Charset#defaultCharset() default charset} for this
2086      * instance of the Java virtual machine.
2087      *
2088      * <p> The locale used is the {@linkplain
2089      * Locale#getDefault(Locale.Category) default locale} for
2090      * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java
2091      * virtual machine.
2092      *
2093      * @param  file
2094      *         The file to use as the destination of this formatter.  If the
2095      *         file exists then it will be truncated to zero size; otherwise,
2096      *         a new file will be created.  The output will be written to the
2097      *         file and is buffered.
2098      *
2099      * @throws  SecurityException
2100      *          If a security manager is present and {@link
2101      *          SecurityManager#checkWrite checkWrite(file.getPath())} denies
2102      *          write access to the file
2103      *
2104      * @throws  FileNotFoundException
2105      *          If the given file object does not denote an existing, writable
2106      *          regular file and a new regular file of that name cannot be
2107      *          created, or if some other error occurs while opening or
2108      *          creating the file
2109      */
Formatter(File file)2110     public Formatter(File file) throws FileNotFoundException {
2111         this(Locale.getDefault(Locale.Category.FORMAT),
2112              new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))));
2113     }
2114 
2115     /**
2116      * Constructs a new formatter with the specified file and charset.
2117      *
2118      * <p> The locale used is the {@linkplain
2119      * Locale#getDefault(Locale.Category) default locale} for
2120      * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java
2121      * virtual machine.
2122      *
2123      * @param  file
2124      *         The file to use as the destination of this formatter.  If the
2125      *         file exists then it will be truncated to zero size; otherwise,
2126      *         a new file will be created.  The output will be written to the
2127      *         file and is buffered.
2128      *
2129      * @param  csn
2130      *         The name of a supported {@linkplain java.nio.charset.Charset
2131      *         charset}
2132      *
2133      * @throws  FileNotFoundException
2134      *          If the given file object does not denote an existing, writable
2135      *          regular file and a new regular file of that name cannot be
2136      *          created, or if some other error occurs while opening or
2137      *          creating the file
2138      *
2139      * @throws  SecurityException
2140      *          If a security manager is present and {@link
2141      *          SecurityManager#checkWrite checkWrite(file.getPath())} denies
2142      *          write access to the file
2143      *
2144      * @throws  UnsupportedEncodingException
2145      *          If the named charset is not supported
2146      */
Formatter(File file, String csn)2147     public Formatter(File file, String csn)
2148         throws FileNotFoundException, UnsupportedEncodingException
2149     {
2150         this(file, csn, Locale.getDefault(Locale.Category.FORMAT));
2151     }
2152 
2153     /**
2154      * Constructs a new formatter with the specified file, charset, and
2155      * locale.
2156      *
2157      * @param  file
2158      *         The file to use as the destination of this formatter.  If the
2159      *         file exists then it will be truncated to zero size; otherwise,
2160      *         a new file will be created.  The output will be written to the
2161      *         file and is buffered.
2162      *
2163      * @param  csn
2164      *         The name of a supported {@linkplain java.nio.charset.Charset
2165      *         charset}
2166      *
2167      * @param  l
2168      *         The {@linkplain java.util.Locale locale} to apply during
2169      *         formatting.  If {@code l} is {@code null} then no localization
2170      *         is applied.
2171      *
2172      * @throws  FileNotFoundException
2173      *          If the given file object does not denote an existing, writable
2174      *          regular file and a new regular file of that name cannot be
2175      *          created, or if some other error occurs while opening or
2176      *          creating the file
2177      *
2178      * @throws  SecurityException
2179      *          If a security manager is present and {@link
2180      *          SecurityManager#checkWrite checkWrite(file.getPath())} denies
2181      *          write access to the file
2182      *
2183      * @throws  UnsupportedEncodingException
2184      *          If the named charset is not supported
2185      */
Formatter(File file, String csn, Locale l)2186     public Formatter(File file, String csn, Locale l)
2187         throws FileNotFoundException, UnsupportedEncodingException
2188     {
2189         this(toCharset(csn), l, file);
2190     }
2191 
2192     /**
2193      * Constructs a new formatter with the specified print stream.
2194      *
2195      * <p> The locale used is the {@linkplain
2196      * Locale#getDefault(Locale.Category) default locale} for
2197      * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java
2198      * virtual machine.
2199      *
2200      * <p> Characters are written to the given {@link java.io.PrintStream
2201      * PrintStream} object and are therefore encoded using that object's
2202      * charset.
2203      *
2204      * @param  ps
2205      *         The stream to use as the destination of this formatter.
2206      */
Formatter(PrintStream ps)2207     public Formatter(PrintStream ps) {
2208         this(Locale.getDefault(Locale.Category.FORMAT),
2209              (Appendable)Objects.requireNonNull(ps));
2210     }
2211 
2212     /**
2213      * Constructs a new formatter with the specified output stream.
2214      *
2215      * <p> The charset used is the {@linkplain
2216      * java.nio.charset.Charset#defaultCharset() default charset} for this
2217      * instance of the Java virtual machine.
2218      *
2219      * <p> The locale used is the {@linkplain
2220      * Locale#getDefault(Locale.Category) default locale} for
2221      * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java
2222      * virtual machine.
2223      *
2224      * @param  os
2225      *         The output stream to use as the destination of this formatter.
2226      *         The output will be buffered.
2227      */
Formatter(OutputStream os)2228     public Formatter(OutputStream os) {
2229         this(Locale.getDefault(Locale.Category.FORMAT),
2230              new BufferedWriter(new OutputStreamWriter(os)));
2231     }
2232 
2233     /**
2234      * Constructs a new formatter with the specified output stream and
2235      * charset.
2236      *
2237      * <p> The locale used is the {@linkplain
2238      * Locale#getDefault(Locale.Category) default locale} for
2239      * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java
2240      * virtual machine.
2241      *
2242      * @param  os
2243      *         The output stream to use as the destination of this formatter.
2244      *         The output will be buffered.
2245      *
2246      * @param  csn
2247      *         The name of a supported {@linkplain java.nio.charset.Charset
2248      *         charset}
2249      *
2250      * @throws  UnsupportedEncodingException
2251      *          If the named charset is not supported
2252      */
Formatter(OutputStream os, String csn)2253     public Formatter(OutputStream os, String csn)
2254         throws UnsupportedEncodingException
2255     {
2256         this(os, csn, Locale.getDefault(Locale.Category.FORMAT));
2257     }
2258 
2259     /**
2260      * Constructs a new formatter with the specified output stream, charset,
2261      * and locale.
2262      *
2263      * @param  os
2264      *         The output stream to use as the destination of this formatter.
2265      *         The output will be buffered.
2266      *
2267      * @param  csn
2268      *         The name of a supported {@linkplain java.nio.charset.Charset
2269      *         charset}
2270      *
2271      * @param  l
2272      *         The {@linkplain java.util.Locale locale} to apply during
2273      *         formatting.  If {@code l} is {@code null} then no localization
2274      *         is applied.
2275      *
2276      * @throws  UnsupportedEncodingException
2277      *          If the named charset is not supported
2278      */
Formatter(OutputStream os, String csn, Locale l)2279     public Formatter(OutputStream os, String csn, Locale l)
2280         throws UnsupportedEncodingException
2281     {
2282         this(l, new BufferedWriter(new OutputStreamWriter(os, csn)));
2283     }
2284 
getZero(Locale l)2285     private static char getZero(Locale l) {
2286         if ((l != null) && !l.equals(Locale.US)) {
2287             // Android-changed: Improve the performance by 10x http://b/197788756
2288             // Unclear if this mapping is needed but inherited from DecimalFormatSymbols
2289             l = LocaleData.mapInvalidAndNullLocales(l);
2290             DecimalFormatData decimalFormatData = DecimalFormatData.getInstance(l);
2291             return decimalFormatData.getZeroDigit();
2292             // DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(l);
2293             //  return dfs.getZeroDigit();
2294         } else {
2295             return '0';
2296         }
2297     }
2298 
2299     /**
2300      * Returns the locale set by the construction of this formatter.
2301      *
2302      * <p> The {@link #format(java.util.Locale,String,Object...) format} method
2303      * for this object which has a locale argument does not change this value.
2304      *
2305      * @return  {@code null} if no localization is applied, otherwise a
2306      *          locale
2307      *
2308      * @throws  FormatterClosedException
2309      *          If this formatter has been closed by invoking its {@link
2310      *          #close()} method
2311      */
locale()2312     public Locale locale() {
2313         ensureOpen();
2314         return l;
2315     }
2316 
2317     /**
2318      * Returns the destination for the output.
2319      *
2320      * @return  The destination for the output
2321      *
2322      * @throws  FormatterClosedException
2323      *          If this formatter has been closed by invoking its {@link
2324      *          #close()} method
2325      */
out()2326     public Appendable out() {
2327         ensureOpen();
2328         return a;
2329     }
2330 
2331     /**
2332      * Returns the result of invoking {@code toString()} on the destination
2333      * for the output.  For example, the following code formats text into a
2334      * {@link StringBuilder} then retrieves the resultant string:
2335      *
2336      * <blockquote><pre>
2337      *   Formatter f = new Formatter();
2338      *   f.format("Last reboot at %tc", lastRebootDate);
2339      *   String s = f.toString();
2340      *   // -&gt; s == "Last reboot at Sat Jan 01 00:00:00 PST 2000"
2341      * </pre></blockquote>
2342      *
2343      * <p> An invocation of this method behaves in exactly the same way as the
2344      * invocation
2345      *
2346      * <pre>
2347      *     out().toString() </pre>
2348      *
2349      * <p> Depending on the specification of {@code toString} for the {@link
2350      * Appendable}, the returned string may or may not contain the characters
2351      * written to the destination.  For instance, buffers typically return
2352      * their contents in {@code toString()}, but streams cannot since the
2353      * data is discarded.
2354      *
2355      * @return  The result of invoking {@code toString()} on the destination
2356      *          for the output
2357      *
2358      * @throws  FormatterClosedException
2359      *          If this formatter has been closed by invoking its {@link
2360      *          #close()} method
2361      */
toString()2362     public String toString() {
2363         ensureOpen();
2364         return a.toString();
2365     }
2366 
2367     /**
2368      * Flushes this formatter.  If the destination implements the {@link
2369      * java.io.Flushable} interface, its {@code flush} method will be invoked.
2370      *
2371      * <p> Flushing a formatter writes any buffered output in the destination
2372      * to the underlying stream.
2373      *
2374      * @throws  FormatterClosedException
2375      *          If this formatter has been closed by invoking its {@link
2376      *          #close()} method
2377      */
flush()2378     public void flush() {
2379         ensureOpen();
2380         if (a instanceof Flushable) {
2381             try {
2382                 ((Flushable)a).flush();
2383             } catch (IOException ioe) {
2384                 lastException = ioe;
2385             }
2386         }
2387     }
2388 
2389     /**
2390      * Closes this formatter.  If the destination implements the {@link
2391      * java.io.Closeable} interface, its {@code close} method will be invoked.
2392      *
2393      * <p> Closing a formatter allows it to release resources it may be holding
2394      * (such as open files).  If the formatter is already closed, then invoking
2395      * this method has no effect.
2396      *
2397      * <p> Attempting to invoke any methods except {@link #ioException()} in
2398      * this formatter after it has been closed will result in a {@link
2399      * FormatterClosedException}.
2400      */
close()2401     public void close() {
2402         if (a == null)
2403             return;
2404         try {
2405             if (a instanceof Closeable)
2406                 ((Closeable)a).close();
2407         } catch (IOException ioe) {
2408             lastException = ioe;
2409         } finally {
2410             a = null;
2411         }
2412     }
2413 
ensureOpen()2414     private void ensureOpen() {
2415         if (a == null)
2416             throw new FormatterClosedException();
2417     }
2418 
2419     /**
2420      * Returns the {@code IOException} last thrown by this formatter's {@link
2421      * Appendable}.
2422      *
2423      * <p> If the destination's {@code append()} method never throws
2424      * {@code IOException}, then this method will always return {@code null}.
2425      *
2426      * @return  The last exception thrown by the Appendable or {@code null} if
2427      *          no such exception exists.
2428      */
ioException()2429     public IOException ioException() {
2430         return lastException;
2431     }
2432 
2433     /**
2434      * Writes a formatted string to this object's destination using the
2435      * specified format string and arguments.  The locale used is the one
2436      * defined during the construction of this formatter.
2437      *
2438      * @param  format
2439      *         A format string as described in <a href="#syntax">Format string
2440      *         syntax</a>.
2441      *
2442      * @param  args
2443      *         Arguments referenced by the format specifiers in the format
2444      *         string.  If there are more arguments than format specifiers, the
2445      *         extra arguments are ignored.  The maximum number of arguments is
2446      *         limited by the maximum dimension of a Java array as defined by
2447      *         <cite>The Java&trade; Virtual Machine Specification</cite>.
2448      *
2449      * @throws  IllegalFormatException
2450      *          If a format string contains an illegal syntax, a format
2451      *          specifier that is incompatible with the given arguments,
2452      *          insufficient arguments given the format string, or other
2453      *          illegal conditions.  For specification of all possible
2454      *          formatting errors, see the <a href="#detail">Details</a>
2455      *          section of the formatter class specification.
2456      *
2457      * @throws  FormatterClosedException
2458      *          If this formatter has been closed by invoking its {@link
2459      *          #close()} method
2460      *
2461      * @return  This formatter
2462      */
format(String format, Object ... args)2463     public Formatter format(String format, Object ... args) {
2464         return format(l, format, args);
2465     }
2466 
2467     /**
2468      * Writes a formatted string to this object's destination using the
2469      * specified locale, format string, and arguments.
2470      *
2471      * @param  l
2472      *         The {@linkplain java.util.Locale locale} to apply during
2473      *         formatting.  If {@code l} is {@code null} then no localization
2474      *         is applied.  This does not change this object's locale that was
2475      *         set during construction.
2476      *
2477      * @param  format
2478      *         A format string as described in <a href="#syntax">Format string
2479      *         syntax</a>
2480      *
2481      * @param  args
2482      *         Arguments referenced by the format specifiers in the format
2483      *         string.  If there are more arguments than format specifiers, the
2484      *         extra arguments are ignored.  The maximum number of arguments is
2485      *         limited by the maximum dimension of a Java array as defined by
2486      *         <cite>The Java&trade; Virtual Machine Specification</cite>.
2487      *
2488      * @throws  IllegalFormatException
2489      *          If a format string contains an illegal syntax, a format
2490      *          specifier that is incompatible with the given arguments,
2491      *          insufficient arguments given the format string, or other
2492      *          illegal conditions.  For specification of all possible
2493      *          formatting errors, see the <a href="#detail">Details</a>
2494      *          section of the formatter class specification.
2495      *
2496      * @throws  FormatterClosedException
2497      *          If this formatter has been closed by invoking its {@link
2498      *          #close()} method
2499      *
2500      * @return  This formatter
2501      */
format(Locale l, String format, Object ... args)2502     public Formatter format(Locale l, String format, Object ... args) {
2503         ensureOpen();
2504 
2505         // index of last argument referenced
2506         int last = -1;
2507         // last ordinary index
2508         int lasto = -1;
2509 
2510         FormatString[] fsa = parse(format);
2511         for (int i = 0; i < fsa.length; i++) {
2512             FormatString fs = fsa[i];
2513             int index = fs.index();
2514             try {
2515                 switch (index) {
2516                 case -2:  // fixed string, "%n", or "%%"
2517                     fs.print(null, l);
2518                     break;
2519                 case -1:  // relative index
2520                     if (last < 0 || (args != null && last > args.length - 1))
2521                         throw new MissingFormatArgumentException(fs.toString());
2522                     fs.print((args == null ? null : args[last]), l);
2523                     break;
2524                 case 0:  // ordinary index
2525                     lasto++;
2526                     last = lasto;
2527                     if (args != null && lasto > args.length - 1)
2528                         throw new MissingFormatArgumentException(fs.toString());
2529                     fs.print((args == null ? null : args[lasto]), l);
2530                     break;
2531                 default:  // explicit index
2532                     last = index - 1;
2533                     if (args != null && last > args.length - 1)
2534                         throw new MissingFormatArgumentException(fs.toString());
2535                     fs.print((args == null ? null : args[last]), l);
2536                     break;
2537                 }
2538             } catch (IOException x) {
2539                 lastException = x;
2540             }
2541         }
2542         return this;
2543     }
2544 
2545     // BEGIN Android-changed: changed parse() to manual parsing instead of regex.
2546     /**
2547      * Finds format specifiers in the format string.
2548      */
parse(String s)2549     private FormatString[] parse(String s) {
2550         ArrayList<FormatString> al = new ArrayList<>();
2551         for (int i = 0, len = s.length(); i < len; ) {
2552             int nextPercent = s.indexOf('%', i);
2553             if (s.charAt(i) != '%') {
2554                 // This is plain-text part, find the maximal plain-text
2555                 // sequence and store it.
2556                 int plainTextStart = i;
2557                 int plainTextEnd = (nextPercent == -1) ? len: nextPercent;
2558                 al.add(new FixedString(s.substring(plainTextStart,
2559                                                    plainTextEnd)));
2560                 i = plainTextEnd;
2561             } else {
2562                 // We have a format specifier
2563                 FormatSpecifierParser fsp = new FormatSpecifierParser(s, i + 1);
2564                 al.add(fsp.getFormatSpecifier());
2565                 i = fsp.getEndIdx();
2566             }
2567         }
2568         return al.toArray(new FormatString[al.size()]);
2569     }
2570 
2571     /**
2572      * Parses the format specifier.
2573      * %[argument_index$][flags][width][.precision][t]conversion
2574      */
2575     private class FormatSpecifierParser {
2576         private final String format;
2577         private int cursor;
2578         private FormatSpecifier fs;
2579 
2580         private String index;
2581         private String flags;
2582         private String width;
2583         private String precision;
2584         private String tT;
2585         private String conv;
2586 
2587         private static final String FLAGS = ",-(+# 0<";
2588 
FormatSpecifierParser(String format, int startIdx)2589         public FormatSpecifierParser(String format, int startIdx) {
2590             this.format = format;
2591             cursor = startIdx;
2592             // Index
2593             if (nextIsInt()) {
2594                 String nint = nextInt();
2595                 if (peek() == '$') {
2596                     index = nint;
2597                     advance();
2598                 } else if (nint.charAt(0) == '0') {
2599                     // This is a flag, skip to parsing flags.
2600                     back(nint.length());
2601                 } else {
2602                     // This is the width, skip to parsing precision.
2603                     width = nint;
2604                 }
2605             }
2606             // Flags
2607             flags = "";
2608             while (width == null && FLAGS.indexOf(peek()) >= 0) {
2609                 flags += advance();
2610             }
2611             // Width
2612             if (width == null && nextIsInt()) {
2613                 width = nextInt();
2614             }
2615             // Precision
2616             if (peek() == '.') {
2617                 advance();
2618                 if (!nextIsInt()) {
2619                     throw new IllegalFormatPrecisionException(peek());
2620                 }
2621                 precision = nextInt();
2622             }
2623             // tT
2624             if (peek() == 't' || peek() == 'T') {
2625                 tT = String.valueOf(advance());
2626             }
2627             // Conversion
2628             conv = String.valueOf(advance());
2629 
2630             fs = new FormatSpecifier(index, flags, width, precision, tT, conv);
2631         }
2632 
nextInt()2633         private String nextInt() {
2634             int strBegin = cursor;
2635             while (nextIsInt()) {
2636                 advance();
2637             }
2638             return format.substring(strBegin, cursor);
2639         }
2640 
nextIsInt()2641         private boolean nextIsInt() {
2642             return !isEnd() && Character.isDigit(peek());
2643         }
2644 
peek()2645         private char peek() {
2646             if (isEnd()) {
2647                 throw new UnknownFormatConversionException("End of String");
2648             }
2649             return format.charAt(cursor);
2650         }
2651 
advance()2652         private char advance() {
2653             if (isEnd()) {
2654                 throw new UnknownFormatConversionException("End of String");
2655             }
2656             return format.charAt(cursor++);
2657         }
2658 
back(int len)2659         private void back(int len) {
2660             cursor -= len;
2661         }
2662 
isEnd()2663         private boolean isEnd() {
2664             return cursor == format.length();
2665         }
2666 
getFormatSpecifier()2667         public FormatSpecifier getFormatSpecifier() {
2668             return fs;
2669         }
2670 
getEndIdx()2671         public int getEndIdx() {
2672             return cursor;
2673         }
2674     }
2675     // END Android-changed: changed parse() to manual parsing instead of regex.
2676 
2677     private interface FormatString {
index()2678         int index();
print(Object arg, Locale l)2679         void print(Object arg, Locale l) throws IOException;
toString()2680         String toString();
2681     }
2682 
2683     private class FixedString implements FormatString {
2684         private String s;
FixedString(String s)2685         FixedString(String s) { this.s = s; }
index()2686         public int index() { return -2; }
print(Object arg, Locale l)2687         public void print(Object arg, Locale l)
2688             throws IOException { a.append(s); }
toString()2689         public String toString() { return s; }
2690     }
2691 
2692     /**
2693      * Enum for {@code BigDecimal} formatting.
2694      */
2695     public enum BigDecimalLayoutForm {
2696         /**
2697          * Format the {@code BigDecimal} in computerized scientific notation.
2698          */
2699         SCIENTIFIC,
2700 
2701         /**
2702          * Format the {@code BigDecimal} as a decimal number.
2703          */
2704         DECIMAL_FLOAT
2705     };
2706 
2707     private class FormatSpecifier implements FormatString {
2708         private int index = -1;
2709         private Flags f = Flags.NONE;
2710         private int width;
2711         private int precision;
2712         private boolean dt = false;
2713         private char c;
2714 
index(String s)2715         private int index(String s) {
2716             if (s != null) {
2717                 try {
2718                     // Android-changed: FormatSpecifierParser passes in correct String.
2719                     // index = Integer.parseInt(s.substring(0, s.length() - 1));
2720                     index = Integer.parseInt(s);
2721                 } catch (NumberFormatException x) {
2722                     assert(false);
2723                 }
2724             } else {
2725                 index = 0;
2726             }
2727             return index;
2728         }
2729 
index()2730         public int index() {
2731             return index;
2732         }
2733 
flags(String s)2734         private Flags flags(String s) {
2735             f = Flags.parse(s);
2736             if (f.contains(Flags.PREVIOUS))
2737                 index = -1;
2738             return f;
2739         }
2740 
flags()2741         Flags flags() {
2742             return f;
2743         }
2744 
width(String s)2745         private int width(String s) {
2746             width = -1;
2747             if (s != null) {
2748                 try {
2749                     width  = Integer.parseInt(s);
2750                     if (width < 0)
2751                         throw new IllegalFormatWidthException(width);
2752                 } catch (NumberFormatException x) {
2753                     assert(false);
2754                 }
2755             }
2756             return width;
2757         }
2758 
width()2759         int width() {
2760             return width;
2761         }
2762 
precision(String s)2763         private int precision(String s) {
2764             precision = -1;
2765             if (s != null) {
2766                 try {
2767                     // Android-changed: FormatSpecifierParser passes in correct String.
2768                     // precision = Integer.parseInt(s.substring(1));
2769                     precision = Integer.parseInt(s);
2770                     if (precision < 0)
2771                         throw new IllegalFormatPrecisionException(precision);
2772                 } catch (NumberFormatException x) {
2773                     assert(false);
2774                 }
2775             }
2776             return precision;
2777         }
2778 
precision()2779         int precision() {
2780             return precision;
2781         }
2782 
conversion(String s)2783         private char conversion(String s) {
2784             c = s.charAt(0);
2785             if (!dt) {
2786                 if (!Conversion.isValid(c))
2787                     throw new UnknownFormatConversionException(String.valueOf(c));
2788                 if (Character.isUpperCase(c))
2789                     f.add(Flags.UPPERCASE);
2790                 c = Character.toLowerCase(c);
2791                 if (Conversion.isText(c))
2792                     index = -2;
2793             }
2794             return c;
2795         }
2796 
conversion()2797         private char conversion() {
2798             return c;
2799         }
2800 
2801         // BEGIN Android-changed: FormatSpecifierParser passes in the values instead of a Matcher.
FormatSpecifier(String indexStr, String flagsStr, String widthStr, String precisionStr, String tTStr, String convStr)2802         FormatSpecifier(String indexStr, String flagsStr, String widthStr,
2803                         String precisionStr, String tTStr, String convStr) {
2804             int idx = 1;
2805 
2806             index(indexStr);
2807             flags(flagsStr);
2808             width(widthStr);
2809             precision(precisionStr);
2810 
2811             if (tTStr != null) {
2812                 dt = true;
2813                 if (tTStr.equals("T"))
2814                     f.add(Flags.UPPERCASE);
2815             }
2816 
2817             conversion(convStr);
2818         // END Android-changed: FormatSpecifierParser passes in the values instead of a Matcher.
2819             if (dt)
2820                 checkDateTime();
2821             else if (Conversion.isGeneral(c))
2822                 checkGeneral();
2823             else if (Conversion.isCharacter(c))
2824                 checkCharacter();
2825             else if (Conversion.isInteger(c))
2826                 checkInteger();
2827             else if (Conversion.isFloat(c))
2828                 checkFloat();
2829             else if (Conversion.isText(c))
2830                 checkText();
2831             else
2832                 throw new UnknownFormatConversionException(String.valueOf(c));
2833         }
2834 
print(Object arg, Locale l)2835         public void print(Object arg, Locale l) throws IOException {
2836             if (dt) {
2837                 printDateTime(arg, l);
2838                 return;
2839             }
2840             switch(c) {
2841             case Conversion.DECIMAL_INTEGER:
2842             case Conversion.OCTAL_INTEGER:
2843             case Conversion.HEXADECIMAL_INTEGER:
2844                 printInteger(arg, l);
2845                 break;
2846             case Conversion.SCIENTIFIC:
2847             case Conversion.GENERAL:
2848             case Conversion.DECIMAL_FLOAT:
2849             case Conversion.HEXADECIMAL_FLOAT:
2850                 printFloat(arg, l);
2851                 break;
2852             case Conversion.CHARACTER:
2853             case Conversion.CHARACTER_UPPER:
2854                 printCharacter(arg);
2855                 break;
2856             case Conversion.BOOLEAN:
2857                 printBoolean(arg);
2858                 break;
2859             case Conversion.STRING:
2860                 printString(arg, l);
2861                 break;
2862             case Conversion.HASHCODE:
2863                 printHashCode(arg);
2864                 break;
2865             case Conversion.LINE_SEPARATOR:
2866                 a.append(System.lineSeparator());
2867                 break;
2868             case Conversion.PERCENT_SIGN:
2869                 a.append('%');
2870                 break;
2871             default:
2872                 assert false;
2873             }
2874         }
2875 
printInteger(Object arg, Locale l)2876         private void printInteger(Object arg, Locale l) throws IOException {
2877             if (arg == null)
2878                 print("null");
2879             else if (arg instanceof Byte)
2880                 print(((Byte)arg).byteValue(), l);
2881             else if (arg instanceof Short)
2882                 print(((Short)arg).shortValue(), l);
2883             else if (arg instanceof Integer)
2884                 print(((Integer)arg).intValue(), l);
2885             else if (arg instanceof Long)
2886                 print(((Long)arg).longValue(), l);
2887             else if (arg instanceof BigInteger)
2888                 print(((BigInteger)arg), l);
2889             else
2890                 failConversion(c, arg);
2891         }
2892 
printFloat(Object arg, Locale l)2893         private void printFloat(Object arg, Locale l) throws IOException {
2894             if (arg == null)
2895                 print("null");
2896             else if (arg instanceof Float)
2897                 print(((Float)arg).floatValue(), l);
2898             else if (arg instanceof Double)
2899                 print(((Double)arg).doubleValue(), l);
2900             else if (arg instanceof BigDecimal)
2901                 print(((BigDecimal)arg), l);
2902             else
2903                 failConversion(c, arg);
2904         }
2905 
printDateTime(Object arg, Locale l)2906         private void printDateTime(Object arg, Locale l) throws IOException {
2907             if (arg == null) {
2908                 print("null");
2909                 return;
2910             }
2911             Calendar cal = null;
2912 
2913             // Instead of Calendar.setLenient(true), perhaps we should
2914             // wrap the IllegalArgumentException that might be thrown?
2915             if (arg instanceof Long) {
2916                 // Note that the following method uses an instance of the
2917                 // default time zone (TimeZone.getDefaultRef().
2918                 cal = Calendar.getInstance(l == null ? Locale.US : l);
2919                 cal.setTimeInMillis((Long)arg);
2920             } else if (arg instanceof Date) {
2921                 // Note that the following method uses an instance of the
2922                 // default time zone (TimeZone.getDefaultRef().
2923                 cal = Calendar.getInstance(l == null ? Locale.US : l);
2924                 cal.setTime((Date)arg);
2925             } else if (arg instanceof Calendar) {
2926                 cal = (Calendar) ((Calendar) arg).clone();
2927                 cal.setLenient(true);
2928             } else if (arg instanceof TemporalAccessor) {
2929                 print((TemporalAccessor) arg, c, l);
2930                 return;
2931             } else {
2932                 failConversion(c, arg);
2933             }
2934             // Use the provided locale so that invocations of
2935             // localizedMagnitude() use optimizations for null.
2936             print(cal, c, l);
2937         }
2938 
printCharacter(Object arg)2939         private void printCharacter(Object arg) throws IOException {
2940             if (arg == null) {
2941                 print("null");
2942                 return;
2943             }
2944             String s = null;
2945             if (arg instanceof Character) {
2946                 s = ((Character)arg).toString();
2947             } else if (arg instanceof Byte) {
2948                 byte i = ((Byte)arg).byteValue();
2949                 if (Character.isValidCodePoint(i))
2950                     s = new String(Character.toChars(i));
2951                 else
2952                     throw new IllegalFormatCodePointException(i);
2953             } else if (arg instanceof Short) {
2954                 short i = ((Short)arg).shortValue();
2955                 if (Character.isValidCodePoint(i))
2956                     s = new String(Character.toChars(i));
2957                 else
2958                     throw new IllegalFormatCodePointException(i);
2959             } else if (arg instanceof Integer) {
2960                 int i = ((Integer)arg).intValue();
2961                 if (Character.isValidCodePoint(i))
2962                     s = new String(Character.toChars(i));
2963                 else
2964                     throw new IllegalFormatCodePointException(i);
2965             } else {
2966                 failConversion(c, arg);
2967             }
2968             print(s);
2969         }
2970 
printString(Object arg, Locale l)2971         private void printString(Object arg, Locale l) throws IOException {
2972             if (arg instanceof Formattable) {
2973                 Formatter fmt = Formatter.this;
2974                 if (fmt.locale() != l)
2975                     fmt = new Formatter(fmt.out(), l);
2976                 ((Formattable)arg).formatTo(fmt, f.valueOf(), width, precision);
2977             } else {
2978                 if (f.contains(Flags.ALTERNATE))
2979                     failMismatch(Flags.ALTERNATE, 's');
2980                 if (arg == null)
2981                     print("null");
2982                 else
2983                     print(arg.toString());
2984             }
2985         }
2986 
printBoolean(Object arg)2987         private void printBoolean(Object arg) throws IOException {
2988             String s;
2989             if (arg != null)
2990                 s = ((arg instanceof Boolean)
2991                      ? ((Boolean)arg).toString()
2992                      : Boolean.toString(true));
2993             else
2994                 s = Boolean.toString(false);
2995             print(s);
2996         }
2997 
printHashCode(Object arg)2998         private void printHashCode(Object arg) throws IOException {
2999             String s = (arg == null
3000                         ? "null"
3001                         : Integer.toHexString(arg.hashCode()));
3002             print(s);
3003         }
3004 
print(String s)3005         private void print(String s) throws IOException {
3006             if (precision != -1 && precision < s.length())
3007                 s = s.substring(0, precision);
3008             if (f.contains(Flags.UPPERCASE)) {
3009                 // Android-changed: Use provided locale instead of default, if it is non-null.
3010                 // s = s.toUpperCase();
3011                 s = s.toUpperCase(l != null ? l : Locale.getDefault());
3012             }
3013             a.append(justify(s));
3014         }
3015 
justify(String s)3016         private String justify(String s) {
3017             if (width == -1)
3018                 return s;
3019             StringBuilder sb = new StringBuilder();
3020             boolean pad = f.contains(Flags.LEFT_JUSTIFY);
3021             int sp = width - s.length();
3022             if (!pad)
3023                 for (int i = 0; i < sp; i++) sb.append(' ');
3024             sb.append(s);
3025             if (pad)
3026                 for (int i = 0; i < sp; i++) sb.append(' ');
3027             return sb.toString();
3028         }
3029 
toString()3030         public String toString() {
3031             StringBuilder sb = new StringBuilder("%");
3032             // Flags.UPPERCASE is set internally for legal conversions.
3033             Flags dupf = f.dup().remove(Flags.UPPERCASE);
3034             sb.append(dupf.toString());
3035             if (index > 0)
3036                 sb.append(index).append('$');
3037             if (width != -1)
3038                 sb.append(width);
3039             if (precision != -1)
3040                 sb.append('.').append(precision);
3041             if (dt)
3042                 sb.append(f.contains(Flags.UPPERCASE) ? 'T' : 't');
3043             sb.append(f.contains(Flags.UPPERCASE)
3044                       ? Character.toUpperCase(c) : c);
3045             return sb.toString();
3046         }
3047 
checkGeneral()3048         private void checkGeneral() {
3049             if ((c == Conversion.BOOLEAN || c == Conversion.HASHCODE)
3050                 && f.contains(Flags.ALTERNATE))
3051                 failMismatch(Flags.ALTERNATE, c);
3052             // '-' requires a width
3053             if (width == -1 && f.contains(Flags.LEFT_JUSTIFY))
3054                 throw new MissingFormatWidthException(toString());
3055             checkBadFlags(Flags.PLUS, Flags.LEADING_SPACE, Flags.ZERO_PAD,
3056                           Flags.GROUP, Flags.PARENTHESES);
3057         }
3058 
checkDateTime()3059         private void checkDateTime() {
3060             if (precision != -1)
3061                 throw new IllegalFormatPrecisionException(precision);
3062             if (!DateTime.isValid(c))
3063                 throw new UnknownFormatConversionException("t" + c);
3064             checkBadFlags(Flags.ALTERNATE, Flags.PLUS, Flags.LEADING_SPACE,
3065                           Flags.ZERO_PAD, Flags.GROUP, Flags.PARENTHESES);
3066             // '-' requires a width
3067             if (width == -1 && f.contains(Flags.LEFT_JUSTIFY))
3068                 throw new MissingFormatWidthException(toString());
3069         }
3070 
checkCharacter()3071         private void checkCharacter() {
3072             if (precision != -1)
3073                 throw new IllegalFormatPrecisionException(precision);
3074             checkBadFlags(Flags.ALTERNATE, Flags.PLUS, Flags.LEADING_SPACE,
3075                           Flags.ZERO_PAD, Flags.GROUP, Flags.PARENTHESES);
3076             // '-' requires a width
3077             if (width == -1 && f.contains(Flags.LEFT_JUSTIFY))
3078                 throw new MissingFormatWidthException(toString());
3079         }
3080 
checkInteger()3081         private void checkInteger() {
3082             checkNumeric();
3083             if (precision != -1)
3084                 throw new IllegalFormatPrecisionException(precision);
3085 
3086             if (c == Conversion.DECIMAL_INTEGER)
3087                 checkBadFlags(Flags.ALTERNATE);
3088             else if (c == Conversion.OCTAL_INTEGER)
3089                 checkBadFlags(Flags.GROUP);
3090             else
3091                 checkBadFlags(Flags.GROUP);
3092         }
3093 
checkBadFlags(Flags .... badFlags)3094         private void checkBadFlags(Flags ... badFlags) {
3095             for (int i = 0; i < badFlags.length; i++)
3096                 if (f.contains(badFlags[i]))
3097                     failMismatch(badFlags[i], c);
3098         }
3099 
checkFloat()3100         private void checkFloat() {
3101             checkNumeric();
3102             if (c == Conversion.DECIMAL_FLOAT) {
3103             } else if (c == Conversion.HEXADECIMAL_FLOAT) {
3104                 checkBadFlags(Flags.PARENTHESES, Flags.GROUP);
3105             } else if (c == Conversion.SCIENTIFIC) {
3106                 checkBadFlags(Flags.GROUP);
3107             } else if (c == Conversion.GENERAL) {
3108                 checkBadFlags(Flags.ALTERNATE);
3109             }
3110         }
3111 
checkNumeric()3112         private void checkNumeric() {
3113             if (width != -1 && width < 0)
3114                 throw new IllegalFormatWidthException(width);
3115 
3116             if (precision != -1 && precision < 0)
3117                 throw new IllegalFormatPrecisionException(precision);
3118 
3119             // '-' and '0' require a width
3120             if (width == -1
3121                 && (f.contains(Flags.LEFT_JUSTIFY) || f.contains(Flags.ZERO_PAD)))
3122                 throw new MissingFormatWidthException(toString());
3123 
3124             // bad combination
3125             if ((f.contains(Flags.PLUS) && f.contains(Flags.LEADING_SPACE))
3126                 || (f.contains(Flags.LEFT_JUSTIFY) && f.contains(Flags.ZERO_PAD)))
3127                 throw new IllegalFormatFlagsException(f.toString());
3128         }
3129 
checkText()3130         private void checkText() {
3131             if (precision != -1)
3132                 throw new IllegalFormatPrecisionException(precision);
3133             switch (c) {
3134             case Conversion.PERCENT_SIGN:
3135                 if (f.valueOf() != Flags.LEFT_JUSTIFY.valueOf()
3136                     && f.valueOf() != Flags.NONE.valueOf())
3137                     throw new IllegalFormatFlagsException(f.toString());
3138                 // '-' requires a width
3139                 if (width == -1 && f.contains(Flags.LEFT_JUSTIFY))
3140                     throw new MissingFormatWidthException(toString());
3141                 break;
3142             case Conversion.LINE_SEPARATOR:
3143                 if (width != -1)
3144                     throw new IllegalFormatWidthException(width);
3145                 if (f.valueOf() != Flags.NONE.valueOf())
3146                     throw new IllegalFormatFlagsException(f.toString());
3147                 break;
3148             default:
3149                 assert false;
3150             }
3151         }
3152 
print(byte value, Locale l)3153         private void print(byte value, Locale l) throws IOException {
3154             long v = value;
3155             if (value < 0
3156                 && (c == Conversion.OCTAL_INTEGER
3157                     || c == Conversion.HEXADECIMAL_INTEGER)) {
3158                 v += (1L << 8);
3159                 assert v >= 0 : v;
3160             }
3161             print(v, l);
3162         }
3163 
print(short value, Locale l)3164         private void print(short value, Locale l) throws IOException {
3165             long v = value;
3166             if (value < 0
3167                 && (c == Conversion.OCTAL_INTEGER
3168                     || c == Conversion.HEXADECIMAL_INTEGER)) {
3169                 v += (1L << 16);
3170                 assert v >= 0 : v;
3171             }
3172             print(v, l);
3173         }
3174 
print(int value, Locale l)3175         private void print(int value, Locale l) throws IOException {
3176             long v = value;
3177             if (value < 0
3178                 && (c == Conversion.OCTAL_INTEGER
3179                     || c == Conversion.HEXADECIMAL_INTEGER)) {
3180                 v += (1L << 32);
3181                 assert v >= 0 : v;
3182             }
3183             print(v, l);
3184         }
3185 
print(long value, Locale l)3186         private void print(long value, Locale l) throws IOException {
3187 
3188             StringBuilder sb = new StringBuilder();
3189 
3190             if (c == Conversion.DECIMAL_INTEGER) {
3191                 boolean neg = value < 0;
3192                 char[] va;
3193                 if (value < 0)
3194                     va = Long.toString(value, 10).substring(1).toCharArray();
3195                 else
3196                     va = Long.toString(value, 10).toCharArray();
3197 
3198                 // leading sign indicator
3199                 leadingSign(sb, neg);
3200 
3201                 // the value
3202                 localizedMagnitude(sb, va, f, adjustWidth(width, f, neg), l);
3203 
3204                 // trailing sign indicator
3205                 trailingSign(sb, neg);
3206             } else if (c == Conversion.OCTAL_INTEGER) {
3207                 checkBadFlags(Flags.PARENTHESES, Flags.LEADING_SPACE,
3208                               Flags.PLUS);
3209                 String s = Long.toOctalString(value);
3210                 int len = (f.contains(Flags.ALTERNATE)
3211                            ? s.length() + 1
3212                            : s.length());
3213 
3214                 // apply ALTERNATE (radix indicator for octal) before ZERO_PAD
3215                 if (f.contains(Flags.ALTERNATE))
3216                     sb.append('0');
3217                 if (f.contains(Flags.ZERO_PAD))
3218                     for (int i = 0; i < width - len; i++) sb.append('0');
3219                 sb.append(s);
3220             } else if (c == Conversion.HEXADECIMAL_INTEGER) {
3221                 checkBadFlags(Flags.PARENTHESES, Flags.LEADING_SPACE,
3222                               Flags.PLUS);
3223                 String s = Long.toHexString(value);
3224                 int len = (f.contains(Flags.ALTERNATE)
3225                            ? s.length() + 2
3226                            : s.length());
3227 
3228                 // apply ALTERNATE (radix indicator for hex) before ZERO_PAD
3229                 if (f.contains(Flags.ALTERNATE))
3230                     sb.append(f.contains(Flags.UPPERCASE) ? "0X" : "0x");
3231                 if (f.contains(Flags.ZERO_PAD))
3232                     for (int i = 0; i < width - len; i++) sb.append('0');
3233                 if (f.contains(Flags.UPPERCASE))
3234                     s = s.toUpperCase();
3235                 sb.append(s);
3236             }
3237 
3238             // justify based on width
3239             a.append(justify(sb.toString()));
3240         }
3241 
3242         // neg := val < 0
3243         private StringBuilder leadingSign(StringBuilder sb, boolean neg) {
3244             if (!neg) {
3245                 if (f.contains(Flags.PLUS)) {
3246                     sb.append('+');
3247                 } else if (f.contains(Flags.LEADING_SPACE)) {
3248                     sb.append(' ');
3249                 }
3250             } else {
3251                 if (f.contains(Flags.PARENTHESES))
3252                     sb.append('(');
3253                 else
3254                     sb.append('-');
3255             }
3256             return sb;
3257         }
3258 
3259         // neg := val < 0
3260         private StringBuilder trailingSign(StringBuilder sb, boolean neg) {
3261             if (neg && f.contains(Flags.PARENTHESES))
3262                 sb.append(')');
3263             return sb;
3264         }
3265 
3266         private void print(BigInteger value, Locale l) throws IOException {
3267             StringBuilder sb = new StringBuilder();
3268             boolean neg = value.signum() == -1;
3269             BigInteger v = value.abs();
3270 
3271             // leading sign indicator
3272             leadingSign(sb, neg);
3273 
3274             // the value
3275             if (c == Conversion.DECIMAL_INTEGER) {
3276                 char[] va = v.toString().toCharArray();
3277                 localizedMagnitude(sb, va, f, adjustWidth(width, f, neg), l);
3278             } else if (c == Conversion.OCTAL_INTEGER) {
3279                 String s = v.toString(8);
3280 
3281                 int len = s.length() + sb.length();
3282                 if (neg && f.contains(Flags.PARENTHESES))
3283                     len++;
3284 
3285                 // apply ALTERNATE (radix indicator for octal) before ZERO_PAD
3286                 if (f.contains(Flags.ALTERNATE)) {
3287                     len++;
3288                     sb.append('0');
3289                 }
3290                 if (f.contains(Flags.ZERO_PAD)) {
3291                     for (int i = 0; i < width - len; i++)
3292                         sb.append('0');
3293                 }
3294                 sb.append(s);
3295             } else if (c == Conversion.HEXADECIMAL_INTEGER) {
3296                 String s = v.toString(16);
3297 
3298                 int len = s.length() + sb.length();
3299                 if (neg && f.contains(Flags.PARENTHESES))
3300                     len++;
3301 
3302                 // apply ALTERNATE (radix indicator for hex) before ZERO_PAD
3303                 if (f.contains(Flags.ALTERNATE)) {
3304                     len += 2;
3305                     sb.append(f.contains(Flags.UPPERCASE) ? "0X" : "0x");
3306                 }
3307                 if (f.contains(Flags.ZERO_PAD))
3308                     for (int i = 0; i < width - len; i++)
3309                         sb.append('0');
3310                 if (f.contains(Flags.UPPERCASE))
3311                     s = s.toUpperCase();
3312                 sb.append(s);
3313             }
3314 
3315             // trailing sign indicator
3316             trailingSign(sb, (value.signum() == -1));
3317 
3318             // justify based on width
3319             a.append(justify(sb.toString()));
3320         }
3321 
3322         private void print(float value, Locale l) throws IOException {
3323             print((double) value, l);
3324         }
3325 
3326         private void print(double value, Locale l) throws IOException {
3327             StringBuilder sb = new StringBuilder();
3328             boolean neg = Double.compare(value, 0.0) == -1;
3329 
3330             if (!Double.isNaN(value)) {
3331                 double v = Math.abs(value);
3332 
3333                 // leading sign indicator
3334                 leadingSign(sb, neg);
3335 
3336                 // the value
3337                 if (!Double.isInfinite(v))
3338                     print(sb, v, l, f, c, precision, neg);
3339                 else
3340                     sb.append(f.contains(Flags.UPPERCASE)
3341                               ? "INFINITY" : "Infinity");
3342 
3343                 // trailing sign indicator
3344                 trailingSign(sb, neg);
3345             } else {
3346                 sb.append(f.contains(Flags.UPPERCASE) ? "NAN" : "NaN");
3347             }
3348 
3349             // justify based on width
3350             a.append(justify(sb.toString()));
3351         }
3352 
3353         // !Double.isInfinite(value) && !Double.isNaN(value)
3354         private void print(StringBuilder sb, double value, Locale l,
3355                            Flags f, char c, int precision, boolean neg)
3356             throws IOException
3357         {
3358             if (c == Conversion.SCIENTIFIC) {
3359                 // Create a new FormattedFloatingDecimal with the desired
3360                 // precision.
3361                 int prec = (precision == -1 ? 6 : precision);
3362 
3363                 FormattedFloatingDecimal fd
3364                         = FormattedFloatingDecimal.valueOf(value, prec,
3365                           FormattedFloatingDecimal.Form.SCIENTIFIC);
3366 
3367                 char[] mant = addZeros(fd.getMantissa(), prec);
3368 
3369                 // If the precision is zero and the '#' flag is set, add the
3370                 // requested decimal point.
3371                 if (f.contains(Flags.ALTERNATE) && (prec == 0))
3372                     mant = addDot(mant);
3373 
3374                 char[] exp = (value == 0.0)
3375                     ? new char[] {'+','0','0'} : fd.getExponent();
3376 
3377                 int newW = width;
3378                 if (width != -1)
3379                     newW = adjustWidth(width - exp.length - 1, f, neg);
3380                 localizedMagnitude(sb, mant, f, newW, l);
3381 
3382                 // BEGIN Android-changed: Use localized exponent separator for %e.
3383                 Locale separatorLocale = (l != null) ? l : Locale.getDefault();
3384                 DecimalFormatData formatData = DecimalFormatData.getInstance(separatorLocale);
3385                 sb.append(f.contains(Flags.UPPERCASE) ?
3386                         formatData.getExponentSeparator().toUpperCase(separatorLocale) :
3387                         formatData.getExponentSeparator().toLowerCase(separatorLocale));
3388                 // END Android-changed: Use localized exponent separator for %e.
3389 
3390                 Flags flags = f.dup().remove(Flags.GROUP);
3391                 char sign = exp[0];
3392                 assert(sign == '+' || sign == '-');
3393                 sb.append(sign);
3394 
3395                 char[] tmp = new char[exp.length - 1];
3396                 System.arraycopy(exp, 1, tmp, 0, exp.length - 1);
3397                 sb.append(localizedMagnitude(null, tmp, flags, -1, l));
3398             } else if (c == Conversion.DECIMAL_FLOAT) {
3399                 // Create a new FormattedFloatingDecimal with the desired
3400                 // precision.
3401                 int prec = (precision == -1 ? 6 : precision);
3402 
3403                 FormattedFloatingDecimal fd
3404                         = FormattedFloatingDecimal.valueOf(value, prec,
3405                           FormattedFloatingDecimal.Form.DECIMAL_FLOAT);
3406 
3407                 char[] mant = addZeros(fd.getMantissa(), prec);
3408 
3409                 // If the precision is zero and the '#' flag is set, add the
3410                 // requested decimal point.
3411                 if (f.contains(Flags.ALTERNATE) && (prec == 0))
3412                     mant = addDot(mant);
3413 
3414                 int newW = width;
3415                 if (width != -1)
3416                     newW = adjustWidth(width, f, neg);
3417                 localizedMagnitude(sb, mant, f, newW, l);
3418             } else if (c == Conversion.GENERAL) {
3419                 int prec = precision;
3420                 if (precision == -1)
3421                     prec = 6;
3422                 else if (precision == 0)
3423                     prec = 1;
3424 
3425                 char[] exp;
3426                 char[] mant;
3427                 int expRounded;
3428                 if (value == 0.0) {
3429                     exp = null;
3430                     mant = new char[] {'0'};
3431                     expRounded = 0;
3432                 } else {
3433                     FormattedFloatingDecimal fd
3434                         = FormattedFloatingDecimal.valueOf(value, prec,
3435                           FormattedFloatingDecimal.Form.GENERAL);
3436                     exp = fd.getExponent();
3437                     mant = fd.getMantissa();
3438                     expRounded = fd.getExponentRounded();
3439                 }
3440 
3441                 if (exp != null) {
3442                     prec -= 1;
3443                 } else {
3444                     prec -= expRounded + 1;
3445                 }
3446 
3447                 mant = addZeros(mant, prec);
3448                 // If the precision is zero and the '#' flag is set, add the
3449                 // requested decimal point.
3450                 if (f.contains(Flags.ALTERNATE) && (prec == 0))
3451                     mant = addDot(mant);
3452 
3453                 int newW = width;
3454                 if (width != -1) {
3455                     if (exp != null)
3456                         newW = adjustWidth(width - exp.length - 1, f, neg);
3457                     else
3458                         newW = adjustWidth(width, f, neg);
3459                 }
3460                 localizedMagnitude(sb, mant, f, newW, l);
3461 
3462                 if (exp != null) {
3463                     sb.append(f.contains(Flags.UPPERCASE) ? 'E' : 'e');
3464 
3465                     Flags flags = f.dup().remove(Flags.GROUP);
3466                     char sign = exp[0];
3467                     assert(sign == '+' || sign == '-');
3468                     sb.append(sign);
3469 
3470                     char[] tmp = new char[exp.length - 1];
3471                     System.arraycopy(exp, 1, tmp, 0, exp.length - 1);
3472                     sb.append(localizedMagnitude(null, tmp, flags, -1, l));
3473                 }
3474             } else if (c == Conversion.HEXADECIMAL_FLOAT) {
3475                 int prec = precision;
3476                 if (precision == -1)
3477                     // assume that we want all of the digits
3478                     prec = 0;
3479                 else if (precision == 0)
3480                     prec = 1;
3481 
3482                 String s = hexDouble(value, prec);
3483 
3484                 char[] va;
3485                 boolean upper = f.contains(Flags.UPPERCASE);
3486                 sb.append(upper ? "0X" : "0x");
3487 
3488                 if (f.contains(Flags.ZERO_PAD))
3489                     for (int i = 0; i < width - s.length() - 2; i++)
3490                         sb.append('0');
3491 
3492                 int idx = s.indexOf('p');
3493                 va = s.substring(0, idx).toCharArray();
3494                 if (upper) {
3495                     String tmp = new String(va);
3496                     // don't localize hex
3497                     tmp = tmp.toUpperCase(Locale.US);
3498                     va = tmp.toCharArray();
3499                 }
3500                 sb.append(prec != 0 ? addZeros(va, prec) : va);
3501                 sb.append(upper ? 'P' : 'p');
3502                 sb.append(s.substring(idx+1));
3503             }
3504         }
3505 
3506         // Add zeros to the requested precision.
3507         private char[] addZeros(char[] v, int prec) {
3508             // Look for the dot.  If we don't find one, the we'll need to add
3509             // it before we add the zeros.
3510             int i;
3511             for (i = 0; i < v.length; i++) {
3512                 if (v[i] == '.')
3513                     break;
3514             }
3515             boolean needDot = false;
3516             if (i == v.length) {
3517                 needDot = true;
3518             }
3519 
3520             // Determine existing precision.
3521             int outPrec = v.length - i - (needDot ? 0 : 1);
3522             assert (outPrec <= prec);
3523             if (outPrec == prec)
3524                 return v;
3525 
3526             // Create new array with existing contents.
3527             char[] tmp
3528                 = new char[v.length + prec - outPrec + (needDot ? 1 : 0)];
3529             System.arraycopy(v, 0, tmp, 0, v.length);
3530 
3531             // Add dot if previously determined to be necessary.
3532             int start = v.length;
3533             if (needDot) {
3534                 tmp[v.length] = '.';
3535                 start++;
3536             }
3537 
3538             // Add zeros.
3539             for (int j = start; j < tmp.length; j++)
3540                 tmp[j] = '0';
3541 
3542             return tmp;
3543         }
3544 
3545         // Method assumes that d > 0.
3546         private String hexDouble(double d, int prec) {
3547             // Let Double.toHexString handle simple cases
3548             if(!Double.isFinite(d) || d == 0.0 || prec == 0 || prec >= 13)
3549                 // remove "0x"
3550                 return Double.toHexString(d).substring(2);
3551             else {
3552                 assert(prec >= 1 && prec <= 12);
3553 
3554                 int exponent  = Math.getExponent(d);
3555                 boolean subnormal
3556                     = (exponent == DoubleConsts.MIN_EXPONENT - 1);
3557 
3558                 // If this is subnormal input so normalize (could be faster to
3559                 // do as integer operation).
3560                 if (subnormal) {
3561                     scaleUp = Math.scalb(1.0, 54);
3562                     d *= scaleUp;
3563                     // Calculate the exponent.  This is not just exponent + 54
3564                     // since the former is not the normalized exponent.
3565                     exponent = Math.getExponent(d);
3566                     assert exponent >= DoubleConsts.MIN_EXPONENT &&
3567                         exponent <= DoubleConsts.MAX_EXPONENT: exponent;
3568                 }
3569 
3570                 int precision = 1 + prec*4;
3571                 int shiftDistance
3572                     =  DoubleConsts.SIGNIFICAND_WIDTH - precision;
3573                 assert(shiftDistance >= 1 && shiftDistance < DoubleConsts.SIGNIFICAND_WIDTH);
3574 
3575                 long doppel = Double.doubleToLongBits(d);
3576                 // Deterime the number of bits to keep.
3577                 long newSignif
3578                     = (doppel & (DoubleConsts.EXP_BIT_MASK
3579                                  | DoubleConsts.SIGNIF_BIT_MASK))
3580                                      >> shiftDistance;
3581                 // Bits to round away.
3582                 long roundingBits = doppel & ~(~0L << shiftDistance);
3583 
3584                 // To decide how to round, look at the low-order bit of the
3585                 // working significand, the highest order discarded bit (the
3586                 // round bit) and whether any of the lower order discarded bits
3587                 // are nonzero (the sticky bit).
3588 
3589                 boolean leastZero = (newSignif & 0x1L) == 0L;
3590                 boolean round
3591                     = ((1L << (shiftDistance - 1) ) & roundingBits) != 0L;
3592                 boolean sticky  = shiftDistance > 1 &&
3593                     (~(1L<< (shiftDistance - 1)) & roundingBits) != 0;
3594                 if((leastZero && round && sticky) || (!leastZero && round)) {
3595                     newSignif++;
3596                 }
3597 
3598                 long signBit = doppel & DoubleConsts.SIGN_BIT_MASK;
3599                 newSignif = signBit | (newSignif << shiftDistance);
3600                 double result = Double.longBitsToDouble(newSignif);
3601 
3602                 if (Double.isInfinite(result) ) {
3603                     // Infinite result generated by rounding
3604                     return "1.0p1024";
3605                 } else {
3606                     String res = Double.toHexString(result).substring(2);
3607                     if (!subnormal)
3608                         return res;
3609                     else {
3610                         // Create a normalized subnormal string.
3611                         int idx = res.indexOf('p');
3612                         if (idx == -1) {
3613                             // No 'p' character in hex string.
3614                             assert false;
3615                             return null;
3616                         } else {
3617                             // Get exponent and append at the end.
3618                             String exp = res.substring(idx + 1);
3619                             int iexp = Integer.parseInt(exp) -54;
3620                             return res.substring(0, idx) + "p"
3621                                 + Integer.toString(iexp);
3622                         }
3623                     }
3624                 }
3625             }
3626         }
3627 
3628         private void print(BigDecimal value, Locale l) throws IOException {
3629             if (c == Conversion.HEXADECIMAL_FLOAT)
3630                 failConversion(c, value);
3631             StringBuilder sb = new StringBuilder();
3632             boolean neg = value.signum() == -1;
3633             BigDecimal v = value.abs();
3634             // leading sign indicator
3635             leadingSign(sb, neg);
3636 
3637             // the value
3638             print(sb, v, l, f, c, precision, neg);
3639 
3640             // trailing sign indicator
3641             trailingSign(sb, neg);
3642 
3643             // justify based on width
3644             a.append(justify(sb.toString()));
3645         }
3646 
3647         // value > 0
3648         private void print(StringBuilder sb, BigDecimal value, Locale l,
3649                            Flags f, char c, int precision, boolean neg)
3650             throws IOException
3651         {
3652             if (c == Conversion.SCIENTIFIC) {
3653                 // Create a new BigDecimal with the desired precision.
3654                 int prec = (precision == -1 ? 6 : precision);
3655                 int scale = value.scale();
3656                 int origPrec = value.precision();
3657                 int nzeros = 0;
3658                 int compPrec;
3659 
3660                 if (prec > origPrec - 1) {
3661                     compPrec = origPrec;
3662                     nzeros = prec - (origPrec - 1);
3663                 } else {
3664                     compPrec = prec + 1;
3665                 }
3666 
3667                 MathContext mc = new MathContext(compPrec);
3668                 BigDecimal v
3669                     = new BigDecimal(value.unscaledValue(), scale, mc);
3670 
3671                 BigDecimalLayout bdl
3672                     = new BigDecimalLayout(v.unscaledValue(), v.scale(),
3673                                            BigDecimalLayoutForm.SCIENTIFIC);
3674 
3675                 char[] mant = bdl.mantissa();
3676 
3677                 // Add a decimal point if necessary.  The mantissa may not
3678                 // contain a decimal point if the scale is zero (the internal
3679                 // representation has no fractional part) or the original
3680                 // precision is one. Append a decimal point if '#' is set or if
3681                 // we require zero padding to get to the requested precision.
3682                 if ((origPrec == 1 || !bdl.hasDot())
3683                     && (nzeros > 0 || (f.contains(Flags.ALTERNATE))))
3684                     mant = addDot(mant);
3685 
3686                 // Add trailing zeros in the case precision is greater than
3687                 // the number of available digits after the decimal separator.
3688                 mant = trailingZeros(mant, nzeros);
3689 
3690                 char[] exp = bdl.exponent();
3691                 int newW = width;
3692                 if (width != -1)
3693                     newW = adjustWidth(width - exp.length - 1, f, neg);
3694                 localizedMagnitude(sb, mant, f, newW, l);
3695 
3696                 sb.append(f.contains(Flags.UPPERCASE) ? 'E' : 'e');
3697 
3698                 Flags flags = f.dup().remove(Flags.GROUP);
3699                 char sign = exp[0];
3700                 assert(sign == '+' || sign == '-');
3701                 sb.append(exp[0]);
3702 
3703                 char[] tmp = new char[exp.length - 1];
3704                 System.arraycopy(exp, 1, tmp, 0, exp.length - 1);
3705                 sb.append(localizedMagnitude(null, tmp, flags, -1, l));
3706             } else if (c == Conversion.DECIMAL_FLOAT) {
3707                 // Create a new BigDecimal with the desired precision.
3708                 int prec = (precision == -1 ? 6 : precision);
3709                 int scale = value.scale();
3710 
3711                 if (scale > prec) {
3712                     // more "scale" digits than the requested "precision"
3713                     int compPrec = value.precision();
3714                     if (compPrec <= scale) {
3715                         // case of 0.xxxxxx
3716                         value = value.setScale(prec, RoundingMode.HALF_UP);
3717                     } else {
3718                         compPrec -= (scale - prec);
3719                         value = new BigDecimal(value.unscaledValue(),
3720                                                scale,
3721                                                new MathContext(compPrec));
3722                     }
3723                 }
3724                 BigDecimalLayout bdl = new BigDecimalLayout(
3725                                            value.unscaledValue(),
3726                                            value.scale(),
3727                                            BigDecimalLayoutForm.DECIMAL_FLOAT);
3728 
3729                 char mant[] = bdl.mantissa();
3730                 int nzeros = (bdl.scale() < prec ? prec - bdl.scale() : 0);
3731 
3732                 // Add a decimal point if necessary.  The mantissa may not
3733                 // contain a decimal point if the scale is zero (the internal
3734                 // representation has no fractional part).  Append a decimal
3735                 // point if '#' is set or we require zero padding to get to the
3736                 // requested precision.
3737                 if (bdl.scale() == 0 && (f.contains(Flags.ALTERNATE) || nzeros > 0))
3738                     mant = addDot(bdl.mantissa());
3739 
3740                 // Add trailing zeros if the precision is greater than the
3741                 // number of available digits after the decimal separator.
3742                 mant = trailingZeros(mant, nzeros);
3743 
3744                 localizedMagnitude(sb, mant, f, adjustWidth(width, f, neg), l);
3745             } else if (c == Conversion.GENERAL) {
3746                 int prec = precision;
3747                 if (precision == -1)
3748                     prec = 6;
3749                 else if (precision == 0)
3750                     prec = 1;
3751 
3752                 BigDecimal tenToTheNegFour = BigDecimal.valueOf(1, 4);
3753                 BigDecimal tenToThePrec = BigDecimal.valueOf(1, -prec);
3754                 if ((value.equals(BigDecimal.ZERO))
3755                     || ((value.compareTo(tenToTheNegFour) != -1)
3756                         && (value.compareTo(tenToThePrec) == -1))) {
3757 
3758                     int e = - value.scale()
3759                         + (value.unscaledValue().toString().length() - 1);
3760 
3761                     // xxx.yyy
3762                     //   g precision (# sig digits) = #x + #y
3763                     //   f precision = #y
3764                     //   exponent = #x - 1
3765                     // => f precision = g precision - exponent - 1
3766                     // 0.000zzz
3767                     //   g precision (# sig digits) = #z
3768                     //   f precision = #0 (after '.') + #z
3769                     //   exponent = - #0 (after '.') - 1
3770                     // => f precision = g precision - exponent - 1
3771                     prec = prec - e - 1;
3772 
3773                     print(sb, value, l, f, Conversion.DECIMAL_FLOAT, prec,
3774                           neg);
3775                 } else {
3776                     print(sb, value, l, f, Conversion.SCIENTIFIC, prec - 1, neg);
3777                 }
3778             } else if (c == Conversion.HEXADECIMAL_FLOAT) {
3779                 // This conversion isn't supported.  The error should be
3780                 // reported earlier.
3781                 assert false;
3782             }
3783         }
3784 
3785         private class BigDecimalLayout {
3786             private StringBuilder mant;
3787             private StringBuilder exp;
3788             private boolean dot = false;
3789             private int scale;
3790 
3791             public BigDecimalLayout(BigInteger intVal, int scale, BigDecimalLayoutForm form) {
3792                 layout(intVal, scale, form);
3793             }
3794 
3795             public boolean hasDot() {
3796                 return dot;
3797             }
3798 
3799             public int scale() {
3800                 return scale;
3801             }
3802 
3803             // char[] with canonical string representation
3804             public char[] layoutChars() {
3805                 StringBuilder sb = new StringBuilder(mant);
3806                 if (exp != null) {
3807                     sb.append('E');
3808                     sb.append(exp);
3809                 }
3810                 return toCharArray(sb);
3811             }
3812 
3813             public char[] mantissa() {
3814                 return toCharArray(mant);
3815             }
3816 
3817             // The exponent will be formatted as a sign ('+' or '-') followed
3818             // by the exponent zero-padded to include at least two digits.
3819             public char[] exponent() {
3820                 return toCharArray(exp);
3821             }
3822 
3823             private char[] toCharArray(StringBuilder sb) {
3824                 if (sb == null)
3825                     return null;
3826                 char[] result = new char[sb.length()];
3827                 sb.getChars(0, result.length, result, 0);
3828                 return result;
3829             }
3830 
3831             private void layout(BigInteger intVal, int scale, BigDecimalLayoutForm form) {
3832                 char coeff[] = intVal.toString().toCharArray();
3833                 this.scale = scale;
3834 
3835                 // Construct a buffer, with sufficient capacity for all cases.
3836                 // If E-notation is needed, length will be: +1 if negative, +1
3837                 // if '.' needed, +2 for "E+", + up to 10 for adjusted
3838                 // exponent.  Otherwise it could have +1 if negative, plus
3839                 // leading "0.00000"
3840                 mant = new StringBuilder(coeff.length + 14);
3841 
3842                 if (scale == 0) {
3843                     int len = coeff.length;
3844                     if (len > 1) {
3845                         mant.append(coeff[0]);
3846                         if (form == BigDecimalLayoutForm.SCIENTIFIC) {
3847                             mant.append('.');
3848                             dot = true;
3849                             mant.append(coeff, 1, len - 1);
3850                             exp = new StringBuilder("+");
3851                             if (len < 10)
3852                                 exp.append("0").append(len - 1);
3853                             else
3854                                 exp.append(len - 1);
3855                         } else {
3856                             mant.append(coeff, 1, len - 1);
3857                         }
3858                     } else {
3859                         mant.append(coeff);
3860                         if (form == BigDecimalLayoutForm.SCIENTIFIC)
3861                             exp = new StringBuilder("+00");
3862                     }
3863                     return;
3864                 }
3865                 long adjusted = -(long) scale + (coeff.length - 1);
3866                 if (form == BigDecimalLayoutForm.DECIMAL_FLOAT) {
3867                     // count of padding zeros
3868                     int pad = scale - coeff.length;
3869                     if (pad >= 0) {
3870                         // 0.xxx form
3871                         mant.append("0.");
3872                         dot = true;
3873                         for (; pad > 0 ; pad--) mant.append('0');
3874                         mant.append(coeff);
3875                     } else {
3876                         if (-pad < coeff.length) {
3877                             // xx.xx form
3878                             mant.append(coeff, 0, -pad);
3879                             mant.append('.');
3880                             dot = true;
3881                             mant.append(coeff, -pad, scale);
3882                         } else {
3883                             // xx form
3884                             mant.append(coeff, 0, coeff.length);
3885                             for (int i = 0; i < -scale; i++)
3886                                 mant.append('0');
3887                             this.scale = 0;
3888                         }
3889                     }
3890                 } else {
3891                     // x.xxx form
3892                     mant.append(coeff[0]);
3893                     if (coeff.length > 1) {
3894                         mant.append('.');
3895                         dot = true;
3896                         mant.append(coeff, 1, coeff.length-1);
3897                     }
3898                     exp = new StringBuilder();
3899                     if (adjusted != 0) {
3900                         long abs = Math.abs(adjusted);
3901                         // require sign
3902                         exp.append(adjusted < 0 ? '-' : '+');
3903                         if (abs < 10)
3904                             exp.append('0');
3905                         exp.append(abs);
3906                     } else {
3907                         exp.append("+00");
3908                     }
3909                 }
3910             }
3911         }
3912 
3913         private int adjustWidth(int width, Flags f, boolean neg) {
3914             int newW = width;
3915             if (newW != -1 && neg && f.contains(Flags.PARENTHESES))
3916                 newW--;
3917             return newW;
3918         }
3919 
3920         // Add a '.' to th mantissa if required
3921         private char[] addDot(char[] mant) {
3922             char[] tmp = mant;
3923             tmp = new char[mant.length + 1];
3924             System.arraycopy(mant, 0, tmp, 0, mant.length);
3925             tmp[tmp.length - 1] = '.';
3926             return tmp;
3927         }
3928 
3929         // Add trailing zeros in the case precision is greater than the number
3930         // of available digits after the decimal separator.
3931         private char[] trailingZeros(char[] mant, int nzeros) {
3932             char[] tmp = mant;
3933             if (nzeros > 0) {
3934                 tmp = new char[mant.length + nzeros];
3935                 System.arraycopy(mant, 0, tmp, 0, mant.length);
3936                 for (int i = mant.length; i < tmp.length; i++)
3937                     tmp[i] = '0';
3938             }
3939             return tmp;
3940         }
3941 
3942         private void print(Calendar t, char c, Locale l)  throws IOException
3943         {
3944             StringBuilder sb = new StringBuilder();
3945             print(sb, t, c, l);
3946 
3947             // justify based on width
3948             String s = justify(sb.toString());
3949             if (f.contains(Flags.UPPERCASE))
3950                 s = s.toUpperCase();
3951 
3952             a.append(s);
3953         }
3954 
3955         private Appendable print(StringBuilder sb, Calendar t, char c,
3956                                  Locale l)
3957             throws IOException
3958         {
3959             if (sb == null)
3960                 sb = new StringBuilder();
3961             switch (c) {
3962             case DateTime.HOUR_OF_DAY_0: // 'H' (00 - 23)
3963             case DateTime.HOUR_0:        // 'I' (01 - 12)
3964             case DateTime.HOUR_OF_DAY:   // 'k' (0 - 23) -- like H
3965             case DateTime.HOUR:        { // 'l' (1 - 12) -- like I
3966                 int i = t.get(Calendar.HOUR_OF_DAY);
3967                 if (c == DateTime.HOUR_0 || c == DateTime.HOUR)
3968                     i = (i == 0 || i == 12 ? 12 : i % 12);
3969                 Flags flags = (c == DateTime.HOUR_OF_DAY_0
3970                                || c == DateTime.HOUR_0
3971                                ? Flags.ZERO_PAD
3972                                : Flags.NONE);
3973                 sb.append(localizedMagnitude(null, i, flags, 2, l));
3974                 break;
3975             }
3976             case DateTime.MINUTE:      { // 'M' (00 - 59)
3977                 int i = t.get(Calendar.MINUTE);
3978                 Flags flags = Flags.ZERO_PAD;
3979                 sb.append(localizedMagnitude(null, i, flags, 2, l));
3980                 break;
3981             }
3982             case DateTime.NANOSECOND:  { // 'N' (000000000 - 999999999)
3983                 int i = t.get(Calendar.MILLISECOND) * 1000000;
3984                 Flags flags = Flags.ZERO_PAD;
3985                 sb.append(localizedMagnitude(null, i, flags, 9, l));
3986                 break;
3987             }
3988             case DateTime.MILLISECOND: { // 'L' (000 - 999)
3989                 int i = t.get(Calendar.MILLISECOND);
3990                 Flags flags = Flags.ZERO_PAD;
3991                 sb.append(localizedMagnitude(null, i, flags, 3, l));
3992                 break;
3993             }
3994             case DateTime.MILLISECOND_SINCE_EPOCH: { // 'Q' (0 - 99...?)
3995                 long i = t.getTimeInMillis();
3996                 Flags flags = Flags.NONE;
3997                 sb.append(localizedMagnitude(null, i, flags, width, l));
3998                 break;
3999             }
4000             case DateTime.AM_PM:       { // 'p' (am or pm)
4001                 // Calendar.AM = 0, Calendar.PM = 1, LocaleElements defines upper
4002                 String[] ampm = { "AM", "PM" };
4003                 if (l != null && l != Locale.US) {
4004                     DateFormatSymbols dfs = DateFormatSymbols.getInstance(l);
4005                     ampm = dfs.getAmPmStrings();
4006                 }
4007                 String s = ampm[t.get(Calendar.AM_PM)];
4008                 sb.append(s.toLowerCase(l != null ? l : Locale.US));
4009                 break;
4010             }
4011             case DateTime.SECONDS_SINCE_EPOCH: { // 's' (0 - 99...?)
4012                 long i = t.getTimeInMillis() / 1000;
4013                 Flags flags = Flags.NONE;
4014                 sb.append(localizedMagnitude(null, i, flags, width, l));
4015                 break;
4016             }
4017             case DateTime.SECOND:      { // 'S' (00 - 60 - leap second)
4018                 int i = t.get(Calendar.SECOND);
4019                 Flags flags = Flags.ZERO_PAD;
4020                 sb.append(localizedMagnitude(null, i, flags, 2, l));
4021                 break;
4022             }
4023             case DateTime.ZONE_NUMERIC: { // 'z' ({-|+}####) - ls minus?
4024                 int i = t.get(Calendar.ZONE_OFFSET) + t.get(Calendar.DST_OFFSET);
4025                 boolean neg = i < 0;
4026                 sb.append(neg ? '-' : '+');
4027                 if (neg)
4028                     i = -i;
4029                 int min = i / 60000;
4030                 // combine minute and hour into a single integer
4031                 int offset = (min / 60) * 100 + (min % 60);
4032                 Flags flags = Flags.ZERO_PAD;
4033 
4034                 sb.append(localizedMagnitude(null, offset, flags, 4, l));
4035                 break;
4036             }
4037             case DateTime.ZONE:        { // 'Z' (symbol)
4038                 TimeZone tz = t.getTimeZone();
4039                 sb.append(tz.getDisplayName((t.get(Calendar.DST_OFFSET) != 0),
4040                                            TimeZone.SHORT,
4041                                             (l == null) ? Locale.US : l));
4042                 break;
4043             }
4044 
4045             // Date
4046             case DateTime.NAME_OF_DAY_ABBREV:     // 'a'
4047             case DateTime.NAME_OF_DAY:          { // 'A'
4048                 int i = t.get(Calendar.DAY_OF_WEEK);
4049                 Locale lt = ((l == null) ? Locale.US : l);
4050                 DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt);
4051                 if (c == DateTime.NAME_OF_DAY)
4052                     sb.append(dfs.getWeekdays()[i]);
4053                 else
4054                     sb.append(dfs.getShortWeekdays()[i]);
4055                 break;
4056             }
4057             case DateTime.NAME_OF_MONTH_ABBREV:   // 'b'
4058             case DateTime.NAME_OF_MONTH_ABBREV_X: // 'h' -- same b
4059             case DateTime.NAME_OF_MONTH:        { // 'B'
4060                 int i = t.get(Calendar.MONTH);
4061                 Locale lt = ((l == null) ? Locale.US : l);
4062                 DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt);
4063                 if (c == DateTime.NAME_OF_MONTH)
4064                     sb.append(dfs.getMonths()[i]);
4065                 else
4066                     sb.append(dfs.getShortMonths()[i]);
4067                 break;
4068             }
4069             case DateTime.CENTURY:                // 'C' (00 - 99)
4070             case DateTime.YEAR_2:                 // 'y' (00 - 99)
4071             case DateTime.YEAR_4:               { // 'Y' (0000 - 9999)
4072                 int i = t.get(Calendar.YEAR);
4073                 int size = 2;
4074                 switch (c) {
4075                 case DateTime.CENTURY:
4076                     i /= 100;
4077                     break;
4078                 case DateTime.YEAR_2:
4079                     i %= 100;
4080                     break;
4081                 case DateTime.YEAR_4:
4082                     size = 4;
4083                     break;
4084                 }
4085                 Flags flags = Flags.ZERO_PAD;
4086                 sb.append(localizedMagnitude(null, i, flags, size, l));
4087                 break;
4088             }
4089             case DateTime.DAY_OF_MONTH_0:         // 'd' (01 - 31)
4090             case DateTime.DAY_OF_MONTH:         { // 'e' (1 - 31) -- like d
4091                 int i = t.get(Calendar.DATE);
4092                 Flags flags = (c == DateTime.DAY_OF_MONTH_0
4093                                ? Flags.ZERO_PAD
4094                                : Flags.NONE);
4095                 sb.append(localizedMagnitude(null, i, flags, 2, l));
4096                 break;
4097             }
4098             case DateTime.DAY_OF_YEAR:          { // 'j' (001 - 366)
4099                 int i = t.get(Calendar.DAY_OF_YEAR);
4100                 Flags flags = Flags.ZERO_PAD;
4101                 sb.append(localizedMagnitude(null, i, flags, 3, l));
4102                 break;
4103             }
4104             case DateTime.MONTH:                { // 'm' (01 - 12)
4105                 int i = t.get(Calendar.MONTH) + 1;
4106                 Flags flags = Flags.ZERO_PAD;
4107                 sb.append(localizedMagnitude(null, i, flags, 2, l));
4108                 break;
4109             }
4110 
4111             // Composites
4112             case DateTime.TIME:         // 'T' (24 hour hh:mm:ss - %tH:%tM:%tS)
4113             case DateTime.TIME_24_HOUR:    { // 'R' (hh:mm same as %H:%M)
4114                 char sep = ':';
4115                 print(sb, t, DateTime.HOUR_OF_DAY_0, l).append(sep);
4116                 print(sb, t, DateTime.MINUTE, l);
4117                 if (c == DateTime.TIME) {
4118                     sb.append(sep);
4119                     print(sb, t, DateTime.SECOND, l);
4120                 }
4121                 break;
4122             }
4123             case DateTime.TIME_12_HOUR:    { // 'r' (hh:mm:ss [AP]M)
4124                 char sep = ':';
4125                 print(sb, t, DateTime.HOUR_0, l).append(sep);
4126                 print(sb, t, DateTime.MINUTE, l).append(sep);
4127                 print(sb, t, DateTime.SECOND, l).append(' ');
4128                 // this may be in wrong place for some locales
4129                 StringBuilder tsb = new StringBuilder();
4130                 print(tsb, t, DateTime.AM_PM, l);
4131                 sb.append(tsb.toString().toUpperCase(l != null ? l : Locale.US));
4132                 break;
4133             }
4134             case DateTime.DATE_TIME:    { // 'c' (Sat Nov 04 12:02:33 EST 1999)
4135                 char sep = ' ';
4136                 print(sb, t, DateTime.NAME_OF_DAY_ABBREV, l).append(sep);
4137                 print(sb, t, DateTime.NAME_OF_MONTH_ABBREV, l).append(sep);
4138                 print(sb, t, DateTime.DAY_OF_MONTH_0, l).append(sep);
4139                 print(sb, t, DateTime.TIME, l).append(sep);
4140                 print(sb, t, DateTime.ZONE, l).append(sep);
4141                 print(sb, t, DateTime.YEAR_4, l);
4142                 break;
4143             }
4144             case DateTime.DATE:            { // 'D' (mm/dd/yy)
4145                 char sep = '/';
4146                 print(sb, t, DateTime.MONTH, l).append(sep);
4147                 print(sb, t, DateTime.DAY_OF_MONTH_0, l).append(sep);
4148                 print(sb, t, DateTime.YEAR_2, l);
4149                 break;
4150             }
4151             case DateTime.ISO_STANDARD_DATE: { // 'F' (%Y-%m-%d)
4152                 char sep = '-';
4153                 print(sb, t, DateTime.YEAR_4, l).append(sep);
4154                 print(sb, t, DateTime.MONTH, l).append(sep);
4155                 print(sb, t, DateTime.DAY_OF_MONTH_0, l);
4156                 break;
4157             }
4158             default:
4159                 assert false;
4160             }
4161             return sb;
4162         }
4163 
4164         private void print(TemporalAccessor t, char c, Locale l)  throws IOException {
4165             StringBuilder sb = new StringBuilder();
4166             print(sb, t, c, l);
4167             // justify based on width
4168             String s = justify(sb.toString());
4169             if (f.contains(Flags.UPPERCASE))
4170                 s = s.toUpperCase();
4171             a.append(s);
4172         }
4173 
4174         private Appendable print(StringBuilder sb, TemporalAccessor t, char c,
4175                                  Locale l) throws IOException {
4176             if (sb == null)
4177                 sb = new StringBuilder();
4178             try {
4179                 switch (c) {
4180                 case DateTime.HOUR_OF_DAY_0: {  // 'H' (00 - 23)
4181                     int i = t.get(ChronoField.HOUR_OF_DAY);
4182                     sb.append(localizedMagnitude(null, i, Flags.ZERO_PAD, 2, l));
4183                     break;
4184                 }
4185                 case DateTime.HOUR_OF_DAY: {   // 'k' (0 - 23) -- like H
4186                     int i = t.get(ChronoField.HOUR_OF_DAY);
4187                     sb.append(localizedMagnitude(null, i, Flags.NONE, 2, l));
4188                     break;
4189                 }
4190                 case DateTime.HOUR_0:      {  // 'I' (01 - 12)
4191                     int i = t.get(ChronoField.CLOCK_HOUR_OF_AMPM);
4192                     sb.append(localizedMagnitude(null, i, Flags.ZERO_PAD, 2, l));
4193                     break;
4194                 }
4195                 case DateTime.HOUR:        { // 'l' (1 - 12) -- like I
4196                     int i = t.get(ChronoField.CLOCK_HOUR_OF_AMPM);
4197                     sb.append(localizedMagnitude(null, i, Flags.NONE, 2, l));
4198                     break;
4199                 }
4200                 case DateTime.MINUTE:      { // 'M' (00 - 59)
4201                     int i = t.get(ChronoField.MINUTE_OF_HOUR);
4202                     Flags flags = Flags.ZERO_PAD;
4203                     sb.append(localizedMagnitude(null, i, flags, 2, l));
4204                     break;
4205                 }
4206                 case DateTime.NANOSECOND:  { // 'N' (000000000 - 999999999)
4207                     int i = t.get(ChronoField.MILLI_OF_SECOND) * 1000000;
4208                     Flags flags = Flags.ZERO_PAD;
4209                     sb.append(localizedMagnitude(null, i, flags, 9, l));
4210                     break;
4211                 }
4212                 case DateTime.MILLISECOND: { // 'L' (000 - 999)
4213                     int i = t.get(ChronoField.MILLI_OF_SECOND);
4214                     Flags flags = Flags.ZERO_PAD;
4215                     sb.append(localizedMagnitude(null, i, flags, 3, l));
4216                     break;
4217                 }
4218                 case DateTime.MILLISECOND_SINCE_EPOCH: { // 'Q' (0 - 99...?)
4219                     long i = t.getLong(ChronoField.INSTANT_SECONDS) * 1000L +
4220                              t.getLong(ChronoField.MILLI_OF_SECOND);
4221                     Flags flags = Flags.NONE;
4222                     sb.append(localizedMagnitude(null, i, flags, width, l));
4223                     break;
4224                 }
4225                 case DateTime.AM_PM:       { // 'p' (am or pm)
4226                     // Calendar.AM = 0, Calendar.PM = 1, LocaleElements defines upper
4227                     String[] ampm = { "AM", "PM" };
4228                     if (l != null && l != Locale.US) {
4229                         DateFormatSymbols dfs = DateFormatSymbols.getInstance(l);
4230                         ampm = dfs.getAmPmStrings();
4231                     }
4232                     String s = ampm[t.get(ChronoField.AMPM_OF_DAY)];
4233                     sb.append(s.toLowerCase(l != null ? l : Locale.US));
4234                     break;
4235                 }
4236                 case DateTime.SECONDS_SINCE_EPOCH: { // 's' (0 - 99...?)
4237                     long i = t.getLong(ChronoField.INSTANT_SECONDS);
4238                     Flags flags = Flags.NONE;
4239                     sb.append(localizedMagnitude(null, i, flags, width, l));
4240                     break;
4241                 }
4242                 case DateTime.SECOND:      { // 'S' (00 - 60 - leap second)
4243                     int i = t.get(ChronoField.SECOND_OF_MINUTE);
4244                     Flags flags = Flags.ZERO_PAD;
4245                     sb.append(localizedMagnitude(null, i, flags, 2, l));
4246                     break;
4247                 }
4248                 case DateTime.ZONE_NUMERIC: { // 'z' ({-|+}####) - ls minus?
4249                     int i = t.get(ChronoField.OFFSET_SECONDS);
4250                     boolean neg = i < 0;
4251                     sb.append(neg ? '-' : '+');
4252                     if (neg)
4253                         i = -i;
4254                     int min = i / 60;
4255                     // combine minute and hour into a single integer
4256                     int offset = (min / 60) * 100 + (min % 60);
4257                     Flags flags = Flags.ZERO_PAD;
4258                     sb.append(localizedMagnitude(null, offset, flags, 4, l));
4259                     break;
4260                 }
4261                 case DateTime.ZONE:        { // 'Z' (symbol)
4262                     ZoneId zid = t.query(TemporalQueries.zone());
4263                     if (zid == null) {
4264                         throw new IllegalFormatConversionException(c, t.getClass());
4265                     }
4266                     if (!(zid instanceof ZoneOffset) &&
4267                         t.isSupported(ChronoField.INSTANT_SECONDS)) {
4268                         Instant instant = Instant.from(t);
4269                         sb.append(TimeZone.getTimeZone(zid.getId())
4270                                           .getDisplayName(zid.getRules().isDaylightSavings(instant),
4271                                                           TimeZone.SHORT,
4272                                                           (l == null) ? Locale.US : l));
4273                         break;
4274                     }
4275                     sb.append(zid.getId());
4276                     break;
4277                 }
4278                 // Date
4279                 case DateTime.NAME_OF_DAY_ABBREV:     // 'a'
4280                 case DateTime.NAME_OF_DAY:          { // 'A'
4281                     int i = t.get(ChronoField.DAY_OF_WEEK) % 7 + 1;
4282                     Locale lt = ((l == null) ? Locale.US : l);
4283                     DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt);
4284                     if (c == DateTime.NAME_OF_DAY)
4285                         sb.append(dfs.getWeekdays()[i]);
4286                     else
4287                         sb.append(dfs.getShortWeekdays()[i]);
4288                     break;
4289                 }
4290                 case DateTime.NAME_OF_MONTH_ABBREV:   // 'b'
4291                 case DateTime.NAME_OF_MONTH_ABBREV_X: // 'h' -- same b
4292                 case DateTime.NAME_OF_MONTH:        { // 'B'
4293                     int i = t.get(ChronoField.MONTH_OF_YEAR) - 1;
4294                     Locale lt = ((l == null) ? Locale.US : l);
4295                     DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt);
4296                     if (c == DateTime.NAME_OF_MONTH)
4297                         sb.append(dfs.getMonths()[i]);
4298                     else
4299                         sb.append(dfs.getShortMonths()[i]);
4300                     break;
4301                 }
4302                 case DateTime.CENTURY:                // 'C' (00 - 99)
4303                 case DateTime.YEAR_2:                 // 'y' (00 - 99)
4304                 case DateTime.YEAR_4:               { // 'Y' (0000 - 9999)
4305                     int i = t.get(ChronoField.YEAR_OF_ERA);
4306                     int size = 2;
4307                     switch (c) {
4308                     case DateTime.CENTURY:
4309                         i /= 100;
4310                         break;
4311                     case DateTime.YEAR_2:
4312                         i %= 100;
4313                         break;
4314                     case DateTime.YEAR_4:
4315                         size = 4;
4316                         break;
4317                     }
4318                     Flags flags = Flags.ZERO_PAD;
4319                     sb.append(localizedMagnitude(null, i, flags, size, l));
4320                     break;
4321                 }
4322                 case DateTime.DAY_OF_MONTH_0:         // 'd' (01 - 31)
4323                 case DateTime.DAY_OF_MONTH:         { // 'e' (1 - 31) -- like d
4324                     int i = t.get(ChronoField.DAY_OF_MONTH);
4325                     Flags flags = (c == DateTime.DAY_OF_MONTH_0
4326                                    ? Flags.ZERO_PAD
4327                                    : Flags.NONE);
4328                     sb.append(localizedMagnitude(null, i, flags, 2, l));
4329                     break;
4330                 }
4331                 case DateTime.DAY_OF_YEAR:          { // 'j' (001 - 366)
4332                     int i = t.get(ChronoField.DAY_OF_YEAR);
4333                     Flags flags = Flags.ZERO_PAD;
4334                     sb.append(localizedMagnitude(null, i, flags, 3, l));
4335                     break;
4336                 }
4337                 case DateTime.MONTH:                { // 'm' (01 - 12)
4338                     int i = t.get(ChronoField.MONTH_OF_YEAR);
4339                     Flags flags = Flags.ZERO_PAD;
4340                     sb.append(localizedMagnitude(null, i, flags, 2, l));
4341                     break;
4342                 }
4343 
4344                 // Composites
4345                 case DateTime.TIME:         // 'T' (24 hour hh:mm:ss - %tH:%tM:%tS)
4346                 case DateTime.TIME_24_HOUR:    { // 'R' (hh:mm same as %H:%M)
4347                     char sep = ':';
4348                     print(sb, t, DateTime.HOUR_OF_DAY_0, l).append(sep);
4349                     print(sb, t, DateTime.MINUTE, l);
4350                     if (c == DateTime.TIME) {
4351                         sb.append(sep);
4352                         print(sb, t, DateTime.SECOND, l);
4353                     }
4354                     break;
4355                 }
4356                 case DateTime.TIME_12_HOUR:    { // 'r' (hh:mm:ss [AP]M)
4357                     char sep = ':';
4358                     print(sb, t, DateTime.HOUR_0, l).append(sep);
4359                     print(sb, t, DateTime.MINUTE, l).append(sep);
4360                     print(sb, t, DateTime.SECOND, l).append(' ');
4361                     // this may be in wrong place for some locales
4362                     StringBuilder tsb = new StringBuilder();
4363                     print(tsb, t, DateTime.AM_PM, l);
4364                     sb.append(tsb.toString().toUpperCase(l != null ? l : Locale.US));
4365                     break;
4366                 }
4367                 case DateTime.DATE_TIME:    { // 'c' (Sat Nov 04 12:02:33 EST 1999)
4368                     char sep = ' ';
4369                     print(sb, t, DateTime.NAME_OF_DAY_ABBREV, l).append(sep);
4370                     print(sb, t, DateTime.NAME_OF_MONTH_ABBREV, l).append(sep);
4371                     print(sb, t, DateTime.DAY_OF_MONTH_0, l).append(sep);
4372                     print(sb, t, DateTime.TIME, l).append(sep);
4373                     print(sb, t, DateTime.ZONE, l).append(sep);
4374                     print(sb, t, DateTime.YEAR_4, l);
4375                     break;
4376                 }
4377                 case DateTime.DATE:            { // 'D' (mm/dd/yy)
4378                     char sep = '/';
4379                     print(sb, t, DateTime.MONTH, l).append(sep);
4380                     print(sb, t, DateTime.DAY_OF_MONTH_0, l).append(sep);
4381                     print(sb, t, DateTime.YEAR_2, l);
4382                     break;
4383                 }
4384                 case DateTime.ISO_STANDARD_DATE: { // 'F' (%Y-%m-%d)
4385                     char sep = '-';
4386                     print(sb, t, DateTime.YEAR_4, l).append(sep);
4387                     print(sb, t, DateTime.MONTH, l).append(sep);
4388                     print(sb, t, DateTime.DAY_OF_MONTH_0, l);
4389                     break;
4390                 }
4391                 default:
4392                     assert false;
4393                 }
4394             } catch (DateTimeException x) {
4395                 throw new IllegalFormatConversionException(c, t.getClass());
4396             }
4397             return sb;
4398         }
4399 
4400         // -- Methods to support throwing exceptions --
4401 
4402         private void failMismatch(Flags f, char c) {
4403             String fs = f.toString();
4404             throw new FormatFlagsConversionMismatchException(fs, c);
4405         }
4406 
4407         private void failConversion(char c, Object arg) {
4408             throw new IllegalFormatConversionException(c, arg.getClass());
4409         }
4410 
4411         private char getZero(Locale l) {
4412             if ((l != null) &&  !l.equals(locale())) {
4413                 // Android-changed: Improve the performance by 10x http://b/197788756
4414                 // Unclear if this mapping is needed but inherited from DecimalFormatSymbols
4415                 l = LocaleData.mapInvalidAndNullLocales(l);
4416                 DecimalFormatData decimalFormatData = DecimalFormatData.getInstance(l);
4417                 return decimalFormatData.getZeroDigit();
4418                 //  DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(l);
4419                 //  return dfs.getZeroDigit();
4420             }
4421             return zero;
4422         }
4423 
4424         private StringBuilder
4425             localizedMagnitude(StringBuilder sb, long value, Flags f,
4426                                int width, Locale l)
4427         {
4428             char[] va = Long.toString(value, 10).toCharArray();
4429             return localizedMagnitude(sb, va, f, width, l);
4430         }
4431 
4432         private StringBuilder
4433             localizedMagnitude(StringBuilder sb, char[] value, Flags f,
4434                                int width, Locale l)
4435         {
4436             if (sb == null)
4437                 sb = new StringBuilder();
4438             int begin = sb.length();
4439 
4440             char zero = getZero(l);
4441 
4442             // determine localized grouping separator and size
4443             char grpSep = '\0';
4444             int  grpSize = -1;
4445             char decSep = '\0';
4446 
4447             int len = value.length;
4448             int dot = len;
4449             for (int j = 0; j < len; j++) {
4450                 if (value[j] == '.') {
4451                     dot = j;
4452                     break;
4453                 }
4454             }
4455 
4456             if (dot < len) {
4457                 if (l == null || l.equals(Locale.US)) {
4458                     decSep  = '.';
4459                 } else {
4460                     DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(l);
4461                     decSep  = dfs.getDecimalSeparator();
4462                 }
4463             }
4464 
4465             if (f.contains(Flags.GROUP)) {
4466                 if (l == null || l.equals(Locale.US)) {
4467                     grpSep = ',';
4468                     grpSize = 3;
4469                 } else {
4470                     DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(l);
4471                     grpSep = dfs.getGroupingSeparator();
4472                     DecimalFormat df = (DecimalFormat) NumberFormat.getIntegerInstance(l);
4473                     grpSize = df.getGroupingSize();
4474                     // BEGIN Android-changed: Fix division by zero if group separator is not clear.
4475                     // http://b/33245708
4476                     // Some locales have a group separator but also patterns without groups.
4477                     // If we do not clear the group separator in these cases a divide by zero
4478                     // is thrown when determining where to place the separators.
4479                     if (!df.isGroupingUsed() || df.getGroupingSize() == 0) {
4480                         grpSep = '\0';
4481                     }
4482                     // END Android-changed: Fix division by zero if group separator is not clear.
4483                 }
4484             }
4485 
4486             // localize the digits inserting group separators as necessary
4487             for (int j = 0; j < len; j++) {
4488                 if (j == dot) {
4489                     sb.append(decSep);
4490                     // no more group separators after the decimal separator
4491                     grpSep = '\0';
4492                     continue;
4493                 }
4494 
4495                 char c = value[j];
4496                 sb.append((char) ((c - '0') + zero));
4497                 if (grpSep != '\0' && j != dot - 1 && ((dot - j) % grpSize == 1))
4498                     sb.append(grpSep);
4499             }
4500 
4501             // apply zero padding
4502             len = sb.length();
4503             if (width != -1 && f.contains(Flags.ZERO_PAD))
4504                 for (int k = 0; k < width - len; k++)
4505                     sb.insert(begin, zero);
4506 
4507             return sb;
4508         }
4509     }
4510 
4511     private static class Flags {
4512         private int flags;
4513 
4514         static final Flags NONE          = new Flags(0);      // ''
4515 
4516         // duplicate declarations from Formattable.java
4517         static final Flags LEFT_JUSTIFY  = new Flags(1<<0);   // '-'
4518         static final Flags UPPERCASE     = new Flags(1<<1);   // '^'
4519         static final Flags ALTERNATE     = new Flags(1<<2);   // '#'
4520 
4521         // numerics
4522         static final Flags PLUS          = new Flags(1<<3);   // '+'
4523         static final Flags LEADING_SPACE = new Flags(1<<4);   // ' '
4524         static final Flags ZERO_PAD      = new Flags(1<<5);   // '0'
4525         static final Flags GROUP         = new Flags(1<<6);   // ','
4526         static final Flags PARENTHESES   = new Flags(1<<7);   // '('
4527 
4528         // indexing
4529         static final Flags PREVIOUS      = new Flags(1<<8);   // '<'
4530 
4531         private Flags(int f) {
4532             flags = f;
4533         }
4534 
4535         public int valueOf() {
4536             return flags;
4537         }
4538 
4539         public boolean contains(Flags f) {
4540             return (flags & f.valueOf()) == f.valueOf();
4541         }
4542 
4543         public Flags dup() {
4544             return new Flags(flags);
4545         }
4546 
4547         private Flags add(Flags f) {
4548             flags |= f.valueOf();
4549             return this;
4550         }
4551 
4552         public Flags remove(Flags f) {
4553             flags &= ~f.valueOf();
4554             return this;
4555         }
4556 
4557         public static Flags parse(String s) {
4558             char[] ca = s.toCharArray();
4559             Flags f = new Flags(0);
4560             for (int i = 0; i < ca.length; i++) {
4561                 Flags v = parse(ca[i]);
4562                 if (f.contains(v))
4563                     throw new DuplicateFormatFlagsException(v.toString());
4564                 f.add(v);
4565             }
4566             return f;
4567         }
4568 
4569         // parse those flags which may be provided by users
4570         private static Flags parse(char c) {
4571             switch (c) {
4572             case '-': return LEFT_JUSTIFY;
4573             case '#': return ALTERNATE;
4574             case '+': return PLUS;
4575             case ' ': return LEADING_SPACE;
4576             case '0': return ZERO_PAD;
4577             case ',': return GROUP;
4578             case '(': return PARENTHESES;
4579             case '<': return PREVIOUS;
4580             default:
4581                 throw new UnknownFormatFlagsException(String.valueOf(c));
4582             }
4583         }
4584 
4585         // Returns a string representation of the current {@code Flags}.
4586         public static String toString(Flags f) {
4587             return f.toString();
4588         }
4589 
4590         public String toString() {
4591             StringBuilder sb = new StringBuilder();
4592             if (contains(LEFT_JUSTIFY))  sb.append('-');
4593             if (contains(UPPERCASE))     sb.append('^');
4594             if (contains(ALTERNATE))     sb.append('#');
4595             if (contains(PLUS))          sb.append('+');
4596             if (contains(LEADING_SPACE)) sb.append(' ');
4597             if (contains(ZERO_PAD))      sb.append('0');
4598             if (contains(GROUP))         sb.append(',');
4599             if (contains(PARENTHESES))   sb.append('(');
4600             if (contains(PREVIOUS))      sb.append('<');
4601             return sb.toString();
4602         }
4603     }
4604 
4605     private static class Conversion {
4606         // Byte, Short, Integer, Long, BigInteger
4607         // (and associated primitives due to autoboxing)
4608         static final char DECIMAL_INTEGER     = 'd';
4609         static final char OCTAL_INTEGER       = 'o';
4610         static final char HEXADECIMAL_INTEGER = 'x';
4611         static final char HEXADECIMAL_INTEGER_UPPER = 'X';
4612 
4613         // Float, Double, BigDecimal
4614         // (and associated primitives due to autoboxing)
4615         static final char SCIENTIFIC          = 'e';
4616         static final char SCIENTIFIC_UPPER    = 'E';
4617         static final char GENERAL             = 'g';
4618         static final char GENERAL_UPPER       = 'G';
4619         static final char DECIMAL_FLOAT       = 'f';
4620         static final char HEXADECIMAL_FLOAT   = 'a';
4621         static final char HEXADECIMAL_FLOAT_UPPER = 'A';
4622 
4623         // Character, Byte, Short, Integer
4624         // (and associated primitives due to autoboxing)
4625         static final char CHARACTER           = 'c';
4626         static final char CHARACTER_UPPER     = 'C';
4627 
4628         // java.util.Date, java.util.Calendar, long
4629         static final char DATE_TIME           = 't';
4630         static final char DATE_TIME_UPPER     = 'T';
4631 
4632         // if (arg.TYPE != boolean) return boolean
4633         // if (arg != null) return true; else return false;
4634         static final char BOOLEAN             = 'b';
4635         static final char BOOLEAN_UPPER       = 'B';
4636         // if (arg instanceof Formattable) arg.formatTo()
4637         // else arg.toString();
4638         static final char STRING              = 's';
4639         static final char STRING_UPPER        = 'S';
4640         // arg.hashCode()
4641         static final char HASHCODE            = 'h';
4642         static final char HASHCODE_UPPER      = 'H';
4643 
4644         static final char LINE_SEPARATOR      = 'n';
4645         static final char PERCENT_SIGN        = '%';
4646 
4647         static boolean isValid(char c) {
4648             return (isGeneral(c) || isInteger(c) || isFloat(c) || isText(c)
4649                     || c == 't' || isCharacter(c));
4650         }
4651 
4652         // Returns true iff the Conversion is applicable to all objects.
4653         static boolean isGeneral(char c) {
4654             switch (c) {
4655             case BOOLEAN:
4656             case BOOLEAN_UPPER:
4657             case STRING:
4658             case STRING_UPPER:
4659             case HASHCODE:
4660             case HASHCODE_UPPER:
4661                 return true;
4662             default:
4663                 return false;
4664             }
4665         }
4666 
4667         // Returns true iff the Conversion is applicable to character.
4668         static boolean isCharacter(char c) {
4669             switch (c) {
4670             case CHARACTER:
4671             case CHARACTER_UPPER:
4672                 return true;
4673             default:
4674                 return false;
4675             }
4676         }
4677 
4678         // Returns true iff the Conversion is an integer type.
4679         static boolean isInteger(char c) {
4680             switch (c) {
4681             case DECIMAL_INTEGER:
4682             case OCTAL_INTEGER:
4683             case HEXADECIMAL_INTEGER:
4684             case HEXADECIMAL_INTEGER_UPPER:
4685                 return true;
4686             default:
4687                 return false;
4688             }
4689         }
4690 
4691         // Returns true iff the Conversion is a floating-point type.
4692         static boolean isFloat(char c) {
4693             switch (c) {
4694             case SCIENTIFIC:
4695             case SCIENTIFIC_UPPER:
4696             case GENERAL:
4697             case GENERAL_UPPER:
4698             case DECIMAL_FLOAT:
4699             case HEXADECIMAL_FLOAT:
4700             case HEXADECIMAL_FLOAT_UPPER:
4701                 return true;
4702             default:
4703                 return false;
4704             }
4705         }
4706 
4707         // Returns true iff the Conversion does not require an argument
4708         static boolean isText(char c) {
4709             switch (c) {
4710             case LINE_SEPARATOR:
4711             case PERCENT_SIGN:
4712                 return true;
4713             default:
4714                 return false;
4715             }
4716         }
4717     }
4718 
4719     private static class DateTime {
4720         static final char HOUR_OF_DAY_0 = 'H'; // (00 - 23)
4721         static final char HOUR_0        = 'I'; // (01 - 12)
4722         static final char HOUR_OF_DAY   = 'k'; // (0 - 23) -- like H
4723         static final char HOUR          = 'l'; // (1 - 12) -- like I
4724         static final char MINUTE        = 'M'; // (00 - 59)
4725         static final char NANOSECOND    = 'N'; // (000000000 - 999999999)
4726         static final char MILLISECOND   = 'L'; // jdk, not in gnu (000 - 999)
4727         static final char MILLISECOND_SINCE_EPOCH = 'Q'; // (0 - 99...?)
4728         static final char AM_PM         = 'p'; // (am or pm)
4729         static final char SECONDS_SINCE_EPOCH = 's'; // (0 - 99...?)
4730         static final char SECOND        = 'S'; // (00 - 60 - leap second)
4731         static final char TIME          = 'T'; // (24 hour hh:mm:ss)
4732         static final char ZONE_NUMERIC  = 'z'; // (-1200 - +1200) - ls minus?
4733         static final char ZONE          = 'Z'; // (symbol)
4734 
4735         // Date
4736         static final char NAME_OF_DAY_ABBREV    = 'a'; // 'a'
4737         static final char NAME_OF_DAY           = 'A'; // 'A'
4738         static final char NAME_OF_MONTH_ABBREV  = 'b'; // 'b'
4739         static final char NAME_OF_MONTH         = 'B'; // 'B'
4740         static final char CENTURY               = 'C'; // (00 - 99)
4741         static final char DAY_OF_MONTH_0        = 'd'; // (01 - 31)
4742         static final char DAY_OF_MONTH          = 'e'; // (1 - 31) -- like d
4743 // *    static final char ISO_WEEK_OF_YEAR_2    = 'g'; // cross %y %V
4744 // *    static final char ISO_WEEK_OF_YEAR_4    = 'G'; // cross %Y %V
4745         static final char NAME_OF_MONTH_ABBREV_X  = 'h'; // -- same b
4746         static final char DAY_OF_YEAR           = 'j'; // (001 - 366)
4747         static final char MONTH                 = 'm'; // (01 - 12)
4748 // *    static final char DAY_OF_WEEK_1         = 'u'; // (1 - 7) Monday
4749 // *    static final char WEEK_OF_YEAR_SUNDAY   = 'U'; // (0 - 53) Sunday+
4750 // *    static final char WEEK_OF_YEAR_MONDAY_01 = 'V'; // (01 - 53) Monday+
4751 // *    static final char DAY_OF_WEEK_0         = 'w'; // (0 - 6) Sunday
4752 // *    static final char WEEK_OF_YEAR_MONDAY   = 'W'; // (00 - 53) Monday
4753         static final char YEAR_2                = 'y'; // (00 - 99)
4754         static final char YEAR_4                = 'Y'; // (0000 - 9999)
4755 
4756         // Composites
4757         static final char TIME_12_HOUR  = 'r'; // (hh:mm:ss [AP]M)
4758         static final char TIME_24_HOUR  = 'R'; // (hh:mm same as %H:%M)
4759 // *    static final char LOCALE_TIME   = 'X'; // (%H:%M:%S) - parse format?
4760         static final char DATE_TIME             = 'c';
4761                                             // (Sat Nov 04 12:02:33 EST 1999)
4762         static final char DATE                  = 'D'; // (mm/dd/yy)
4763         static final char ISO_STANDARD_DATE     = 'F'; // (%Y-%m-%d)
4764 // *    static final char LOCALE_DATE           = 'x'; // (mm/dd/yy)
4765 
4766         static boolean isValid(char c) {
4767             switch (c) {
4768             case HOUR_OF_DAY_0:
4769             case HOUR_0:
4770             case HOUR_OF_DAY:
4771             case HOUR:
4772             case MINUTE:
4773             case NANOSECOND:
4774             case MILLISECOND:
4775             case MILLISECOND_SINCE_EPOCH:
4776             case AM_PM:
4777             case SECONDS_SINCE_EPOCH:
4778             case SECOND:
4779             case TIME:
4780             case ZONE_NUMERIC:
4781             case ZONE:
4782 
4783             // Date
4784             case NAME_OF_DAY_ABBREV:
4785             case NAME_OF_DAY:
4786             case NAME_OF_MONTH_ABBREV:
4787             case NAME_OF_MONTH:
4788             case CENTURY:
4789             case DAY_OF_MONTH_0:
4790             case DAY_OF_MONTH:
4791 // *        case ISO_WEEK_OF_YEAR_2:
4792 // *        case ISO_WEEK_OF_YEAR_4:
4793             case NAME_OF_MONTH_ABBREV_X:
4794             case DAY_OF_YEAR:
4795             case MONTH:
4796 // *        case DAY_OF_WEEK_1:
4797 // *        case WEEK_OF_YEAR_SUNDAY:
4798 // *        case WEEK_OF_YEAR_MONDAY_01:
4799 // *        case DAY_OF_WEEK_0:
4800 // *        case WEEK_OF_YEAR_MONDAY:
4801             case YEAR_2:
4802             case YEAR_4:
4803 
4804             // Composites
4805             case TIME_12_HOUR:
4806             case TIME_24_HOUR:
4807 // *        case LOCALE_TIME:
4808             case DATE_TIME:
4809             case DATE:
4810             case ISO_STANDARD_DATE:
4811 // *        case LOCALE_DATE:
4812                 return true;
4813             default:
4814                 return false;
4815             }
4816         }
4817     }
4818 }
4819