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