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