Source Code Cross Referenced for Formatter.java in  » 6.0-JDK-Core » Collections-Jar-Zip-Logging-regex » java » util » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » Collections Jar Zip Logging regex » java.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001        /*
0002         * Copyright 2003-2007 Sun Microsystems, Inc.  All Rights Reserved.
0003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004         *
0005         * This code is free software; you can redistribute it and/or modify it
0006         * under the terms of the GNU General Public License version 2 only, as
0007         * published by the Free Software Foundation.  Sun designates this
0008         * particular file as subject to the "Classpath" exception as provided
0009         * by Sun in the LICENSE file that accompanied this code.
0010         *
0011         * This code is distributed in the hope that it will be useful, but WITHOUT
0012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014         * version 2 for more details (a copy is included in the LICENSE file that
0015         * accompanied this code).
0016         *
0017         * You should have received a copy of the GNU General Public License version
0018         * 2 along with this work; if not, write to the Free Software Foundation,
0019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020         *
0021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022         * CA 95054 USA or visit www.sun.com if you need additional information or
0023         * have any questions.
0024         */
0025
0026        package java.util;
0027
0028        import java.io.BufferedWriter;
0029        import java.io.Closeable;
0030        import java.io.IOException;
0031        import java.io.File;
0032        import java.io.FileOutputStream;
0033        import java.io.FileNotFoundException;
0034        import java.io.Flushable;
0035        import java.io.OutputStream;
0036        import java.io.OutputStreamWriter;
0037        import java.io.PrintStream;
0038        import java.io.UnsupportedEncodingException;
0039        import java.math.BigDecimal;
0040        import java.math.BigInteger;
0041        import java.math.MathContext;
0042        import java.nio.charset.Charset;
0043        import java.text.DateFormatSymbols;
0044        import java.text.DecimalFormat;
0045        import java.text.DecimalFormatSymbols;
0046        import java.text.NumberFormat;
0047        import java.util.Calendar;
0048        import java.util.Date;
0049        import java.util.Locale;
0050        import java.util.regex.Matcher;
0051        import java.util.regex.Pattern;
0052
0053        import sun.misc.FpUtils;
0054        import sun.misc.DoubleConsts;
0055        import sun.misc.FormattedFloatingDecimal;
0056
0057        /**
0058         * An interpreter for printf-style format strings.  This class provides support
0059         * for layout justification and alignment, common formats for numeric, string,
0060         * and date/time data, and locale-specific output.  Common Java types such as
0061         * <tt>byte</tt>, {@link java.math.BigDecimal BigDecimal}, and {@link Calendar}
0062         * are supported.  Limited formatting customization for arbitrary user types is
0063         * provided through the {@link Formattable} interface.
0064         *
0065         * <p> Formatters are not necessarily safe for multithreaded access.  Thread
0066         * safety is optional and is the responsibility of users of methods in this
0067         * class.
0068         *
0069         * <p> Formatted printing for the Java language is heavily inspired by C's
0070         * <tt>printf</tt>.  Although the format strings are similar to C, some
0071         * customizations have been made to accommodate the Java language and exploit
0072         * some of its features.  Also, Java formatting is more strict than C's; for
0073         * example, if a conversion is incompatible with a flag, an exception will be
0074         * thrown.  In C inapplicable flags are silently ignored.  The format strings
0075         * are thus intended to be recognizable to C programmers but not necessarily
0076         * completely compatible with those in C.
0077         *
0078         * <p> Examples of expected usage:
0079         *
0080         * <blockquote><pre>
0081         *   StringBuilder sb = new StringBuilder();
0082         *   // Send all output to the Appendable object sb
0083         *   Formatter formatter = new Formatter(sb, Locale.US);
0084         *
0085         *   // Explicit argument indices may be used to re-order output.
0086         *   formatter.format("%4$2s %3$2s %2$2s %1$2s", "a", "b", "c", "d")
0087         *   // -&gt; " d  c  b  a"
0088         *
0089         *   // Optional locale as the first argument can be used to get
0090         *   // locale-specific formatting of numbers.  The precision and width can be
0091         *   // given to round and align the value.
0092         *   formatter.format(Locale.FRANCE, "e = %+10.4f", Math.E);
0093         *   // -&gt; "e =    +2,7183"
0094         *
0095         *   // The '(' numeric flag may be used to format negative numbers with
0096         *   // parentheses rather than a minus sign.  Group separators are
0097         *   // automatically inserted.
0098         *   formatter.format("Amount gained or lost since last statement: $ %(,.2f",
0099         *                    balanceDelta);
0100         *   // -&gt; "Amount gained or lost since last statement: $ (6,217.58)"
0101         * </pre></blockquote>
0102         *
0103         * <p> Convenience methods for common formatting requests exist as illustrated
0104         * by the following invocations:
0105         *
0106         * <blockquote><pre>
0107         *   // Writes a formatted string to System.out.
0108         *   System.out.format("Local time: %tT", Calendar.getInstance());
0109         *   // -&gt; "Local time: 13:34:18"
0110         *
0111         *   // Writes formatted output to System.err.
0112         *   System.err.printf("Unable to open file '%1$s': %2$s",
0113         *                     fileName, exception.getMessage());
0114         *   // -&gt; "Unable to open file 'food': No such file or directory"
0115         * </pre></blockquote>
0116         *
0117         * <p> Like C's <tt>sprintf(3)</tt>, Strings may be formatted using the static
0118         * method {@link String#format(String,Object...) String.format}:
0119         *
0120         * <blockquote><pre>
0121         *   // Format a string containing a date.
0122         *   import java.util.Calendar;
0123         *   import java.util.GregorianCalendar;
0124         *   import static java.util.Calendar.*;
0125         *
0126         *   Calendar c = new GregorianCalendar(1995, MAY, 23);
0127         *   String s = String.format("Duke's Birthday: %1$tm %1$te,%1$tY", c);
0128         *   // -&gt; s == "Duke's Birthday: May 23, 1995"
0129         * </pre></blockquote>
0130         *
0131         * <h3><a name="org">Organization</a></h3>
0132         *
0133         * <p> This specification is divided into two sections.  The first section, <a
0134         * href="#summary">Summary</a>, covers the basic formatting concepts.  This
0135         * section is intended for users who want to get started quickly and are
0136         * familiar with formatted printing in other programming languages.  The second
0137         * section, <a href="#detail">Details</a>, covers the specific implementation
0138         * details.  It is intended for users who want more precise specification of
0139         * formatting behavior.
0140         *
0141         * <h3><a name="summary">Summary</a></h3>
0142         *
0143         * <p> This section is intended to provide a brief overview of formatting
0144         * concepts.  For precise behavioral details, refer to the <a
0145         * href="#detail">Details</a> section.
0146         *
0147         * <h4><a name="syntax">Format String Syntax</a></h4>
0148         *
0149         * <p> Every method which produces formatted output requires a <i>format
0150         * string</i> and an <i>argument list</i>.  The format string is a {@link
0151         * String} which may contain fixed text and one or more embedded <i>format
0152         * specifiers</i>.  Consider the following example:
0153         *
0154         * <blockquote><pre>
0155         *   Calendar c = ...;
0156         *   String s = String.format("Duke's Birthday: %1$tm %1$te,%1$tY", c);
0157         * </pre></blockquote>
0158         *
0159         * This format string is the first argument to the <tt>format</tt> method.  It
0160         * contains three format specifiers "<tt>%1$tm</tt>", "<tt>%1$te</tt>", and
0161         * "<tt>%1$tY</tt>" which indicate how the arguments should be processed and
0162         * where they should be inserted in the text.  The remaining portions of the
0163         * format string are fixed text including <tt>"Dukes Birthday: "</tt> and any
0164         * other spaces or punctuation.
0165         *
0166         * The argument list consists of all arguments passed to the method after the
0167         * format string.  In the above example, the argument list is of size one and
0168         * consists of the {@link java.util.Calendar Calendar} object <tt>c</tt>.
0169         *
0170         * <ul>
0171         *
0172         * <li> The format specifiers for general, character, and numeric types have
0173         * the following syntax:
0174         *
0175         * <blockquote><pre>
0176         *   %[argument_index$][flags][width][.precision]conversion
0177         * </pre></blockquote>
0178         *
0179         * <p> The optional <i>argument_index</i> is a decimal integer indicating the
0180         * position of the argument in the argument list.  The first argument is
0181         * referenced by "<tt>1$</tt>", the second by "<tt>2$</tt>", etc.
0182         *
0183         * <p> The optional <i>flags</i> is a set of characters that modify the output
0184         * format.  The set of valid flags depends on the conversion.
0185         *
0186         * <p> The optional <i>width</i> is a non-negative decimal integer indicating
0187         * the minimum number of characters to be written to the output.
0188         *
0189         * <p> The optional <i>precision</i> is a non-negative decimal integer usually
0190         * used to restrict the number of characters.  The specific behavior depends on
0191         * the conversion.
0192         *
0193         * <p> The required <i>conversion</i> is a character indicating how the
0194         * argument should be formatted.  The set of valid conversions for a given
0195         * argument depends on the argument's data type.
0196         *
0197         * <li> The format specifiers for types which are used to represents dates and
0198         * times have the following syntax:
0199         *
0200         * <blockquote><pre>
0201         *   %[argument_index$][flags][width]conversion
0202         * </pre></blockquote>
0203         *
0204         * <p> The optional <i>argument_index</i>, <i>flags</i> and <i>width</i> are
0205         * defined as above.
0206         *
0207         * <p> The required <i>conversion</i> is a two character sequence.  The first
0208         * character is <tt>'t'</tt> or <tt>'T'</tt>.  The second character indicates
0209         * the format to be used.  These characters are similar to but not completely
0210         * identical to those defined by GNU <tt>date</tt> and POSIX
0211         * <tt>strftime(3c)</tt>.
0212         *
0213         * <li> The format specifiers which do not correspond to arguments have the
0214         * following syntax:
0215         *
0216         * <blockquote><pre>
0217         *   %[flags][width]conversion
0218         * </pre></blockquote>
0219         *
0220         * <p> The optional <i>flags</i> and <i>width</i> is defined as above.
0221         *
0222         * <p> The required <i>conversion</i> is a character indicating content to be
0223         * inserted in the output.
0224         *
0225         * </ul>
0226         *
0227         * <h4> Conversions </h4>
0228         *
0229         * <p> Conversions are divided into the following categories:
0230         *
0231         * <ol>
0232         *
0233         * <li> <b>General</b> - may be applied to any argument
0234         * type
0235         *
0236         * <li> <b>Character</b> - may be applied to basic types which represent
0237         * Unicode characters: <tt>char</tt>, {@link Character}, <tt>byte</tt>, {@link
0238         * Byte}, <tt>short</tt>, and {@link Short}. This conversion may also be
0239         * applied to the types <tt>int</tt> and {@link Integer} when {@link
0240         * Character#isValidCodePoint} returns <tt>true</tt>
0241         *
0242         * <li> <b>Numeric</b>
0243         *
0244         * <ol>
0245         *
0246         * <li> <b>Integral</b> - may be applied to Java integral types: <tt>byte</tt>,
0247         * {@link Byte}, <tt>short</tt>, {@link Short}, <tt>int</tt> and {@link
0248         * Integer}, <tt>long</tt>, {@link Long}, and {@link java.math.BigInteger
0249         * BigInteger}
0250         *
0251         * <li><b>Floating Point</b> - may be applied to Java floating-point types:
0252         * <tt>float</tt>, {@link Float}, <tt>double</tt>, {@link Double}, and {@link
0253         * java.math.BigDecimal BigDecimal}
0254         *
0255         * </ol>
0256         *
0257         * <li> <b>Date/Time</b> - may be applied to Java types which are capable of
0258         * encoding a date or time: <tt>long</tt>, {@link Long}, {@link Calendar}, and
0259         * {@link Date}.
0260         *
0261         * <li> <b>Percent</b> - produces a literal <tt>'%'</tt>
0262         * (<tt>'&#92;u0025'</tt>)
0263         *
0264         * <li> <b>Line Separator</b> - produces the platform-specific line separator
0265         *
0266         * </ol>
0267         *
0268         * <p> The following table summarizes the supported conversions.  Conversions
0269         * denoted by an upper-case character (i.e. <tt>'B'</tt>, <tt>'H'</tt>,
0270         * <tt>'S'</tt>, <tt>'C'</tt>, <tt>'X'</tt>, <tt>'E'</tt>, <tt>'G'</tt>,
0271         * <tt>'A'</tt>, and <tt>'T'</tt>) are the same as those for the corresponding
0272         * lower-case conversion characters except that the result is converted to
0273         * upper case according to the rules of the prevailing {@link java.util.Locale
0274         * Locale}.  The result is equivalent to the following invocation of {@link
0275         * String#toUpperCase()}
0276         *
0277         * <pre>
0278         *    out.toUpperCase() </pre>
0279         *
0280         * <table cellpadding=5 summary="genConv">
0281         *
0282         * <tr><th valign="bottom"> Conversion
0283         *     <th valign="bottom"> Argument Category
0284         *     <th valign="bottom"> Description
0285         *
0286         * <tr><td valign="top"> <tt>'b'</tt>, <tt>'B'</tt>
0287         *     <td valign="top"> general
0288         *     <td> If the argument <i>arg</i> is <tt>null</tt>, then the result is
0289         *     "<tt>false</tt>".  If <i>arg</i> is a <tt>boolean</tt> or {@link
0290         *     Boolean}, then the result is the string returned by {@link
0291         *     String#valueOf(boolean) String.valueOf(arg)}.  Otherwise, the result is
0292         *     "true".
0293         *
0294         * <tr><td valign="top"> <tt>'h'</tt>, <tt>'H'</tt>
0295         *     <td valign="top"> general
0296         *     <td> If the argument <i>arg</i> is <tt>null</tt>, then the result is
0297         *     "<tt>null</tt>".  Otherwise, the result is obtained by invoking
0298         *     <tt>Integer.toHexString(arg.hashCode())</tt>.
0299         *
0300         * <tr><td valign="top"> <tt>'s'</tt>, <tt>'S'</tt>
0301         *     <td valign="top"> general
0302         *     <td> If the argument <i>arg</i> is <tt>null</tt>, then the result is
0303         *     "<tt>null</tt>".  If <i>arg</i> implements {@link Formattable}, then
0304         *     {@link Formattable#formatTo arg.formatTo} is invoked. Otherwise, the
0305         *     result is obtained by invoking <tt>arg.toString()</tt>.
0306         *
0307         * <tr><td valign="top"><tt>'c'</tt>, <tt>'C'</tt>
0308         *     <td valign="top"> character
0309         *     <td> The result is a Unicode character
0310         *
0311         * <tr><td valign="top"><tt>'d'</tt>
0312         *     <td valign="top"> integral
0313         *     <td> The result is formatted as a decimal integer
0314         *
0315         * <tr><td valign="top"><tt>'o'</tt>
0316         *     <td valign="top"> integral
0317         *     <td> The result is formatted as an octal integer
0318         *
0319         * <tr><td valign="top"><tt>'x'</tt>, <tt>'X'</tt>
0320         *     <td valign="top"> integral
0321         *     <td> The result is formatted as a hexadecimal integer
0322         *
0323         * <tr><td valign="top"><tt>'e'</tt>, <tt>'E'</tt>
0324         *     <td valign="top"> floating point
0325         *     <td> The result is formatted as a decimal number in computerized
0326         *     scientific notation
0327         *
0328         * <tr><td valign="top"><tt>'f'</tt>
0329         *     <td valign="top"> floating point
0330         *     <td> The result is formatted as a decimal number
0331         *
0332         * <tr><td valign="top"><tt>'g'</tt>, <tt>'G'</tt>
0333         *     <td valign="top"> floating point
0334         *     <td> The result is formatted using computerized scientific notation or
0335         *     decimal format, depending on the precision and the value after rounding.
0336         *
0337         * <tr><td valign="top"><tt>'a'</tt>, <tt>'A'</tt>
0338         *     <td valign="top"> floating point
0339         *     <td> The result is formatted as a hexadecimal floating-point number with
0340         *     a significand and an exponent
0341         *
0342         * <tr><td valign="top"><tt>'t'</tt>, <tt>'T'</tt>
0343         *     <td valign="top"> date/time
0344         *     <td> Prefix for date and time conversion characters.  See <a
0345         *     href="#dt">Date/Time Conversions</a>.
0346         *
0347         * <tr><td valign="top"><tt>'%'</tt>
0348         *     <td valign="top"> percent
0349         *     <td> The result is a literal <tt>'%'</tt> (<tt>'&#92;u0025'</tt>)
0350         *
0351         * <tr><td valign="top"><tt>'n'</tt>
0352         *     <td valign="top"> line separator
0353         *     <td> The result is the platform-specific line separator
0354         *
0355         * </table>
0356         *
0357         * <p> Any characters not explicitly defined as conversions are illegal and are
0358         * reserved for future extensions.
0359         *
0360         * <h4><a name="dt">Date/Time Conversions</a></h4>
0361         *
0362         * <p> The following date and time conversion suffix characters are defined for
0363         * the <tt>'t'</tt> and <tt>'T'</tt> conversions.  The types are similar to but
0364         * not completely identical to those defined by GNU <tt>date</tt> and POSIX
0365         * <tt>strftime(3c)</tt>.  Additional conversion types are provided to access
0366         * Java-specific functionality (e.g. <tt>'L'</tt> for milliseconds within the
0367         * second).
0368         *
0369         * <p> The following conversion characters are used for formatting times:
0370         *
0371         * <table cellpadding=5 summary="time">
0372         *
0373         * <tr><td valign="top"> <tt>'H'</tt>
0374         *     <td> Hour of the day for the 24-hour clock, formatted as two digits with
0375         *     a leading zero as necessary i.e. <tt>00 - 23</tt>.
0376         *
0377         * <tr><td valign="top"><tt>'I'</tt>
0378         *     <td> Hour for the 12-hour clock, formatted as two digits with a leading
0379         *     zero as necessary, i.e.  <tt>01 - 12</tt>.
0380         *
0381         * <tr><td valign="top"><tt>'k'</tt>
0382         *     <td> Hour of the day for the 24-hour clock, i.e. <tt>0 - 23</tt>.
0383         *
0384         * <tr><td valign="top"><tt>'l'</tt>
0385         *     <td> Hour for the 12-hour clock, i.e. <tt>1 - 12</tt>.
0386         *
0387         * <tr><td valign="top"><tt>'M'</tt>
0388         *     <td> Minute within the hour formatted as two digits with a leading zero
0389         *     as necessary, i.e.  <tt>00 - 59</tt>.
0390         *
0391         * <tr><td valign="top"><tt>'S'</tt>
0392         *     <td> Seconds within the minute, formatted as two digits with a leading
0393         *     zero as necessary, i.e. <tt>00 - 60</tt> ("<tt>60</tt>" is a special
0394         *     value required to support leap seconds).
0395         *
0396         * <tr><td valign="top"><tt>'L'</tt>
0397         *     <td> Millisecond within the second formatted as three digits with
0398         *     leading zeros as necessary, i.e. <tt>000 - 999</tt>.
0399         *
0400         * <tr><td valign="top"><tt>'N'</tt>
0401         *     <td> Nanosecond within the second, formatted as nine digits with leading
0402         *     zeros as necessary, i.e. <tt>000000000 - 999999999</tt>.
0403         *
0404         * <tr><td valign="top"><tt>'p'</tt>
0405         *     <td> Locale-specific {@linkplain
0406         *     java.text.DateFormatSymbols#getAmPmStrings morning or afternoon} marker
0407         *     in lower case, e.g."<tt>am</tt>" or "<tt>pm</tt>". Use of the conversion
0408         *     prefix <tt>'T'</tt> forces this output to upper case.
0409         *
0410         * <tr><td valign="top"><tt>'z'</tt>
0411         *     <td> <a href="http://www.ietf.org/rfc/rfc0822.txt">RFC&nbsp;822</a>
0412         *     style numeric time zone offset from GMT, e.g. <tt>-0800</tt>.
0413         *
0414         * <tr><td valign="top"><tt>'Z'</tt>
0415         *     <td> A string representing the abbreviation for the time zone.  The
0416         *     Formatter's locale will supersede the locale of the argument (if any).
0417         *
0418         * <tr><td valign="top"><tt>'s'</tt>
0419         *     <td> Seconds since the beginning of the epoch starting at 1 January 1970
0420         *     <tt>00:00:00</tt> UTC, i.e. <tt>Long.MIN_VALUE/1000</tt> to
0421         *     <tt>Long.MAX_VALUE/1000</tt>.
0422         *
0423         * <tr><td valign="top"><tt>'Q'</tt>
0424         *     <td> Milliseconds since the beginning of the epoch starting at 1 January
0425         *     1970 <tt>00:00:00</tt> UTC, i.e. <tt>Long.MIN_VALUE</tt> to
0426         *     <tt>Long.MAX_VALUE</tt>.
0427         *
0428         * </table>
0429         *
0430         * <p> The following conversion characters are used for formatting dates:
0431         *
0432         * <table cellpadding=5 summary="date">
0433         *
0434         * <tr><td valign="top"><tt>'B'</tt>
0435         *     <td> Locale-specific {@linkplain java.text.DateFormatSymbols#getMonths
0436         *     full month name}, e.g. <tt>"January"</tt>, <tt>"February"</tt>.
0437         *
0438         * <tr><td valign="top"><tt>'b'</tt>
0439         *     <td> Locale-specific {@linkplain
0440         *     java.text.DateFormatSymbols#getShortMonths abbreviated month name},
0441         *     e.g. <tt>"Jan"</tt>, <tt>"Feb"</tt>.
0442         *
0443         * <tr><td valign="top"><tt>'h'</tt>
0444         *     <td> Same as <tt>'b'</tt>.
0445         *
0446         * <tr><td valign="top"><tt>'A'</tt>
0447         *     <td> Locale-specific full name of the {@linkplain
0448         *     java.text.DateFormatSymbols#getWeekdays day of the week},
0449         *     e.g. <tt>"Sunday"</tt>, <tt>"Monday"</tt>
0450         *
0451         * <tr><td valign="top"><tt>'a'</tt>
0452         *     <td> Locale-specific short name of the {@linkplain
0453         *     java.text.DateFormatSymbols#getShortWeekdays day of the week},
0454         *     e.g. <tt>"Sun"</tt>, <tt>"Mon"</tt>
0455         *
0456         * <tr><td valign="top"><tt>'C'</tt>
0457         *     <td> Four-digit year divided by <tt>100</tt>, formatted as two digits
0458         *     with leading zero as necessary, i.e. <tt>00 - 99</tt>
0459         *
0460         * <tr><td valign="top"><tt>'Y'</tt>
0461         *     <td> Year, formatted as at least four digits with leading zeros as
0462         *     necessary, e.g. <tt>0092</tt> equals <tt>92</tt> CE for the Gregorian
0463         *     calendar.
0464         *
0465         * <tr><td valign="top"><tt>'y'</tt>
0466         *     <td> Last two digits of the year, formatted with leading zeros as
0467         *     necessary, i.e. <tt>00 - 99</tt>.
0468         *
0469         * <tr><td valign="top"><tt>'j'</tt>
0470         *     <td> Day of year, formatted as three digits with leading zeros as
0471         *     necessary, e.g. <tt>001 - 366</tt> for the Gregorian calendar.
0472         *
0473         * <tr><td valign="top"><tt>'m'</tt>
0474         *     <td> Month, formatted as two digits with leading zeros as necessary,
0475         *     i.e. <tt>01 - 13</tt>.
0476         *
0477         * <tr><td valign="top"><tt>'d'</tt>
0478         *     <td> Day of month, formatted as two digits with leading zeros as
0479         *     necessary, i.e. <tt>01 - 31</tt>
0480         *
0481         * <tr><td valign="top"><tt>'e'</tt>
0482         *     <td> Day of month, formatted as two digits, i.e. <tt>1 - 31</tt>.
0483         *
0484         * </table>
0485         *
0486         * <p> The following conversion characters are used for formatting common
0487         * date/time compositions.
0488         *
0489         * <table cellpadding=5 summary="composites">
0490         *
0491         * <tr><td valign="top"><tt>'R'</tt>
0492         *     <td> Time formatted for the 24-hour clock as <tt>"%tH:%tM"</tt>
0493         *
0494         * <tr><td valign="top"><tt>'T'</tt>
0495         *     <td> Time formatted for the 24-hour clock as <tt>"%tH:%tM:%tS"</tt>.
0496         *
0497         * <tr><td valign="top"><tt>'r'</tt>
0498         *     <td> Time formatted for the 12-hour clock as <tt>"%tI:%tM:%tS %Tp"</tt>.
0499         *     The location of the morning or afternoon marker (<tt>'%Tp'</tt>) may be
0500         *     locale-dependent.
0501         *
0502         * <tr><td valign="top"><tt>'D'</tt>
0503         *     <td> Date formatted as <tt>"%tm/%td/%ty"</tt>.
0504         *
0505         * <tr><td valign="top"><tt>'F'</tt>
0506         *     <td> <a href="http://www.w3.org/TR/NOTE-datetime">ISO&nbsp;8601</a>
0507         *     complete date formatted as <tt>"%tY-%tm-%td"</tt>.
0508         *
0509         * <tr><td valign="top"><tt>'c'</tt>
0510         *     <td> Date and time formatted as <tt>"%ta %tb %td %tT %tZ %tY"</tt>,
0511         *     e.g. <tt>"Sun Jul 20 16:17:00 EDT 1969"</tt>.
0512         *
0513         * </table>
0514         *
0515         * <p> Any characters not explicitly defined as date/time conversion suffixes
0516         * are illegal and are reserved for future extensions.
0517         *
0518         * <h4> Flags </h4>
0519         *
0520         * <p> The following table summarizes the supported flags.  <i>y</i> means the
0521         * flag is supported for the indicated argument types.
0522         *
0523         * <table cellpadding=5 summary="genConv">
0524         *
0525         * <tr><th valign="bottom"> Flag <th valign="bottom"> General
0526         *     <th valign="bottom"> Character <th valign="bottom"> Integral
0527         *     <th valign="bottom"> Floating Point
0528         *     <th valign="bottom"> Date/Time
0529         *     <th valign="bottom"> Description
0530         *
0531         * <tr><td> '-' <td align="center" valign="top"> y
0532         *     <td align="center" valign="top"> y
0533         *     <td align="center" valign="top"> y
0534         *     <td align="center" valign="top"> y
0535         *     <td align="center" valign="top"> y
0536         *     <td> The result will be left-justified.
0537         *
0538         * <tr><td> '#' <td align="center" valign="top"> y<sup>1</sup>
0539         *     <td align="center" valign="top"> -
0540         *     <td align="center" valign="top"> y<sup>3</sup>
0541         *     <td align="center" valign="top"> y
0542         *     <td align="center" valign="top"> -
0543         *     <td> The result should use a conversion-dependent alternate form
0544         *
0545         * <tr><td> '+' <td align="center" valign="top"> -
0546         *     <td align="center" valign="top"> -
0547         *     <td align="center" valign="top"> y<sup>4</sup>
0548         *     <td align="center" valign="top"> y
0549         *     <td align="center" valign="top"> -
0550         *     <td> The result will always include a sign
0551         *
0552         * <tr><td> '&nbsp;&nbsp;' <td align="center" valign="top"> -
0553         *     <td align="center" valign="top"> -
0554         *     <td align="center" valign="top"> y<sup>4</sup>
0555         *     <td align="center" valign="top"> y
0556         *     <td align="center" valign="top"> -
0557         *     <td> The result will include a leading space for positive values
0558         *
0559         * <tr><td> '0' <td align="center" valign="top"> -
0560         *     <td align="center" valign="top"> -
0561         *     <td align="center" valign="top"> y
0562         *     <td align="center" valign="top"> y
0563         *     <td align="center" valign="top"> -
0564         *     <td> The result will be zero-padded
0565         *
0566         * <tr><td> ',' <td align="center" valign="top"> -
0567         *     <td align="center" valign="top"> -
0568         *     <td align="center" valign="top"> y<sup>2</sup>
0569         *     <td align="center" valign="top"> y<sup>5</sup>
0570         *     <td align="center" valign="top"> -
0571         *     <td> The result will include locale-specific {@linkplain
0572         *     java.text.DecimalFormatSymbols#getGroupingSeparator grouping separators}
0573         *
0574         * <tr><td> '(' <td align="center" valign="top"> -
0575         *     <td align="center" valign="top"> -
0576         *     <td align="center" valign="top"> y<sup>4</sup>
0577         *     <td align="center" valign="top"> y<sup>5</sup>
0578         *     <td align="center"> -
0579         *     <td> The result will enclose negative numbers in parentheses
0580         *
0581         * </table>
0582         *
0583         * <p> <sup>1</sup> Depends on the definition of {@link Formattable}.
0584         *
0585         * <p> <sup>2</sup> For <tt>'d'</tt> conversion only.
0586         *
0587         * <p> <sup>3</sup> For <tt>'o'</tt>, <tt>'x'</tt>, and <tt>'X'</tt>
0588         * conversions only.
0589         *
0590         * <p> <sup>4</sup> For <tt>'d'</tt>, <tt>'o'</tt>, <tt>'x'</tt>, and
0591         * <tt>'X'</tt> conversions applied to {@link java.math.BigInteger BigInteger}
0592         * or <tt>'d'</tt> applied to <tt>byte</tt>, {@link Byte}, <tt>short</tt>, {@link
0593         * Short}, <tt>int</tt> and {@link Integer}, <tt>long</tt>, and {@link Long}.
0594         *
0595         * <p> <sup>5</sup> For <tt>'e'</tt>, <tt>'E'</tt>, <tt>'f'</tt>,
0596         * <tt>'g'</tt>, and <tt>'G'</tt> conversions only.
0597         *
0598         * <p> Any characters not explicitly defined as flags are illegal and are
0599         * reserved for future extensions.
0600         *
0601         * <h4> Width </h4>
0602         *
0603         * <p> The width is the minimum number of characters to be written to the
0604         * output.  For the line separator conversion, width is not applicable; if it
0605         * is provided, an exception will be thrown.
0606         *
0607         * <h4> Precision </h4>
0608         *
0609         * <p> For general argument types, the precision is the maximum number of
0610         * characters to be written to the output.
0611         *
0612         * <p> For the floating-point conversions <tt>'e'</tt>, <tt>'E'</tt>, and
0613         * <tt>'f'</tt> the precision is the number of digits after the decimal
0614         * separator.  If the conversion is <tt>'g'</tt> or <tt>'G'</tt>, then the
0615         * precision is the total number of digits in the resulting magnitude after
0616         * rounding.  If the conversion is <tt>'a'</tt> or <tt>'A'</tt>, then the
0617         * precision must not be specified.
0618         *
0619         * <p> For character, integral, and date/time argument types and the percent
0620         * and line separator conversions, the precision is not applicable; if a
0621         * precision is provided, an exception will be thrown.
0622         *
0623         * <h4> Argument Index </h4>
0624         *
0625         * <p> The argument index is a decimal integer indicating the position of the
0626         * argument in the argument list.  The first argument is referenced by
0627         * "<tt>1$</tt>", the second by "<tt>2$</tt>", etc.
0628         *
0629         * <p> Another way to reference arguments by position is to use the
0630         * <tt>'&lt;'</tt> (<tt>'&#92;u003c'</tt>) flag, which causes the argument for
0631         * the previous format specifier to be re-used.  For example, the following two
0632         * statements would produce identical strings:
0633         *
0634         * <blockquote><pre>
0635         *   Calendar c = ...;
0636         *   String s1 = String.format("Duke's Birthday: %1$tm %1$te,%1$tY", c);
0637         *
0638         *   String s2 = String.format("Duke's Birthday: %1$tm %&lt;te,%&lt;tY", c);
0639         * </pre></blockquote>
0640         *
0641         * <hr>
0642         * <h3><a name="detail">Details</a></h3>
0643         *
0644         * <p> This section is intended to provide behavioral details for formatting,
0645         * including conditions and exceptions, supported data types, localization, and
0646         * interactions between flags, conversions, and data types.  For an overview of
0647         * formatting concepts, refer to the <a href="#summary">Summary</a>
0648         *
0649         * <p> Any characters not explicitly defined as conversions, date/time
0650         * conversion suffixes, or flags are illegal and are reserved for
0651         * future extensions.  Use of such a character in a format string will
0652         * cause an {@link UnknownFormatConversionException} or {@link
0653         * UnknownFormatFlagsException} to be thrown.
0654         *
0655         * <p> If the format specifier contains a width or precision with an invalid
0656         * value or which is otherwise unsupported, then a {@link
0657         * IllegalFormatWidthException} or {@link IllegalFormatPrecisionException}
0658         * respectively will be thrown.
0659         *
0660         * <p> If a format specifier contains a conversion character that is not
0661         * applicable to the corresponding argument, then an {@link
0662         * IllegalFormatConversionException} will be thrown.
0663         *
0664         * <p> All specified exceptions may be thrown by any of the <tt>format</tt>
0665         * methods of <tt>Formatter</tt> as well as by any <tt>format</tt> convenience
0666         * methods such as {@link String#format(String,Object...) String.format} and
0667         * {@link java.io.PrintStream#printf(String,Object...) PrintStream.printf}.
0668         *
0669         * <p> Conversions denoted by an upper-case character (i.e. <tt>'B'</tt>,
0670         * <tt>'H'</tt>, <tt>'S'</tt>, <tt>'C'</tt>, <tt>'X'</tt>, <tt>'E'</tt>,
0671         * <tt>'G'</tt>, <tt>'A'</tt>, and <tt>'T'</tt>) are the same as those for the
0672         * corresponding lower-case conversion characters except that the result is
0673         * converted to upper case according to the rules of the prevailing {@link
0674         * java.util.Locale Locale}.  The result is equivalent to the following
0675         * invocation of {@link String#toUpperCase()}
0676         *
0677         * <pre>
0678         *    out.toUpperCase() </pre>
0679         *
0680         * <h4><a name="dgen">General</a></h4>
0681         *
0682         * <p> The following general conversions may be applied to any argument type:
0683         *
0684         * <table cellpadding=5 summary="dgConv">
0685         *
0686         * <tr><td valign="top"> <tt>'b'</tt>
0687         *     <td valign="top"> <tt>'&#92;u0062'</tt>
0688         *     <td> Produces either "<tt>true</tt>" or "<tt>false</tt>" as returned by
0689         *     {@link Boolean#toString(boolean)}.
0690         *
0691         *     <p> If the argument is <tt>null</tt>, then the result is
0692         *     "<tt>false</tt>".  If the argument is a <tt>boolean</tt> or {@link
0693         *     Boolean}, then the result is the string returned by {@link
0694         *     String#valueOf(boolean) String.valueOf()}.  Otherwise, the result is
0695         *     "<tt>true</tt>".
0696         *
0697         *     <p> If the <tt>'#'</tt> flag is given, then a {@link
0698         *     FormatFlagsConversionMismatchException} will be thrown.
0699         *
0700         * <tr><td valign="top"> <tt>'B'</tt>
0701         *     <td valign="top"> <tt>'&#92;u0042'</tt>
0702         *     <td> The upper-case variant of <tt>'b'</tt>.
0703         *
0704         * <tr><td valign="top"> <tt>'h'</tt>
0705         *     <td valign="top"> <tt>'&#92;u0068'</tt>
0706         *     <td> Produces a string representing the hash code value of the object.
0707         *
0708         *     <p> If the argument, <i>arg</i> is <tt>null</tt>, then the
0709         *     result is "<tt>null</tt>".  Otherwise, the result is obtained
0710         *     by invoking <tt>Integer.toHexString(arg.hashCode())</tt>.
0711         *
0712         *     <p> If the <tt>'#'</tt> flag is given, then a {@link
0713         *     FormatFlagsConversionMismatchException} will be thrown.
0714         *
0715         * <tr><td valign="top"> <tt>'H'</tt>
0716         *     <td valign="top"> <tt>'&#92;u0048'</tt>
0717         *     <td> The upper-case variant of <tt>'h'</tt>.
0718         *
0719         * <tr><td valign="top"> <tt>'s'</tt>
0720         *     <td valign="top"> <tt>'&#92;u0073'</tt>
0721         *     <td> Produces a string.
0722         *
0723         *     <p> If the argument is <tt>null</tt>, then the result is
0724         *     "<tt>null</tt>".  If the argument implements {@link Formattable}, then
0725         *     its {@link Formattable#formatTo formatTo} method is invoked.
0726         *     Otherwise, the result is obtained by invoking the argument's
0727         *     <tt>toString()</tt> method.
0728         *
0729         *     <p> If the <tt>'#'</tt> flag is given and the argument is not a {@link
0730         *     Formattable} , then a {@link FormatFlagsConversionMismatchException}
0731         *     will be thrown.
0732         *
0733         * <tr><td valign="top"> <tt>'S'</tt>
0734         *     <td valign="top"> <tt>'&#92;u0053'</tt>
0735         *     <td> The upper-case variant of <tt>'s'</tt>.
0736         *
0737         * </table>
0738         *
0739         * <p> The following <a name="dFlags">flags</a> apply to general conversions:
0740         *
0741         * <table cellpadding=5 summary="dFlags">
0742         *
0743         * <tr><td valign="top"> <tt>'-'</tt>
0744         *     <td valign="top"> <tt>'&#92;u002d'</tt>
0745         *     <td> Left justifies the output.  Spaces (<tt>'&#92;u0020'</tt>) will be
0746         *     added at the end of the converted value as required to fill the minimum
0747         *     width of the field.  If the width is not provided, then a {@link
0748         *     MissingFormatWidthException} will be thrown.  If this flag is not given
0749         *     then the output will be right-justified.
0750         *
0751         * <tr><td valign="top"> <tt>'#'</tt>
0752         *     <td valign="top"> <tt>'&#92;u0023'</tt>
0753         *     <td> Requires the output use an alternate form.  The definition of the
0754         *     form is specified by the conversion.
0755         *
0756         * </table>
0757         *
0758         * <p> The <a name="genWidth">width</a> is the minimum number of characters to
0759         * be written to the
0760         * output.  If the length of the converted value is less than the width then
0761         * the output will be padded by <tt>'&nbsp;&nbsp;'</tt> (<tt>&#92;u0020'</tt>)
0762         * until the total number of characters equals the width.  The padding is on
0763         * the left by default.  If the <tt>'-'</tt> flag is given, then the padding
0764         * will be on the right.  If the width is not specified then there is no
0765         * minimum.
0766         *
0767         * <p> The precision is the maximum number of characters to be written to the
0768         * output.  The precision is applied before the width, thus the output will be
0769         * truncated to <tt>precision</tt> characters even if the width is greater than
0770         * the precision.  If the precision is not specified then there is no explicit
0771         * limit on the number of characters.
0772         *
0773         * <h4><a name="dchar">Character</a></h4>
0774         *
0775         * This conversion may be applied to <tt>char</tt> and {@link Character}.  It
0776         * may also be applied to the types <tt>byte</tt>, {@link Byte},
0777         * <tt>short</tt>, and {@link Short}, <tt>int</tt> and {@link Integer} when
0778         * {@link Character#isValidCodePoint} returns <tt>true</tt>.  If it returns
0779         * <tt>false</tt> then an {@link IllegalFormatCodePointException} will be
0780         * thrown.
0781         *
0782         * <table cellpadding=5 summary="charConv">
0783         *
0784         * <tr><td valign="top"> <tt>'c'</tt>
0785         *     <td valign="top"> <tt>'&#92;u0063'</tt>
0786         *     <td> Formats the argument as a Unicode character as described in <a
0787         *     href="../lang/Character.html#unicode">Unicode Character
0788         *     Representation</a>.  This may be more than one 16-bit <tt>char</tt> in
0789         *     the case where the argument represents a supplementary character.
0790         *
0791         *     <p> If the <tt>'#'</tt> flag is given, then a {@link
0792         *     FormatFlagsConversionMismatchException} will be thrown.
0793         *
0794         * <tr><td valign="top"> <tt>'C'</tt>
0795         *     <td valign="top"> <tt>'&#92;u0043'</tt>
0796         *     <td> The upper-case variant of <tt>'c'</tt>.
0797         *
0798         * </table>
0799         *
0800         * <p> The <tt>'-'</tt> flag defined for <a href="#dFlags">General
0801         * conversions</a> applies.  If the <tt>'#'</tt> flag is given, then a {@link
0802         * FormatFlagsConversionMismatchException} will be thrown.
0803         *
0804         * <p> The width is defined as for <a href="#genWidth">General conversions</a>.
0805         *
0806         * <p> The precision is not applicable.  If the precision is specified then an
0807         * {@link IllegalFormatPrecisionException} will be thrown.
0808         *
0809         * <h4><a name="dnum">Numeric</a></h4>
0810         *
0811         * <p> Numeric conversions are divided into the following categories:
0812         *
0813         * <ol>
0814         *
0815         * <li> <a href="#dnint"><b>Byte, Short, Integer, and Long</b></a>
0816         *
0817         * <li> <a href="#dnbint"><b>BigInteger</b></a>
0818         *
0819         * <li> <a href="#dndec"><b>Float and Double</b></a>
0820         *
0821         * <li> <a href="#dndec"><b>BigDecimal</b></a>
0822         *
0823         * </ol>
0824         *
0825         * <p> Numeric types will be formatted according to the following algorithm:
0826         *
0827         * <p><b><a name="l10n algorithm"> Number Localization Algorithm</a></b>
0828         *
0829         * <p> After digits are obtained for the integer part, fractional part, and
0830         * exponent (as appropriate for the data type), the following transformation
0831         * is applied:
0832         *
0833         * <ol>
0834         *
0835         * <li> Each digit character <i>d</i> in the string is replaced by a
0836         * locale-specific digit computed relative to the current locale's
0837         * {@linkplain java.text.DecimalFormatSymbols#getZeroDigit() zero digit}
0838         * <i>z</i>; that is <i>d&nbsp;-&nbsp;</i> <tt>'0'</tt>
0839         * <i>&nbsp;+&nbsp;z</i>.
0840         *
0841         * <li> If a decimal separator is present, a locale-specific {@linkplain
0842         * java.text.DecimalFormatSymbols#getDecimalSeparator decimal separator} is
0843         * substituted.
0844         *
0845         * <li> If the <tt>','</tt> (<tt>'&#92;u002c'</tt>)
0846         * <a name="l10n group">flag</a> is given, then the locale-specific {@linkplain
0847         * java.text.DecimalFormatSymbols#getGroupingSeparator grouping separator} is
0848         * inserted by scanning the integer part of the string from least significant
0849         * to most significant digits and inserting a separator at intervals defined by
0850         * the locale's {@linkplain java.text.DecimalFormat#getGroupingSize() grouping
0851         * size}.
0852         *
0853         * <li> If the <tt>'0'</tt> flag is given, then the locale-specific {@linkplain
0854         * java.text.DecimalFormatSymbols#getZeroDigit() zero digits} are inserted
0855         * after the sign character, if any, and before the first non-zero digit, until
0856         * the length of the string is equal to the requested field width.
0857         *
0858         * <li> If the value is negative and the <tt>'('</tt> flag is given, then a
0859         * <tt>'('</tt> (<tt>'&#92;u0028'</tt>) is prepended and a <tt>')'</tt>
0860         * (<tt>'&#92;u0029'</tt>) is appended.
0861         *
0862         * <li> If the value is negative (or floating-point negative zero) and
0863         * <tt>'('</tt> flag is not given, then a <tt>'-'</tt> (<tt>'&#92;u002d'</tt>)
0864         * is prepended.
0865         *
0866         * <li> If the <tt>'+'</tt> flag is given and the value is positive or zero (or
0867         * floating-point positive zero), then a <tt>'+'</tt> (<tt>'&#92;u002b'</tt>)
0868         * will be prepended.
0869         *
0870         * </ol>
0871         *
0872         * <p> If the value is NaN or positive infinity the literal strings "NaN" or
0873         * "Infinity" respectively, will be output.  If the value is negative infinity,
0874         * then the output will be "(Infinity)" if the <tt>'('</tt> flag is given
0875         * otherwise the output will be "-Infinity".  These values are not localized.
0876         *
0877         * <p><a name="dnint"><b> Byte, Short, Integer, and Long </b></a>
0878         *
0879         * <p> The following conversions may be applied to <tt>byte</tt>, {@link Byte},
0880         * <tt>short</tt>, {@link Short}, <tt>int</tt> and {@link Integer},
0881         * <tt>long</tt>, and {@link Long}.
0882         *
0883         * <table cellpadding=5 summary="IntConv">
0884         *
0885         * <tr><td valign="top"> <tt>'d'</tt>
0886         *     <td valign="top"> <tt>'&#92;u0054'</tt>
0887         *     <td> Formats the argument as a decimal integer. The <a
0888         *     href="#l10n algorithm">localization algorithm</a> is applied.
0889         *
0890         *     <p> If the <tt>'0'</tt> flag is given and the value is negative, then
0891         *     the zero padding will occur after the sign.
0892         *
0893         *     <p> If the <tt>'#'</tt> flag is given then a {@link
0894         *     FormatFlagsConversionMismatchException} will be thrown.
0895         *
0896         * <tr><td valign="top"> <tt>'o'</tt>
0897         *     <td valign="top"> <tt>'&#92;u006f'</tt>
0898         *     <td> Formats the argument as an integer in base eight.  No localization
0899         *     is applied.
0900         *
0901         *     <p> If <i>x</i> is negative then the result will be an unsigned value
0902         *     generated by adding 2<sup>n</sup> to the value where <tt>n</tt> is the
0903         *     number of bits in the type as returned by the static <tt>SIZE</tt> field
0904         *     in the {@linkplain Byte#SIZE Byte}, {@linkplain Short#SIZE Short},
0905         *     {@linkplain Integer#SIZE Integer}, or {@linkplain Long#SIZE Long}
0906         *     classes as appropriate.
0907         *
0908         *     <p> If the <tt>'#'</tt> flag is given then the output will always begin
0909         *     with the radix indicator <tt>'0'</tt>.
0910         *
0911         *     <p> If the <tt>'0'</tt> flag is given then the output will be padded
0912         *     with leading zeros to the field width following any indication of sign.
0913         *
0914         *     <p> If <tt>'('</tt>, <tt>'+'</tt>, '&nbsp&nbsp;', or <tt>','</tt> flags
0915         *     are given then a {@link FormatFlagsConversionMismatchException} will be
0916         *     thrown.
0917         *
0918         * <tr><td valign="top"> <tt>'x'</tt>
0919         *     <td valign="top"> <tt>'&#92;u0078'</tt>
0920         *     <td> Formats the argument as an integer in base sixteen. No
0921         *     localization is applied.
0922         *
0923         *     <p> If <i>x</i> is negative then the result will be an unsigned value
0924         *     generated by adding 2<sup>n</sup> to the value where <tt>n</tt> is the
0925         *     number of bits in the type as returned by the static <tt>SIZE</tt> field
0926         *     in the {@linkplain Byte#SIZE Byte}, {@linkplain Short#SIZE Short},
0927         *     {@linkplain Integer#SIZE Integer}, or {@linkplain Long#SIZE Long}
0928         *     classes as appropriate.
0929         *
0930         *     <p> If the <tt>'#'</tt> flag is given then the output will always begin
0931         *     with the radix indicator <tt>"0x"</tt>.
0932         *
0933         *     <p> If the <tt>'0'</tt> flag is given then the output will be padded to
0934         *     the field width with leading zeros after the radix indicator or sign (if
0935         *     present).
0936         *
0937         *     <p> If <tt>'('</tt>, <tt>'&nbsp;&nbsp;'</tt>, <tt>'+'</tt>, or
0938         *     <tt>','</tt> flags are given then a {@link
0939         *     FormatFlagsConversionMismatchException} will be thrown.
0940         *
0941         * <tr><td valign="top"> <tt>'X'</tt>
0942         *     <td valign="top"> <tt>'&#92;u0058'</tt>
0943         *     <td> The upper-case variant of <tt>'x'</tt>.  The entire string
0944         *     representing the number will be converted to {@linkplain
0945         *     String#toUpperCase upper case} including the <tt>'x'</tt> (if any) and
0946         *     all hexadecimal digits <tt>'a'</tt> - <tt>'f'</tt>
0947         *     (<tt>'&#92;u0061'</tt> -  <tt>'&#92;u0066'</tt>).
0948         *
0949         * </table>
0950         *
0951         * <p> If the conversion is <tt>'o'</tt>, <tt>'x'</tt>, or <tt>'X'</tt> and
0952         * both the <tt>'#'</tt> and the <tt>'0'</tt> flags are given, then result will
0953         * contain the radix indicator (<tt>'0'</tt> for octal and <tt>"0x"</tt> or
0954         * <tt>"0X"</tt> for hexadecimal), some number of zeros (based on the width),
0955         * and the value.
0956         *
0957         * <p> If the <tt>'-'</tt> flag is not given, then the space padding will occur
0958         * before the sign.
0959         *
0960         * <p> The following <a name="intFlags">flags</a> apply to numeric integral
0961         * conversions:
0962         *
0963         * <table cellpadding=5 summary="intFlags">
0964         *
0965         * <tr><td valign="top"> <tt>'+'</tt>
0966         *     <td valign="top"> <tt>'&#92;u002b'</tt>
0967         *     <td> Requires the output to include a positive sign for all positive
0968         *     numbers.  If this flag is not given then only negative values will
0969         *     include a sign.
0970         *
0971         *     <p> If both the <tt>'+'</tt> and <tt>'&nbsp;&nbsp;'</tt> flags are given
0972         *     then an {@link IllegalFormatFlagsException} will be thrown.
0973         *
0974         * <tr><td valign="top"> <tt>'&nbsp;&nbsp;'</tt>
0975         *     <td valign="top"> <tt>'&#92;u0020'</tt>
0976         *     <td> Requires the output to include a single extra space
0977         *     (<tt>'&#92;u0020'</tt>) for non-negative values.
0978         *
0979         *     <p> If both the <tt>'+'</tt> and <tt>'&nbsp;&nbsp;'</tt> flags are given
0980         *     then an {@link IllegalFormatFlagsException} will be thrown.
0981         *
0982         * <tr><td valign="top"> <tt>'0'</tt>
0983         *     <td valign="top"> <tt>'&#92;u0030'</tt>
0984         *     <td> Requires the output to be padded with leading {@linkplain
0985         *     java.text.DecimalFormatSymbols#getZeroDigit zeros} to the minimum field
0986         *     width following any sign or radix indicator except when converting NaN
0987         *     or infinity.  If the width is not provided, then a {@link
0988         *     MissingFormatWidthException} will be thrown.
0989         *
0990         *     <p> If both the <tt>'-'</tt> and <tt>'0'</tt> flags are given then an
0991         *     {@link IllegalFormatFlagsException} will be thrown.
0992         *
0993         * <tr><td valign="top"> <tt>','</tt>
0994         *     <td valign="top"> <tt>'&#92;u002c'</tt>
0995         *     <td> Requires the output to include the locale-specific {@linkplain
0996         *     java.text.DecimalFormatSymbols#getGroupingSeparator group separators} as
0997         *     described in the <a href="#l10n group">"group" section</a> of the
0998         *     localization algorithm.
0999         *
1000         * <tr><td valign="top"> <tt>'('</tt>
1001         *     <td valign="top"> <tt>'&#92;u0028'</tt>
1002         *     <td> Requires the output to prepend a <tt>'('</tt>
1003         *     (<tt>'&#92;u0028'</tt>) and append a <tt>')'</tt>
1004         *     (<tt>'&#92;u0029'</tt>) to negative values.
1005         *
1006         * </table>
1007         *
1008         * <p> If no <a name="intdFlags">flags</a> are given the default formatting is
1009         * as follows:
1010         *
1011         * <ul>
1012         *
1013         * <li> The output is right-justified within the <tt>width</tt>
1014         *
1015         * <li> Negative numbers begin with a <tt>'-'</tt> (<tt>'&#92;u002d'</tt>)
1016         *
1017         * <li> Positive numbers and zero do not include a sign or extra leading
1018         * space
1019         *
1020         * <li> No grouping separators are included
1021         *
1022         * </ul>
1023         *
1024         * <p> The <a name="intWidth">width</a> is the minimum number of characters to
1025         * be written to the output.  This includes any signs, digits, grouping
1026         * separators, radix indicator, and parentheses.  If the length of the
1027         * converted value is less than the width then the output will be padded by
1028         * spaces (<tt>'&#92;u0020'</tt>) until the total number of characters equals
1029         * width.  The padding is on the left by default.  If <tt>'-'</tt> flag is
1030         * given then the padding will be on the right.  If width is not specified then
1031         * there is no minimum.
1032         *
1033         * <p> The precision is not applicable.  If precision is specified then an
1034         * {@link IllegalFormatPrecisionException} will be thrown.
1035         *
1036         * <p><a name="dnbint"><b> BigInteger </b></a>
1037         *
1038         * <p> The following conversions may be applied to {@link
1039         * java.math.BigInteger}.
1040         *
1041         * <table cellpadding=5 summary="BIntConv">
1042         *
1043         * <tr><td valign="top"> <tt>'d'</tt>
1044         *     <td valign="top"> <tt>'&#92;u0054'</tt>
1045         *     <td> Requires the output to be formatted as a decimal integer. The <a
1046         *     href="#l10n algorithm">localization algorithm</a> is applied.
1047         *
1048         *     <p> If the <tt>'#'</tt> flag is given {@link
1049         *     FormatFlagsConversionMismatchException} will be thrown.
1050         *
1051         * <tr><td valign="top"> <tt>'o'</tt>
1052         *     <td valign="top"> <tt>'&#92;u006f'</tt>
1053         *     <td> Requires the output to be formatted as an integer in base eight.
1054         *     No localization is applied.
1055         *
1056         *     <p> If <i>x</i> is negative then the result will be a signed value
1057         *     beginning with <tt>'-'</tt> (<tt>'&#92;u002d'</tt>).  Signed output is
1058         *     allowed for this type because unlike the primitive types it is not
1059         *     possible to create an unsigned equivalent without assuming an explicit
1060         *     data-type size.
1061         *
1062         *     <p> If <i>x</i> is positive or zero and the <tt>'+'</tt> flag is given
1063         *     then the result will begin with <tt>'+'</tt> (<tt>'&#92;u002b'</tt>).
1064         *
1065         *     <p> If the <tt>'#'</tt> flag is given then the output will always begin
1066         *     with <tt>'0'</tt> prefix.
1067         *
1068         *     <p> If the <tt>'0'</tt> flag is given then the output will be padded
1069         *     with leading zeros to the field width following any indication of sign.
1070         *
1071         *     <p> If the <tt>','</tt> flag is given then a {@link
1072         *     FormatFlagsConversionMismatchException} will be thrown.
1073         *
1074         * <tr><td valign="top"> <tt>'x'</tt>
1075         *     <td valign="top"> <tt>'&#92;u0078'</tt>
1076         *     <td> Requires the output to be formatted as an integer in base
1077         *     sixteen.  No localization is applied.
1078         *
1079         *     <p> If <i>x</i> is negative then the result will be a signed value
1080         *     beginning with <tt>'-'</tt> (<tt>'&#92;u002d'</tt>).  Signed output is
1081         *     allowed for this type because unlike the primitive types it is not
1082         *     possible to create an unsigned equivalent without assuming an explicit
1083         *     data-type size.
1084         *
1085         *     <p> If <i>x</i> is positive or zero and the <tt>'+'</tt> flag is given
1086         *     then the result will begin with <tt>'+'</tt> (<tt>'&#92;u002b'</tt>).
1087         *
1088         *     <p> If the <tt>'#'</tt> flag is given then the output will always begin
1089         *     with the radix indicator <tt>"0x"</tt>.
1090         *
1091         *     <p> If the <tt>'0'</tt> flag is given then the output will be padded to
1092         *     the field width with leading zeros after the radix indicator or sign (if
1093         *     present).
1094         *
1095         *     <p> If the <tt>','</tt> flag is given then a {@link
1096         *     FormatFlagsConversionMismatchException} will be thrown.
1097         *
1098         * <tr><td valign="top"> <tt>'X'</tt>
1099         *     <td valign="top"> <tt>'&#92;u0058'</tt>
1100         *     <td> The upper-case variant of <tt>'x'</tt>.  The entire string
1101         *     representing the number will be converted to {@linkplain
1102         *     String#toUpperCase upper case} including the <tt>'x'</tt> (if any) and
1103         *     all hexadecimal digits <tt>'a'</tt> - <tt>'f'</tt>
1104         *     (<tt>'&#92;u0061'</tt> - <tt>'&#92;u0066'</tt>).
1105         *
1106         * </table>
1107         *
1108         * <p> If the conversion is <tt>'o'</tt>, <tt>'x'</tt>, or <tt>'X'</tt> and
1109         * both the <tt>'#'</tt> and the <tt>'0'</tt> flags are given, then result will
1110         * contain the base indicator (<tt>'0'</tt> for octal and <tt>"0x"</tt> or
1111         * <tt>"0X"</tt> for hexadecimal), some number of zeros (based on the width),
1112         * and the value.
1113         *
1114         * <p> If the <tt>'0'</tt> flag is given and the value is negative, then the
1115         * zero padding will occur after the sign.
1116         *
1117         * <p> If the <tt>'-'</tt> flag is not given, then the space padding will occur
1118         * before the sign.
1119         *
1120         * <p> All <a href="#intFlags">flags</a> defined for Byte, Short, Integer, and
1121         * Long apply.  The <a href="#intdFlags">default behavior</a> when no flags are
1122         * given is the same as for Byte, Short, Integer, and Long.
1123         *
1124         * <p> The specification of <a href="#intWidth">width</a> is the same as
1125         * defined for Byte, Short, Integer, and Long.
1126         *
1127         * <p> The precision is not applicable.  If precision is specified then an
1128         * {@link IllegalFormatPrecisionException} will be thrown.
1129         *
1130         * <p><a name="dndec"><b> Float and Double</b></a>
1131         *
1132         * <p> The following conversions may be applied to <tt>float</tt>, {@link
1133         * Float}, <tt>double</tt> and {@link Double}.
1134         *
1135         * <table cellpadding=5 summary="floatConv">
1136         *
1137         * <tr><td valign="top"> <tt>'e'</tt>
1138         *     <td valign="top"> <tt>'&#92;u0065'</tt>
1139         *     <td> Requires the output to be formatted using <a
1140         *     name="scientific">computerized scientific notation</a>.  The <a
1141         *     href="#l10n algorithm">localization algorithm</a> is applied.
1142         *
1143         *     <p> The formatting of the magnitude <i>m</i> depends upon its value.
1144         *
1145         *     <p> If <i>m</i> is NaN or infinite, the literal strings "NaN" or
1146         *     "Infinity", respectively, will be output.  These values are not
1147         *     localized.
1148         *
1149         *     <p> If <i>m</i> is positive-zero or negative-zero, then the exponent
1150         *     will be <tt>"+00"</tt>.
1151         *
1152         *     <p> Otherwise, the result is a string that represents the sign and
1153         *     magnitude (absolute value) of the argument.  The formatting of the sign
1154         *     is described in the <a href="#l10n algorithm">localization
1155         *     algorithm</a>. The formatting of the magnitude <i>m</i> depends upon its
1156         *     value.
1157         *
1158         *     <p> Let <i>n</i> be the unique integer such that 10<sup><i>n</i></sup>
1159         *     &lt;= <i>m</i> &lt; 10<sup><i>n</i>+1</sup>; then let <i>a</i> be the
1160         *     mathematically exact quotient of <i>m</i> and 10<sup><i>n</i></sup> so
1161         *     that 1 &lt;= <i>a</i> &lt; 10. The magnitude is then represented as the
1162         *     integer part of <i>a</i>, as a single decimal digit, followed by the
1163         *     decimal separator followed by decimal digits representing the fractional
1164         *     part of <i>a</i>, followed by the exponent symbol <tt>'e'</tt>
1165         *     (<tt>'&#92;u0065'</tt>), followed by the sign of the exponent, followed
1166         *     by a representation of <i>n</i> as a decimal integer, as produced by the
1167         *     method {@link Long#toString(long, int)}, and zero-padded to include at
1168         *     least two digits.
1169         *
1170         *     <p> The number of digits in the result for the fractional part of
1171         *     <i>m</i> or <i>a</i> is equal to the precision.  If the precision is not
1172         *     specified then the default value is <tt>6</tt>. If the precision is less
1173         *     than the number of digits which would appear after the decimal point in
1174         *     the string returned by {@link Float#toString(float)} or {@link
1175         *     Double#toString(double)} respectively, then the value will be rounded
1176         *     using the {@linkplain java.math.BigDecimal#ROUND_HALF_UP round half up
1177         *     algorithm}.  Otherwise, zeros may be appended to reach the precision.
1178         *     For a canonical representation of the value, use {@link
1179         *     Float#toString(float)} or {@link Double#toString(double)} as
1180         *     appropriate.
1181         *
1182         *     <p>If the <tt>','</tt> flag is given, then an {@link
1183         *     FormatFlagsConversionMismatchException} will be thrown.
1184         *
1185         * <tr><td valign="top"> <tt>'E'</tt>
1186         *     <td valign="top"> <tt>'&#92;u0045'</tt>
1187         *     <td> The upper-case variant of <tt>'e'</tt>.  The exponent symbol
1188         *     will be <tt>'E'</tt> (<tt>'&#92;u0045'</tt>).
1189         *
1190         * <tr><td valign="top"> <tt>'g'</tt>
1191         *     <td valign="top"> <tt>'&#92;u0067'</tt>
1192         *     <td> Requires the output to be formatted in general scientific notation
1193         *     as described below. The <a href="#l10n algorithm">localization
1194         *     algorithm</a> is applied.
1195         *
1196         *     <p> After rounding for the precision, the formatting of the resulting
1197         *     magnitude <i>m</i> depends on its value.
1198         *
1199         *     <p> If <i>m</i> is greater than or equal to 10<sup>-4</sup> but less
1200         *     than 10<sup>precision</sup> then it is represented in <i><a
1201         *     href="#decimal">decimal format</a></i>.
1202         *
1203         *     <p> If <i>m</i> is less than 10<sup>-4</sup> or greater than or equal to
1204         *     10<sup>precision</sup>, then it is represented in <i><a
1205         *     href="#scientific">computerized scientific notation</a></i>.
1206         *
1207         *     <p> The total number of significant digits in <i>m</i> is equal to the
1208         *     precision.  If the precision is not specified, then the default value is
1209         *     <tt>6</tt>.  If the precision is <tt>0</tt>, then it is taken to be
1210         *     <tt>1</tt>.
1211         *
1212         *     <p> If the <tt>'#'</tt> flag is given then an {@link
1213         *     FormatFlagsConversionMismatchException} will be thrown.
1214         *
1215         * <tr><td valign="top"> <tt>'G'</tt>
1216         *     <td valign="top"> <tt>'&#92;u0047'</tt>
1217         *     <td> The upper-case variant of <tt>'g'</tt>.
1218         *
1219         * <tr><td valign="top"> <tt>'f'</tt>
1220         *     <td valign="top"> <tt>'&#92;u0066'</tt>
1221         *     <td> Requires the output to be formatted using <a name="decimal">decimal
1222         *     format</a>.  The <a href="#l10n algorithm">localization algorithm</a> is
1223         *     applied.
1224         *
1225         *     <p> The result is a string that represents the sign and magnitude
1226         *     (absolute value) of the argument.  The formatting of the sign is
1227         *     described in the <a href="#l10n algorithm">localization
1228         *     algorithm</a>. The formatting of the magnitude <i>m</i> depends upon its
1229         *     value.
1230         *
1231         *     <p> If <i>m</i> NaN or infinite, the literal strings "NaN" or
1232         *     "Infinity", respectively, will be output.  These values are not
1233         *     localized.
1234         *
1235         *     <p> The magnitude is formatted as the integer part of <i>m</i>, with no
1236         *     leading zeroes, followed by the decimal separator followed by one or
1237         *     more decimal digits representing the fractional part of <i>m</i>.
1238         *
1239         *     <p> The number of digits in the result for the fractional part of
1240         *     <i>m</i> or <i>a</i> is equal to the precision.  If the precision is not
1241         *     specified then the default value is <tt>6</tt>. If the precision is less
1242         *     than the number of digits which would appear after the decimal point in
1243         *     the string returned by {@link Float#toString(float)} or {@link
1244         *     Double#toString(double)} respectively, then the value will be rounded
1245         *     using the {@linkplain java.math.BigDecimal#ROUND_HALF_UP round half up
1246         *     algorithm}.  Otherwise, zeros may be appended to reach the precision.
1247         *     For a canonical representation of the value,use {@link
1248         *     Float#toString(float)} or {@link Double#toString(double)} as
1249         *     appropriate.
1250         *
1251         * <tr><td valign="top"> <tt>'a'</tt>
1252         *     <td valign="top"> <tt>'&#92;u0061'</tt>
1253         *     <td> Requires the output to be formatted in hexadecimal exponential
1254         *     form.  No localization is applied.
1255         *
1256         *     <p> The result is a string that represents the sign and magnitude
1257         *     (absolute value) of the argument <i>x</i>.
1258         *
1259         *     <p> If <i>x</i> is negative or a negative-zero value then the result
1260         *     will begin with <tt>'-'</tt> (<tt>'&#92;u002d'</tt>).
1261         *
1262         *     <p> If <i>x</i> is positive or a positive-zero value and the
1263         *     <tt>'+'</tt> flag is given then the result will begin with <tt>'+'</tt>
1264         *     (<tt>'&#92;u002b'</tt>).
1265         *
1266         *     <p> The formatting of the magnitude <i>m</i> depends upon its value.
1267         *
1268         *     <ul>
1269         *
1270         *     <li> If the value is NaN or infinite, the literal strings "NaN" or
1271         *     "Infinity", respectively, will be output.
1272         *
1273         *     <li> If <i>m</i> is zero then it is represented by the string
1274         *     <tt>"0x0.0p0"</tt>.
1275         *
1276         *     <li> If <i>m</i> is a <tt>double</tt> value with a normalized
1277         *     representation then substrings are used to represent the significand and
1278         *     exponent fields.  The significand is represented by the characters
1279         *     <tt>"0x1."</tt> followed by the hexadecimal representation of the rest
1280         *     of the significand as a fraction.  The exponent is represented by
1281         *     <tt>'p'</tt> (<tt>'&#92;u0070'</tt>) followed by a decimal string of the
1282         *     unbiased exponent as if produced by invoking {@link
1283         *     Integer#toString(int) Integer.toString} on the exponent value.
1284         *
1285         *     <li> If <i>m</i> is a <tt>double</tt> value with a subnormal
1286         *     representation then the significand is represented by the characters
1287         *     <tt>'0x0.'</tt> followed by the hexadecimal representation of the rest
1288         *     of the significand as a fraction.  The exponent is represented by
1289         *     <tt>'p-1022'</tt>.  Note that there must be at least one nonzero digit
1290         *     in a subnormal significand.
1291         *
1292         *     </ul>
1293         *
1294         *     <p> If the <tt>'('</tt> or <tt>','</tt> flags are given, then a {@link
1295         *     FormatFlagsConversionMismatchException} will be thrown.
1296         *
1297         * <tr><td valign="top"> <tt>'A'</tt>
1298         *     <td valign="top"> <tt>'&#92;u0041'</tt>
1299         *     <td> The upper-case variant of <tt>'a'</tt>.  The entire string
1300         *     representing the number will be converted to upper case including the
1301         *     <tt>'x'</tt> (<tt>'&#92;u0078'</tt>) and <tt>'p'</tt>
1302         *     (<tt>'&#92;u0070'</tt> and all hexadecimal digits <tt>'a'</tt> -
1303         *     <tt>'f'</tt> (<tt>'&#92;u0061'</tt> - <tt>'&#92;u0066'</tt>).
1304         *
1305         * </table>
1306         *
1307         * <p> All <a href="#intFlags">flags</a> defined for Byte, Short, Integer, and
1308         * Long apply.
1309         *
1310         * <p> If the <tt>'#'</tt> flag is given, then the decimal separator will
1311         * always be present.
1312         *
1313         * <p> If no <a name="floatdFlags">flags</a> are given the default formatting
1314         * is as follows:
1315         *
1316         * <ul>
1317         *
1318         * <li> The output is right-justified within the <tt>width</tt>
1319         *
1320         * <li> Negative numbers begin with a <tt>'-'</tt>
1321         *
1322         * <li> Positive numbers and positive zero do not include a sign or extra
1323         * leading space
1324         *
1325         * <li> No grouping separators are included
1326         *
1327         * <li> The decimal separator will only appear if a digit follows it
1328         *
1329         * </ul>
1330         *
1331         * <p> The <a name="floatDWidth">width</a> is the minimum number of characters
1332         * to be written to the output.  This includes any signs, digits, grouping
1333         * separators, decimal separators, exponential symbol, radix indicator,
1334         * parentheses, and strings representing infinity and NaN as applicable.  If
1335         * the length of the converted value is less than the width then the output
1336         * will be padded by spaces (<tt>'&#92;u0020'</tt>) until the total number of
1337         * characters equals width.  The padding is on the left by default.  If the
1338         * <tt>'-'</tt> flag is given then the padding will be on the right.  If width
1339         * is not specified then there is no minimum.
1340         *
1341         * <p> If the <a name="floatDPrec">conversion</a> is <tt>'e'</tt>,
1342         * <tt>'E'</tt> or <tt>'f'</tt>, then the precision is the number of digits
1343         * after the decimal separator.  If the precision is not specified, then it is
1344         * assumed to be <tt>6</tt>.
1345         *
1346         * <p> If the conversion is <tt>'g'</tt> or <tt>'G'</tt>, then the precision is
1347         * the total number of significant digits in the resulting magnitude after
1348         * rounding.  If the precision is not specified, then the default value is
1349         * <tt>6</tt>.  If the precision is <tt>0</tt>, then it is taken to be
1350         * <tt>1</tt>.
1351         *
1352         * <p> If the conversion is <tt>'a'</tt> or <tt>'A'</tt>, then the precision
1353         * is the number of hexadecimal digits after the decimal separator.  If the
1354         * precision is not provided, then all of the digits as returned by {@link
1355         * Double#toHexString(double)} will be output.
1356         *
1357         * <p><a name="dndec"><b> BigDecimal </b></a>
1358         *
1359         * <p> The following conversions may be applied {@link java.math.BigDecimal
1360         * BigDecimal}.
1361         *
1362         * <table cellpadding=5 summary="floatConv">
1363         *
1364         * <tr><td valign="top"> <tt>'e'</tt>
1365         *     <td valign="top"> <tt>'&#92;u0065'</tt>
1366         *     <td> Requires the output to be formatted using <a
1367         *     name="scientific">computerized scientific notation</a>.  The <a
1368         *     href="#l10n algorithm">localization algorithm</a> is applied.
1369         *
1370         *     <p> The formatting of the magnitude <i>m</i> depends upon its value.
1371         *
1372         *     <p> If <i>m</i> is positive-zero or negative-zero, then the exponent
1373         *     will be <tt>"+00"</tt>.
1374         *
1375         *     <p> Otherwise, the result is a string that represents the sign and
1376         *     magnitude (absolute value) of the argument.  The formatting of the sign
1377         *     is described in the <a href="#l10n algorithm">localization
1378         *     algorithm</a>. The formatting of the magnitude <i>m</i> depends upon its
1379         *     value.
1380         *
1381         *     <p> Let <i>n</i> be the unique integer such that 10<sup><i>n</i></sup>
1382         *     &lt;= <i>m</i> &lt; 10<sup><i>n</i>+1</sup>; then let <i>a</i> be the
1383         *     mathematically exact quotient of <i>m</i> and 10<sup><i>n</i></sup> so
1384         *     that 1 &lt;= <i>a</i> &lt; 10. The magnitude is then represented as the
1385         *     integer part of <i>a</i>, as a single decimal digit, followed by the
1386         *     decimal separator followed by decimal digits representing the fractional
1387         *     part of <i>a</i>, followed by the exponent symbol <tt>'e'</tt>
1388         *     (<tt>'&#92;u0065'</tt>), followed by the sign of the exponent, followed
1389         *     by a representation of <i>n</i> as a decimal integer, as produced by the
1390         *     method {@link Long#toString(long, int)}, and zero-padded to include at
1391         *     least two digits.
1392         *
1393         *     <p> The number of digits in the result for the fractional part of
1394         *     <i>m</i> or <i>a</i> is equal to the precision.  If the precision is not
1395         *     specified then the default value is <tt>6</tt>.  If the precision is
1396         *     less than the number of digits which would appear after the decimal
1397         *     point in the string returned by {@link Float#toString(float)} or {@link
1398         *     Double#toString(double)} respectively, then the value will be rounded
1399         *     using the {@linkplain java.math.BigDecimal#ROUND_HALF_UP round half up
1400         *     algorithm}.  Otherwise, zeros may be appended to reach the precision.
1401         *     For a canonical representation of the value, use {@link
1402         *     BigDecimal#toString()}.
1403         *
1404         *     <p> If the <tt>','</tt> flag is given, then an {@link
1405         *     FormatFlagsConversionMismatchException} will be thrown.
1406         *
1407         * <tr><td valign="top"> <tt>'E'</tt>
1408         *     <td valign="top"> <tt>'&#92;u0045'</tt>
1409         *     <td> The upper-case variant of <tt>'e'</tt>.  The exponent symbol
1410         *     will be <tt>'E'</tt> (<tt>'&#92;u0045'</tt>).
1411         *
1412         * <tr><td valign="top"> <tt>'g'</tt>
1413         *     <td valign="top"> <tt>'&#92;u0067'</tt>
1414         *     <td> Requires the output to be formatted in general scientific notation
1415         *     as described below. The <a href="#l10n algorithm">localization
1416         *     algorithm</a> is applied.
1417         *
1418         *     <p> After rounding for the precision, the formatting of the resulting
1419         *     magnitude <i>m</i> depends on its value.
1420         *
1421         *     <p> If <i>m</i> is greater than or equal to 10<sup>-4</sup> but less
1422         *     than 10<sup>precision</sup> then it is represented in <i><a
1423         *     href="#decimal">decimal format</a></i>.
1424         *
1425         *     <p> If <i>m</i> is less than 10<sup>-4</sup> or greater than or equal to
1426         *     10<sup>precision</sup>, then it is represented in <i><a
1427         *     href="#scientific">computerized scientific notation</a></i>.
1428         *
1429         *     <p> The total number of significant digits in <i>m</i> is equal to the
1430         *     precision.  If the precision is not specified, then the default value is
1431         *     <tt>6</tt>.  If the precision is <tt>0</tt>, then it is taken to be
1432         *     <tt>1</tt>.
1433         *
1434         *     <p> If the <tt>'#'</tt> flag is given then an {@link
1435         *     FormatFlagsConversionMismatchException} will be thrown.
1436         *
1437         * <tr><td valign="top"> <tt>'G'</tt>
1438         *     <td valign="top"> <tt>'&#92;u0047'</tt>
1439         *     <td> The upper-case variant of <tt>'g'</tt>.
1440         *
1441         * <tr><td valign="top"> <tt>'f'</tt>
1442         *     <td valign="top"> <tt>'&#92;u0066'</tt>
1443         *     <td> Requires the output to be formatted using <a name="decimal">decimal
1444         *     format</a>.  The <a href="#l10n algorithm">localization algorithm</a> is
1445         *     applied.
1446         *
1447         *     <p> The result is a string that represents the sign and magnitude
1448         *     (absolute value) of the argument.  The formatting of the sign is
1449         *     described in the <a href="#l10n algorithm">localization
1450         *     algorithm</a>. The formatting of the magnitude <i>m</i> depends upon its
1451         *     value.
1452         *
1453         *     <p> The magnitude is formatted as the integer part of <i>m</i>, with no
1454         *     leading zeroes, followed by the decimal separator followed by one or
1455         *     more decimal digits representing the fractional part of <i>m</i>.
1456         *
1457         *     <p> The number of digits in the result for the fractional part of
1458         *     <i>m</i> or <i>a</i> is equal to the precision.  If the precision is not
1459         *     specified then the default value is <tt>6</tt>.  If the precision is
1460         *     less than the number of digits which would appear after the decimal
1461         *     point in the string returned by {@link Float#toString(float)} or {@link
1462         *     Double#toString(double)} respectively, then the value will be rounded
1463         *     using the {@linkplain java.math.BigDecimal#ROUND_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         * </table>
1469         *
1470         * <p> All <a href="#intFlags">flags</a> defined for Byte, Short, Integer, and
1471         * Long apply.
1472         *
1473         * <p> If the <tt>'#'</tt> flag is given, then the decimal separator will
1474         * always be present.
1475         *
1476         * <p> The <a href="#floatdFlags">default behavior</a> when no flags are
1477         * given is the same as for Float and Double.
1478         *
1479         * <p> The specification of <a href="#floatDWidth">width</a> and <a
1480         * href="#floatDPrec">precision</a> is the same as defined for Float and
1481         * Double.
1482         *
1483         * <h4><a name="ddt">Date/Time</a></h4>
1484         *
1485         * <p> This conversion may be applied to <tt>long</tt>, {@link Long}, {@link
1486         * Calendar}, and {@link Date}.
1487         *
1488         * <table cellpadding=5 summary="DTConv">
1489         *
1490         * <tr><td valign="top"> <tt>'t'</tt>
1491         *     <td valign="top"> <tt>'&#92;u0074'</tt>
1492         *     <td> Prefix for date and time conversion characters.
1493         * <tr><td valign="top"> <tt>'T'</tt>
1494         *     <td valign="top"> <tt>'&#92;u0054'</tt>
1495         *     <td> The upper-case variant of <tt>'t'</tt>.
1496         *
1497         * </table>
1498         *
1499         * <p> The following date and time conversion character suffixes are defined
1500         * for the <tt>'t'</tt> and <tt>'T'</tt> conversions.  The types are similar to
1501         * but not completely identical to those defined by GNU <tt>date</tt> and
1502         * POSIX <tt>strftime(3c)</tt>.  Additional conversion types are provided to
1503         * access Java-specific functionality (e.g. <tt>'L'</tt> for milliseconds
1504         * within the second).
1505         *
1506         * <p> The following conversion characters are used for formatting times:
1507         *
1508         * <table cellpadding=5 summary="time">
1509         *
1510         * <tr><td valign="top"> <tt>'H'</tt>
1511         *     <td valign="top"> <tt>'&#92;u0048'</tt>
1512         *     <td> Hour of the day for the 24-hour clock, formatted as two digits with
1513         *     a leading zero as necessary i.e. <tt>00 - 23</tt>. <tt>00</tt>
1514         *     corresponds to midnight.
1515         *
1516         * <tr><td valign="top"><tt>'I'</tt>
1517         *     <td valign="top"> <tt>'&#92;u0049'</tt>
1518         *     <td> Hour for the 12-hour clock, formatted as two digits with a leading
1519         *     zero as necessary, i.e.  <tt>01 - 12</tt>.  <tt>01</tt> corresponds to
1520         *     one o'clock (either morning or afternoon).
1521         *
1522         * <tr><td valign="top"><tt>'k'</tt>
1523         *     <td valign="top"> <tt>'&#92;u006b'</tt>
1524         *     <td> Hour of the day for the 24-hour clock, i.e. <tt>0 - 23</tt>.
1525         *     <tt>0</tt> corresponds to midnight.
1526         *
1527         * <tr><td valign="top"><tt>'l'</tt>
1528         *     <td valign="top"> <tt>'&#92;u006c'</tt>
1529         *     <td> Hour for the 12-hour clock, i.e. <tt>1 - 12</tt>.  <tt>1</tt>
1530         *     corresponds to one o'clock (either morning or afternoon).
1531         *
1532         * <tr><td valign="top"><tt>'M'</tt>
1533         *     <td valign="top"> <tt>'&#92;u004d'</tt>
1534         *     <td> Minute within the hour formatted as two digits with a leading zero
1535         *     as necessary, i.e.  <tt>00 - 59</tt>.
1536         *
1537         * <tr><td valign="top"><tt>'S'</tt>
1538         *     <td valign="top"> <tt>'&#92;u0053'</tt>
1539         *     <td> Seconds within the minute, formatted as two digits with a leading
1540         *     zero as necessary, i.e. <tt>00 - 60</tt> ("<tt>60</tt>" is a special
1541         *     value required to support leap seconds).
1542         *
1543         * <tr><td valign="top"><tt>'L'</tt>
1544         *     <td valign="top"> <tt>'&#92;u004c'</tt>
1545         *     <td> Millisecond within the second formatted as three digits with
1546         *     leading zeros as necessary, i.e. <tt>000 - 999</tt>.
1547         *
1548         * <tr><td valign="top"><tt>'N'</tt>
1549         *     <td valign="top"> <tt>'&#92;u004e'</tt>
1550         *     <td> Nanosecond within the second, formatted as nine digits with leading
1551         *     zeros as necessary, i.e. <tt>000000000 - 999999999</tt>.  The precision
1552         *     of this value is limited by the resolution of the underlying operating
1553         *     system or hardware.
1554         *
1555         * <tr><td valign="top"><tt>'p'</tt>
1556         *     <td valign="top"> <tt>'&#92;u0070'</tt>
1557         *     <td> Locale-specific {@linkplain
1558         *     java.text.DateFormatSymbols#getAmPmStrings morning or afternoon} marker
1559         *     in lower case, e.g."<tt>am</tt>" or "<tt>pm</tt>".  Use of the
1560         *     conversion prefix <tt>'T'</tt> forces this output to upper case.  (Note
1561         *     that <tt>'p'</tt> produces lower-case output.  This is different from
1562         *     GNU <tt>date</tt> and POSIX <tt>strftime(3c)</tt> which produce
1563         *     upper-case output.)
1564         *
1565         * <tr><td valign="top"><tt>'z'</tt>
1566         *     <td valign="top"> <tt>'&#92;u007a'</tt>
1567         *     <td> <a href="http://www.ietf.org/rfc/rfc0822.txt">RFC&nbsp;822</a>
1568         *     style numeric time zone offset from GMT, e.g. <tt>-0800</tt>.
1569         *
1570         * <tr><td valign="top"><tt>'Z'</tt>
1571         *     <td valign="top"> <tt>'&#92;u005a'</tt>
1572         *     <td> A string representing the abbreviation for the time zone.
1573         *
1574         * <tr><td valign="top"><tt>'s'</tt>
1575         *     <td valign="top"> <tt>'&#92;u0073'</tt>
1576         *     <td> Seconds since the beginning of the epoch starting at 1 January 1970
1577         *     <tt>00:00:00</tt> UTC, i.e. <tt>Long.MIN_VALUE/1000</tt> to
1578         *     <tt>Long.MAX_VALUE/1000</tt>.
1579         *
1580         * <tr><td valign="top"><tt>'Q'</tt>
1581         *     <td valign="top"> <tt>'&#92;u004f'</tt>
1582         *     <td> Milliseconds since the beginning of the epoch starting at 1 January
1583         *     1970 <tt>00:00:00</tt> UTC, i.e. <tt>Long.MIN_VALUE</tt> to
1584         *     <tt>Long.MAX_VALUE</tt>. The precision of this value is limited by
1585         *     the resolution of the underlying operating system or hardware.
1586         *
1587         * </table>
1588         *
1589         * <p> The following conversion characters are used for formatting dates:
1590         *
1591         * <table cellpadding=5 summary="date">
1592         *
1593         * <tr><td valign="top"><tt>'B'</tt>
1594         *     <td valign="top"> <tt>'&#92;u0042'</tt>
1595         *     <td> Locale-specific {@linkplain java.text.DateFormatSymbols#getMonths
1596         *     full month name}, e.g. <tt>"January"</tt>, <tt>"February"</tt>.
1597         *
1598         * <tr><td valign="top"><tt>'b'</tt>
1599         *     <td valign="top"> <tt>'&#92;u0062'</tt>
1600         *     <td> Locale-specific {@linkplain
1601         *     java.text.DateFormatSymbols#getShortMonths abbreviated month name},
1602         *     e.g. <tt>"Jan"</tt>, <tt>"Feb"</tt>.
1603         *
1604         * <tr><td valign="top"><tt>'h'</tt>
1605         *     <td valign="top"> <tt>'&#92;u0068'</tt>
1606         *     <td> Same as <tt>'b'</tt>.
1607         *
1608         * <tr><td valign="top"><tt>'A'</tt>
1609         *     <td valign="top"> <tt>'&#92;u0041'</tt>
1610         *     <td> Locale-specific full name of the {@linkplain
1611         *     java.text.DateFormatSymbols#getWeekdays day of the week},
1612         *     e.g. <tt>"Sunday"</tt>, <tt>"Monday"</tt>
1613         *
1614         * <tr><td valign="top"><tt>'a'</tt>
1615         *     <td valign="top"> <tt>'&#92;u0061'</tt>
1616         *     <td> Locale-specific short name of the {@linkplain
1617         *     java.text.DateFormatSymbols#getShortWeekdays day of the week},
1618         *     e.g. <tt>"Sun"</tt>, <tt>"Mon"</tt>
1619         *
1620         * <tr><td valign="top"><tt>'C'</tt>
1621         *     <td valign="top"> <tt>'&#92;u0043'</tt>
1622         *     <td> Four-digit year divided by <tt>100</tt>, formatted as two digits
1623         *     with leading zero as necessary, i.e. <tt>00 - 99</tt>
1624         *
1625         * <tr><td valign="top"><tt>'Y'</tt>
1626         *     <td valign="top"> <tt>'&#92;u0059'</tt> <td> Year, formatted to at least
1627         *     four digits with leading zeros as necessary, e.g. <tt>0092</tt> equals
1628         *     <tt>92</tt> CE for the Gregorian calendar.
1629         *
1630         * <tr><td valign="top"><tt>'y'</tt>
1631         *     <td valign="top"> <tt>'&#92;u0079'</tt>
1632         *     <td> Last two digits of the year, formatted with leading zeros as
1633         *     necessary, i.e. <tt>00 - 99</tt>.
1634         *
1635         * <tr><td valign="top"><tt>'j'</tt>
1636         *     <td valign="top"> <tt>'&#92;u006a'</tt>
1637         *     <td> Day of year, formatted as three digits with leading zeros as
1638         *     necessary, e.g. <tt>001 - 366</tt> for the Gregorian calendar.
1639         *     <tt>001</tt> corresponds to the first day of the year.
1640         *
1641         * <tr><td valign="top"><tt>'m'</tt>
1642         *     <td valign="top"> <tt>'&#92;u006d'</tt>
1643         *     <td> Month, formatted as two digits with leading zeros as necessary,
1644         *     i.e. <tt>01 - 13</tt>, where "<tt>01</tt>" is the first month of the
1645         *     year and ("<tt>13</tt>" is a special value required to support lunar
1646         *     calendars).
1647         *
1648         * <tr><td valign="top"><tt>'d'</tt>
1649         *     <td valign="top"> <tt>'&#92;u0064'</tt>
1650         *     <td> Day of month, formatted as two digits with leading zeros as
1651         *     necessary, i.e. <tt>01 - 31</tt>, where "<tt>01</tt>" is the first day
1652         *     of the month.
1653         *
1654         * <tr><td valign="top"><tt>'e'</tt>
1655         *     <td valign="top"> <tt>'&#92;u0065'</tt>
1656         *     <td> Day of month, formatted as two digits, i.e. <tt>1 - 31</tt> where
1657         *     "<tt>1</tt>" is the first day of the month.
1658         *
1659         * </table>
1660         *
1661         * <p> The following conversion characters are used for formatting common
1662         * date/time compositions.
1663         *
1664         * <table cellpadding=5 summary="composites">
1665         *
1666         * <tr><td valign="top"><tt>'R'</tt>
1667         *     <td valign="top"> <tt>'&#92;u0052'</tt>
1668         *     <td> Time formatted for the 24-hour clock as <tt>"%tH:%tM"</tt>
1669         *
1670         * <tr><td valign="top"><tt>'T'</tt>
1671         *     <td valign="top"> <tt>'&#92;u0054'</tt>
1672         *     <td> Time formatted for the 24-hour clock as <tt>"%tH:%tM:%tS"</tt>.
1673         *
1674         * <tr><td valign="top"><tt>'r'</tt>
1675         *     <td valign="top"> <tt>'&#92;u0072'</tt>
1676         *     <td> Time formatted for the 12-hour clock as <tt>"%tI:%tM:%tS
1677         *     %Tp"</tt>.  The location of the morning or afternoon marker
1678         *     (<tt>'%Tp'</tt>) may be locale-dependent.
1679         *
1680         * <tr><td valign="top"><tt>'D'</tt>
1681         *     <td valign="top"> <tt>'&#92;u0044'</tt>
1682         *     <td> Date formatted as <tt>"%tm/%td/%ty"</tt>.
1683         *
1684         * <tr><td valign="top"><tt>'F'</tt>
1685         *     <td valign="top"> <tt>'&#92;u0046'</tt>
1686         *     <td> <a href="http://www.w3.org/TR/NOTE-datetime">ISO&nbsp;8601</a>
1687         *     complete date formatted as <tt>"%tY-%tm-%td"</tt>.
1688         *
1689         * <tr><td valign="top"><tt>'c'</tt>
1690         *     <td valign="top"> <tt>'&#92;u0063'</tt>
1691         *     <td> Date and time formatted as <tt>"%ta %tb %td %tT %tZ %tY"</tt>,
1692         *     e.g. <tt>"Sun Jul 20 16:17:00 EDT 1969"</tt>.
1693         *
1694         * </table>
1695         *
1696         * <p> The <tt>'-'</tt> flag defined for <a href="#dFlags">General
1697         * conversions</a> applies.  If the <tt>'#'</tt> flag is given, then a {@link
1698         * FormatFlagsConversionMismatchException} will be thrown.
1699         *
1700         * <p> The <a name="dtWidth">width</a> is the minimum number of characters to
1701         * be written to the output.  If the length of the converted value is less than
1702         * the <tt>width</tt> then the output will be padded by spaces
1703         * (<tt>'&#92;u0020'</tt>) until the total number of characters equals width.
1704         * The padding is on the left by default.  If the <tt>'-'</tt> flag is given
1705         * then the padding will be on the right.  If width is not specified then there
1706         * is no minimum.
1707         *
1708         * <p> The precision is not applicable.  If the precision is specified then an
1709         * {@link IllegalFormatPrecisionException} will be thrown.
1710         *
1711         * <h4><a name="dper">Percent</a></h4>
1712         *
1713         * <p> The conversion does not correspond to any argument.
1714         *
1715         * <table cellpadding=5 summary="DTConv">
1716         *
1717         * <tr><td valign="top"><tt>'%'</tt>
1718         *     <td> The result is a literal <tt>'%'</tt> (<tt>'&#92;u0025'</tt>)
1719         *
1720         * <p> The <a name="dtWidth">width</a> is the minimum number of characters to
1721         * be written to the output including the <tt>'%'</tt>.  If the length of the
1722         * converted value is less than the <tt>width</tt> then the output will be
1723         * padded by spaces (<tt>'&#92;u0020'</tt>) until the total number of
1724         * characters equals width.  The padding is on the left.  If width is not
1725         * specified then just the <tt>'%'</tt> is output.
1726         *
1727         * <p> The <tt>'-'</tt> flag defined for <a href="#dFlags">General
1728         * conversions</a> applies.  If any other flags are provided, then a
1729         * {@link FormatFlagsConversionMismatchException} will be thrown.
1730         *
1731         * <p> The precision is not applicable.  If the precision is specified an
1732         * {@link IllegalFormatPrecisionException} will be thrown.
1733         *
1734         * </table>
1735         *
1736         * <h4><a name="dls">Line Separator</a></h4>
1737         *
1738         * <p> The conversion does not correspond to any argument.
1739         *
1740         * <table cellpadding=5 summary="DTConv">
1741         *
1742         * <tr><td valign="top"><tt>'n'</tt>
1743         *     <td> the platform-specific line separator as returned by {@link
1744         *     System#getProperty System.getProperty("line.separator")}.
1745         *
1746         * </table>
1747         *
1748         * <p> Flags, width, and precision are not applicable.  If any are provided an
1749         * {@link IllegalFormatFlagsException}, {@link IllegalFormatWidthException},
1750         * and {@link IllegalFormatPrecisionException}, respectively will be thrown.
1751         *
1752         * <h4><a name="dpos">Argument Index</a></h4>
1753         *
1754         * <p> Format specifiers can reference arguments in three ways:
1755         *
1756         * <ul>
1757         *
1758         * <li> <i>Explicit indexing</i> is used when the format specifier contains an
1759         * argument index.  The argument index is a decimal integer indicating the
1760         * position of the argument in the argument list.  The first argument is
1761         * referenced by "<tt>1$</tt>", the second by "<tt>2$</tt>", etc.  An argument
1762         * may be referenced more than once.
1763         *
1764         * <p> For example:
1765         *
1766         * <blockquote><pre>
1767         *   formatter.format("%4$s %3$s %2$s %1$s %4$s %3$s %2$s %1$s",
1768         *                    "a", "b", "c", "d")
1769         *   // -&gt; "d c b a d c b a"
1770         * </pre></blockquote>
1771         *
1772         * <li> <i>Relative indexing</i> is used when the format specifier contains a
1773         * <tt>'&lt;'</tt> (<tt>'&#92;u003c'</tt>) flag which causes the argument for
1774         * the previous format specifier to be re-used.  If there is no previous
1775         * argument, then a {@link MissingFormatArgumentException} is thrown.
1776         *
1777         * <blockquote><pre>
1778         *    formatter.format("%s %s %&lt;s %&lt;s", "a", "b", "c", "d")
1779         *    // -&gt; "a b b b"
1780         *    // "c" and "d" are ignored because they are not referenced
1781         * </pre></blockquote>
1782         *
1783         * <li> <i>Ordinary indexing</i> is used when the format specifier contains
1784         * neither an argument index nor a <tt>'&lt;'</tt> flag.  Each format specifier
1785         * which uses ordinary indexing is assigned a sequential implicit index into
1786         * argument list which is independent of the indices used by explicit or
1787         * relative indexing.
1788         *
1789         * <blockquote><pre>
1790         *   formatter.format("%s %s %s %s", "a", "b", "c", "d")
1791         *   // -&gt; "a b c d"
1792         * </pre></blockquote>
1793         *
1794         * </ul>
1795         *
1796         * <p> It is possible to have a format string which uses all forms of indexing,
1797         * for example:
1798         *
1799         * <blockquote><pre>
1800         *   formatter.format("%2$s %s %&lt;s %s", "a", "b", "c", "d")
1801         *   // -&gt; "b a a b"
1802         *   // "c" and "d" are ignored because they are not referenced
1803         * </pre></blockquote>
1804         *
1805         * <p> The maximum number of arguments is limited by the maximum dimension of a
1806         * Java array as defined by the <a
1807         * href="http://java.sun.com/docs/books/vmspec/">Java Virtual Machine
1808         * Specification</a>.  If the argument index is does not correspond to an
1809         * available argument, then a {@link MissingFormatArgumentException} is thrown.
1810         *
1811         * <p> If there are more arguments than format specifiers, the extra arguments
1812         * are ignored.
1813         *
1814         * <p> Unless otherwise specified, passing a <tt>null</tt> argument to any
1815         * method or constructor in this class will cause a {@link
1816         * NullPointerException} to be thrown.
1817         *
1818         * @author  Iris Clark
1819         * @since 1.5
1820         */
1821        public final class Formatter implements  Closeable, Flushable {
1822            private Appendable a;
1823            private Locale l;
1824
1825            private IOException lastException;
1826
1827            private char zero = '0';
1828            private static double scaleUp;
1829
1830            // 1 (sign) + 19 (max # sig digits) + 1 ('.') + 1 ('e') + 1 (sign)
1831            // + 3 (max # exp digits) + 4 (error) = 30
1832            private static final int MAX_FD_CHARS = 30;
1833
1834            // Initialize internal data.
1835            private void init(Appendable a, Locale l) {
1836                this .a = a;
1837                this .l = l;
1838                setZero();
1839            }
1840
1841            /**
1842             * Constructs a new formatter.
1843             *
1844             * <p> The destination of the formatted output is a {@link StringBuilder}
1845             * which may be retrieved by invoking {@link #out out()} and whose
1846             * current content may be converted into a string by invoking {@link
1847             * #toString toString()}.  The locale used is the {@linkplain
1848             * Locale#getDefault() default locale} for this instance of the Java
1849             * virtual machine.
1850             */
1851            public Formatter() {
1852                init(new StringBuilder(), Locale.getDefault());
1853            }
1854
1855            /**
1856             * Constructs a new formatter with the specified destination.
1857             *
1858             * <p> The locale used is the {@linkplain Locale#getDefault() default
1859             * locale} for this instance of the Java virtual machine.
1860             *
1861             * @param  a
1862             *         Destination for the formatted output.  If <tt>a</tt> is
1863             *         <tt>null</tt> then a {@link StringBuilder} will be created.
1864             */
1865            public Formatter(Appendable a) {
1866                if (a == null)
1867                    a = new StringBuilder();
1868                init(a, Locale.getDefault());
1869            }
1870
1871            /**
1872             * Constructs a new formatter with the specified locale.
1873             *
1874             * <p> The destination of the formatted output is a {@link StringBuilder}
1875             * which may be retrieved by invoking {@link #out out()} and whose current
1876             * content may be converted into a string by invoking {@link #toString
1877             * toString()}.
1878             *
1879             * @param  l
1880             *         The {@linkplain java.util.Locale locale} to apply during
1881             *         formatting.  If <tt>l</tt> is <tt>null</tt> then no localization
1882             *         is applied.
1883             */
1884            public Formatter(Locale l) {
1885                init(new StringBuilder(), l);
1886            }
1887
1888            /**
1889             * Constructs a new formatter with the specified destination and locale.
1890             *
1891             * @param  a
1892             *         Destination for the formatted output.  If <tt>a</tt> is
1893             *         <tt>null</tt> then a {@link StringBuilder} will be created.
1894             *
1895             * @param  l
1896             *         The {@linkplain java.util.Locale locale} to apply during
1897             *         formatting.  If <tt>l</tt> is <tt>null</tt> then no localization
1898             *         is applied.
1899             */
1900            public Formatter(Appendable a, Locale l) {
1901                if (a == null)
1902                    a = new StringBuilder();
1903                init(a, l);
1904            }
1905
1906            /**
1907             * Constructs a new formatter with the specified file name.
1908             *
1909             * <p> The charset used is the {@linkplain
1910             * java.nio.charset.Charset#defaultCharset() default charset} for this
1911             * instance of the Java virtual machine.
1912             *
1913             * <p> The locale used is the {@linkplain Locale#getDefault() default
1914             * locale} for this instance of the Java virtual machine.
1915             *
1916             * @param  fileName
1917             *         The name of the file to use as the destination of this
1918             *         formatter.  If the file exists then it will be truncated to
1919             *         zero size; otherwise, a new file will be created.  The output
1920             *         will be written to the file and is buffered.
1921             *
1922             * @throws  SecurityException
1923             *          If a security manager is present and {@link
1924             *          SecurityManager#checkWrite checkWrite(fileName)} denies write
1925             *          access to the file
1926             *
1927             * @throws  FileNotFoundException
1928             *          If the given file name does not denote an existing, writable
1929             *          regular file and a new regular file of that name cannot be
1930             *          created, or if some other error occurs while opening or
1931             *          creating the file
1932             */
1933            public Formatter(String fileName) throws FileNotFoundException {
1934                init(new BufferedWriter(new OutputStreamWriter(
1935                        new FileOutputStream(fileName))), Locale.getDefault());
1936            }
1937
1938            /**
1939             * Constructs a new formatter with the specified file name and charset.
1940             *
1941             * <p> The locale used is the {@linkplain Locale#getDefault default
1942             * locale} for this instance of the Java virtual machine.
1943             *
1944             * @param  fileName
1945             *         The name of the file to use as the destination of this
1946             *         formatter.  If the file exists then it will be truncated to
1947             *         zero size; otherwise, a new file will be created.  The output
1948             *         will be written to the file and is buffered.
1949             *
1950             * @param  csn
1951             *         The name of a supported {@linkplain java.nio.charset.Charset
1952             *         charset}
1953             *
1954             * @throws  FileNotFoundException
1955             *          If the given file name does not denote an existing, writable
1956             *          regular file and a new regular file of that name cannot be
1957             *          created, or if some other error occurs while opening or
1958             *          creating the file
1959             *
1960             * @throws  SecurityException
1961             *          If a security manager is present and {@link
1962             *          SecurityManager#checkWrite checkWrite(fileName)} denies write
1963             *          access to the file
1964             *
1965             * @throws  UnsupportedEncodingException
1966             *          If the named charset is not supported
1967             */
1968            public Formatter(String fileName, String csn)
1969                    throws FileNotFoundException, UnsupportedEncodingException {
1970                this (fileName, csn, Locale.getDefault());
1971            }
1972
1973            /**
1974             * Constructs a new formatter with the specified file name, charset, and
1975             * locale.
1976             *
1977             * @param  fileName
1978             *         The name of the file to use as the destination of this
1979             *         formatter.  If the file exists then it will be truncated to
1980             *         zero size; otherwise, a new file will be created.  The output
1981             *         will be written to the file and is buffered.
1982             *
1983             * @param  csn
1984             *         The name of a supported {@linkplain java.nio.charset.Charset
1985             *         charset}
1986             *
1987             * @param  l
1988             *         The {@linkplain java.util.Locale locale} to apply during
1989             *         formatting.  If <tt>l</tt> is <tt>null</tt> then no localization
1990             *         is applied.
1991             *
1992             * @throws  FileNotFoundException
1993             *          If the given file name does not denote an existing, writable
1994             *          regular file and a new regular file of that name cannot be
1995             *          created, or if some other error occurs while opening or
1996             *          creating the file
1997             *
1998             * @throws  SecurityException
1999             *          If a security manager is present and {@link
2000             *          SecurityManager#checkWrite checkWrite(fileName)} denies write
2001             *          access to the file
2002             *
2003             * @throws  UnsupportedEncodingException
2004             *          If the named charset is not supported
2005             */
2006            public Formatter(String fileName, String csn, Locale l)
2007                    throws FileNotFoundException, UnsupportedEncodingException {
2008                init(new BufferedWriter(new OutputStreamWriter(
2009                        new FileOutputStream(fileName), csn)), l);
2010            }
2011
2012            /**
2013             * Constructs a new formatter with the specified file.
2014             *
2015             * <p> The charset used is the {@linkplain
2016             * java.nio.charset.Charset#defaultCharset() default charset} for this
2017             * instance of the Java virtual machine.
2018             *
2019             * <p> The locale used is the {@linkplain Locale#getDefault() default
2020             * locale} for this instance of the Java virtual machine.
2021             *
2022             * @param  file
2023             *         The file to use as the destination of this formatter.  If the
2024             *         file exists then it will be truncated to zero size; otherwise,
2025             *         a new file will be created.  The output will be written to the
2026             *         file and is buffered.
2027             *
2028             * @throws  SecurityException
2029             *          If a security manager is present and {@link
2030             *          SecurityManager#checkWrite checkWrite(file.getPath())} denies
2031             *          write access to the file
2032             *
2033             * @throws  FileNotFoundException
2034             *          If the given file object does not denote an existing, writable
2035             *          regular file and a new regular file of that name cannot be
2036             *          created, or if some other error occurs while opening or
2037             *          creating the file
2038             */
2039            public Formatter(File file) throws FileNotFoundException {
2040                init(new BufferedWriter(new OutputStreamWriter(
2041                        new FileOutputStream(file))), Locale.getDefault());
2042            }
2043
2044            /**
2045             * Constructs a new formatter with the specified file and charset.
2046             *
2047             * <p> The locale used is the {@linkplain Locale#getDefault default
2048             * locale} for this instance of the Java virtual machine.
2049             *
2050             * @param  file
2051             *         The file to use as the destination of this formatter.  If the
2052             *         file exists then it will be truncated to zero size; otherwise,
2053             *         a new file will be created.  The output will be written to the
2054             *         file and is buffered.
2055             *
2056             * @param  csn
2057             *         The name of a supported {@linkplain java.nio.charset.Charset
2058             *         charset}
2059             *
2060             * @throws  FileNotFoundException
2061             *          If the given file object does not denote an existing, writable
2062             *          regular file and a new regular file of that name cannot be
2063             *          created, or if some other error occurs while opening or
2064             *          creating the file
2065             *
2066             * @throws  SecurityException
2067             *          If a security manager is present and {@link
2068             *          SecurityManager#checkWrite checkWrite(file.getPath())} denies
2069             *          write access to the file
2070             *
2071             * @throws  UnsupportedEncodingException
2072             *          If the named charset is not supported
2073             */
2074            public Formatter(File file, String csn)
2075                    throws FileNotFoundException, UnsupportedEncodingException {
2076                this (file, csn, Locale.getDefault());
2077            }
2078
2079            /**
2080             * Constructs a new formatter with the specified file, charset, and
2081             * locale.
2082             *
2083             * @param  file
2084             *         The file to use as the destination of this formatter.  If the
2085             *         file exists then it will be truncated to zero size; otherwise,
2086             *         a new file will be created.  The output will be written to the
2087             *         file and is buffered.
2088             *
2089             * @param  csn
2090             *         The name of a supported {@linkplain java.nio.charset.Charset
2091             *         charset}
2092             *
2093             * @param  l
2094             *         The {@linkplain java.util.Locale locale} to apply during
2095             *         formatting.  If <tt>l</tt> is <tt>null</tt> then no localization
2096             *         is applied.
2097             *
2098             * @throws  FileNotFoundException
2099             *          If the given file object does not denote an existing, writable
2100             *          regular file and a new regular file of that name cannot be
2101             *          created, or if some other error occurs while opening or
2102             *          creating the file
2103             *
2104             * @throws  SecurityException
2105             *          If a security manager is present and {@link
2106             *          SecurityManager#checkWrite checkWrite(file.getPath())} denies
2107             *          write access to the file
2108             *
2109             * @throws  UnsupportedEncodingException
2110             *          If the named charset is not supported
2111             */
2112            public Formatter(File file, String csn, Locale l)
2113                    throws FileNotFoundException, UnsupportedEncodingException {
2114                init(new BufferedWriter(new OutputStreamWriter(
2115                        new FileOutputStream(file), csn)), l);
2116            }
2117
2118            /**
2119             * Constructs a new formatter with the specified print stream.
2120             *
2121             * <p> The locale used is the {@linkplain Locale#getDefault() default
2122             * locale} for this instance of the Java virtual machine.
2123             *
2124             * <p> Characters are written to the given {@link java.io.PrintStream
2125             * PrintStream} object and are therefore encoded using that object's
2126             * charset.
2127             *
2128             * @param  ps
2129             *         The stream to use as the destination of this formatter.
2130             */
2131            public Formatter(PrintStream ps) {
2132                if (ps == null)
2133                    throw new NullPointerException();
2134                init((Appendable) ps, Locale.getDefault());
2135            }
2136
2137            /**
2138             * Constructs a new formatter with the specified output stream.
2139             *
2140             * <p> The charset used is the {@linkplain
2141             * java.nio.charset.Charset#defaultCharset() default charset} for this
2142             * instance of the Java virtual machine.
2143             *
2144             * <p> The locale used is the {@linkplain Locale#getDefault() default
2145             * locale} for this instance of the Java virtual machine.
2146             *
2147             * @param  os
2148             *         The output stream to use as the destination of this formatter.
2149             *         The output will be buffered.
2150             */
2151            public Formatter(OutputStream os) {
2152                init(new BufferedWriter(new OutputStreamWriter(os)), Locale
2153                        .getDefault());
2154            }
2155
2156            /**
2157             * Constructs a new formatter with the specified output stream and
2158             * charset.
2159             *
2160             * <p> The locale used is the {@linkplain Locale#getDefault default
2161             * locale} for this instance of the Java virtual machine.
2162             *
2163             * @param  os
2164             *         The output stream to use as the destination of this formatter.
2165             *         The output will be buffered.
2166             *
2167             * @param  csn
2168             *         The name of a supported {@linkplain java.nio.charset.Charset
2169             *         charset}
2170             *
2171             * @throws  UnsupportedEncodingException
2172             *          If the named charset is not supported
2173             */
2174            public Formatter(OutputStream os, String csn)
2175                    throws UnsupportedEncodingException {
2176                this (os, csn, Locale.getDefault());
2177            }
2178
2179            /**
2180             * Constructs a new formatter with the specified output stream, charset,
2181             * and locale.
2182             *
2183             * @param  os
2184             *         The output stream to use as the destination of this formatter.
2185             *         The output will be buffered.
2186             *
2187             * @param  csn
2188             *         The name of a supported {@linkplain java.nio.charset.Charset
2189             *         charset}
2190             *
2191             * @param  l
2192             *         The {@linkplain java.util.Locale locale} to apply during
2193             *         formatting.  If <tt>l</tt> is <tt>null</tt> then no localization
2194             *         is applied.
2195             *
2196             * @throws  UnsupportedEncodingException
2197             *          If the named charset is not supported
2198             */
2199            public Formatter(OutputStream os, String csn, Locale l)
2200                    throws UnsupportedEncodingException {
2201                init(new BufferedWriter(new OutputStreamWriter(os, csn)), l);
2202            }
2203
2204            private void setZero() {
2205                if ((l != null) && !l.equals(Locale.US)) {
2206                    DecimalFormatSymbols dfs = DecimalFormatSymbols
2207                            .getInstance(l);
2208                    zero = dfs.getZeroDigit();
2209                }
2210            }
2211
2212            /**
2213             * Returns the locale set by the construction of this formatter.
2214             *
2215             * <p> The {@link #format(java.util.Locale,String,Object...) format} method
2216             * for this object which has a locale argument does not change this value.
2217             *
2218             * @return  <tt>null</tt> if no localization is applied, otherwise a
2219             *          locale
2220             *
2221             * @throws  FormatterClosedException
2222             *          If this formatter has been closed by invoking its {@link
2223             *          #close()} method
2224             */
2225            public Locale locale() {
2226                ensureOpen();
2227                return l;
2228            }
2229
2230            /**
2231             * Returns the destination for the output.
2232             *
2233             * @return  The destination for the output
2234             *
2235             * @throws  FormatterClosedException
2236             *          If this formatter has been closed by invoking its {@link
2237             *          #close()} method
2238             */
2239            public Appendable out() {
2240                ensureOpen();
2241                return a;
2242            }
2243
2244            /**
2245             * Returns the result of invoking <tt>toString()</tt> on the destination
2246             * for the output.  For example, the following code formats text into a
2247             * {@link StringBuilder} then retrieves the resultant string:
2248             *
2249             * <blockquote><pre>
2250             *   Formatter f = new Formatter();
2251             *   f.format("Last reboot at %tc", lastRebootDate);
2252             *   String s = f.toString();
2253             *   // -&gt; s == "Last reboot at Sat Jan 01 00:00:00 PST 2000"
2254             * </pre></blockquote>
2255             *
2256             * <p> An invocation of this method behaves in exactly the same way as the
2257             * invocation
2258             *
2259             * <pre>
2260             *     out().toString() </pre>
2261             *
2262             * <p> Depending on the specification of <tt>toString</tt> for the {@link
2263             * Appendable}, the returned string may or may not contain the characters
2264             * written to the destination.  For instance, buffers typically return
2265             * their contents in <tt>toString()</tt>, but streams cannot since the
2266             * data is discarded.
2267             *
2268             * @return  The result of invoking <tt>toString()</tt> on the destination
2269             *          for the output
2270             *
2271             * @throws  FormatterClosedException
2272             *          If this formatter has been closed by invoking its {@link
2273             *          #close()} method
2274             */
2275            public String toString() {
2276                ensureOpen();
2277                return a.toString();
2278            }
2279
2280            /**
2281             * Flushes this formatter.  If the destination implements the {@link
2282             * java.io.Flushable} interface, its <tt>flush</tt> method will be invoked.
2283             *
2284             * <p> Flushing a formatter writes any buffered output in the destination
2285             * to the underlying stream.
2286             *
2287             * @throws  FormatterClosedException
2288             *          If this formatter has been closed by invoking its {@link
2289             *          #close()} method
2290             */
2291            public void flush() {
2292                ensureOpen();
2293                if (a instanceof  Flushable) {
2294                    try {
2295                        ((Flushable) a).flush();
2296                    } catch (IOException ioe) {
2297                        lastException = ioe;
2298                    }
2299                }
2300            }
2301
2302            /**
2303             * Closes this formatter.  If the destination implements the {@link
2304             * java.io.Closeable} interface, its <tt>close</tt> method will be invoked.
2305             *
2306             * <p> Closing a formatter allows it to release resources it may be holding
2307             * (such as open files).  If the formatter is already closed, then invoking
2308             * this method has no effect.
2309             *
2310             * <p> Attempting to invoke any methods except {@link #ioException()} in
2311             * this formatter after it has been closed will result in a {@link
2312             * FormatterClosedException}.
2313             */
2314            public void close() {
2315                if (a == null)
2316                    return;
2317                try {
2318                    if (a instanceof  Closeable)
2319                        ((Closeable) a).close();
2320                } catch (IOException ioe) {
2321                    lastException = ioe;
2322                } finally {
2323                    a = null;
2324                }
2325            }
2326
2327            private void ensureOpen() {
2328                if (a == null)
2329                    throw new FormatterClosedException();
2330            }
2331
2332            /**
2333             * Returns the <tt>IOException</tt> last thrown by this formatter's {@link
2334             * Appendable}.
2335             *
2336             * <p> If the destination's <tt>append()</tt> method never throws
2337             * <tt>IOException</tt>, then this method will always return <tt>null</tt>.
2338             *
2339             * @return  The last exception thrown by the Appendable or <tt>null</tt> if
2340             *          no such exception exists.
2341             */
2342            public IOException ioException() {
2343                return lastException;
2344            }
2345
2346            /**
2347             * Writes a formatted string to this object's destination using the
2348             * specified format string and arguments.  The locale used is the one
2349             * defined during the construction of this formatter.
2350             *
2351             * @param  format
2352             *         A format string as described in <a href="#syntax">Format string
2353             *         syntax</a>.
2354             *
2355             * @param  args
2356             *         Arguments referenced by the format specifiers in the format
2357             *         string.  If there are more arguments than format specifiers, the
2358             *         extra arguments are ignored.  The maximum number of arguments is
2359             *         limited by the maximum dimension of a Java array as defined by
2360             *         the <a href="http://java.sun.com/docs/books/vmspec/">Java
2361             *         Virtual Machine Specification</a>.
2362             *
2363             * @throws  IllegalFormatException
2364             *          If a format string contains an illegal syntax, a format
2365             *          specifier that is incompatible with the given arguments,
2366             *          insufficient arguments given the format string, or other
2367             *          illegal conditions.  For specification of all possible
2368             *          formatting errors, see the <a href="#detail">Details</a>
2369             *          section of the formatter class specification.
2370             *
2371             * @throws  FormatterClosedException
2372             *          If this formatter has been closed by invoking its {@link
2373             *          #close()} method
2374             *
2375             * @return  This formatter
2376             */
2377            public Formatter format(String format, Object... args) {
2378                return format(l, format, args);
2379            }
2380
2381            /**
2382             * Writes a formatted string to this object's destination using the
2383             * specified locale, format string, and arguments.
2384             *
2385             * @param  l
2386             *         The {@linkplain java.util.Locale locale} to apply during
2387             *         formatting.  If <tt>l</tt> is <tt>null</tt> then no localization
2388             *         is applied.  This does not change this object's locale that was
2389             *         set during construction.
2390             *
2391             * @param  format
2392             *         A format string as described in <a href="#syntax">Format string
2393             *         syntax</a>
2394             *
2395             * @param  args
2396             *         Arguments referenced by the format specifiers in the format
2397             *         string.  If there are more arguments than format specifiers, the
2398             *         extra arguments are ignored.  The maximum number of arguments is
2399             *         limited by the maximum dimension of a Java array as defined by
2400             *         the <a href="http://java.sun.com/docs/books/vmspec/">Java
2401             *         Virtual Machine Specification</a>
2402             *
2403             * @throws  IllegalFormatException
2404             *          If a format string contains an illegal syntax, a format
2405             *          specifier that is incompatible with the given arguments,
2406             *          insufficient arguments given the format string, or other
2407             *          illegal conditions.  For specification of all possible
2408             *          formatting errors, see the <a href="#detail">Details</a>
2409             *          section of the formatter class specification.
2410             *
2411             * @throws  FormatterClosedException
2412             *          If this formatter has been closed by invoking its {@link
2413             *          #close()} method
2414             *
2415             * @return  This formatter
2416             */
2417            public Formatter format(Locale l, String format, Object... args) {
2418                ensureOpen();
2419
2420                // index of last argument referenced
2421                int last = -1;
2422                // last ordinary index
2423                int lasto = -1;
2424
2425                FormatString[] fsa = parse(format);
2426                for (int i = 0; i < fsa.length; i++) {
2427                    FormatString fs = fsa[i];
2428                    int index = fs.index();
2429                    try {
2430                        switch (index) {
2431                        case -2: // fixed string, "%n", or "%%"
2432                            fs.print(null, l);
2433                            break;
2434                        case -1: // relative index
2435                            if (last < 0
2436                                    || (args != null && last > args.length - 1))
2437                                throw new MissingFormatArgumentException(fs
2438                                        .toString());
2439                            fs.print((args == null ? null : args[last]), l);
2440                            break;
2441                        case 0: // ordinary index
2442                            lasto++;
2443                            last = lasto;
2444                            if (args != null && lasto > args.length - 1)
2445                                throw new MissingFormatArgumentException(fs
2446                                        .toString());
2447                            fs.print((args == null ? null : args[lasto]), l);
2448                            break;
2449                        default: // explicit index
2450                            last = index - 1;
2451                            if (args != null && last > args.length - 1)
2452                                throw new MissingFormatArgumentException(fs
2453                                        .toString());
2454                            fs.print((args == null ? null : args[last]), l);
2455                            break;
2456                        }
2457                    } catch (IOException x) {
2458                        lastException = x;
2459                    }
2460                }
2461                return this ;
2462            }
2463
2464            // %[argument_index$][flags][width][.precision][t]conversion
2465            private static final String formatSpecifier = "%(\\d+\\$)?([-#+ 0,(\\<]*)?(\\d+)?(\\.\\d+)?([tT])?([a-zA-Z%])";
2466
2467            private static Pattern fsPattern = Pattern.compile(formatSpecifier);
2468
2469            // Look for format specifiers in the format string.
2470            private FormatString[] parse(String s) {
2471                ArrayList al = new ArrayList();
2472                Matcher m = fsPattern.matcher(s);
2473                int i = 0;
2474                while (i < s.length()) {
2475                    if (m.find(i)) {
2476                        // Anything between the start of the string and the beginning
2477                        // of the format specifier is either fixed text or contains
2478                        // an invalid format string.
2479                        if (m.start() != i) {
2480                            // Make sure we didn't miss any invalid format specifiers
2481                            checkText(s.substring(i, m.start()));
2482                            // Assume previous characters were fixed text
2483                            al.add(new FixedString(s.substring(i, m.start())));
2484                        }
2485
2486                        // Expect 6 groups in regular expression
2487                        String[] sa = new String[6];
2488                        for (int j = 0; j < m.groupCount(); j++) {
2489                            sa[j] = m.group(j + 1);
2490                            // 		    System.out.print(sa[j] + " ");
2491                        }
2492                        // 		System.out.println();
2493                        al.add(new FormatSpecifier(this , sa));
2494                        i = m.end();
2495                    } else {
2496                        // No more valid format specifiers.  Check for possible invalid
2497                        // format specifiers.
2498                        checkText(s.substring(i));
2499                        // The rest of the string is fixed text
2500                        al.add(new FixedString(s.substring(i)));
2501                        break;
2502                    }
2503                }
2504                //   	FormatString[] fs = new FormatString[al.size()];
2505                //   	for (int j = 0; j < al.size(); j++)
2506                //   	    System.out.println(((FormatString) al.get(j)).toString());
2507                return (FormatString[]) al.toArray(new FormatString[0]);
2508            }
2509
2510            private void checkText(String s) {
2511                int idx;
2512                // If there are any '%' in the given string, we got a bad format
2513                // specifier.
2514                if ((idx = s.indexOf('%')) != -1) {
2515                    char c = (idx > s.length() - 2 ? '%' : s.charAt(idx + 1));
2516                    throw new UnknownFormatConversionException(String
2517                            .valueOf(c));
2518                }
2519            }
2520
2521            private interface FormatString {
2522                int index();
2523
2524                void print(Object arg, Locale l) throws IOException;
2525
2526                String toString();
2527            }
2528
2529            private class FixedString implements  FormatString {
2530                private String s;
2531
2532                FixedString(String s) {
2533                    this .s = s;
2534                }
2535
2536                public int index() {
2537                    return -2;
2538                }
2539
2540                public void print(Object arg, Locale l) throws IOException {
2541                    a.append(s);
2542                }
2543
2544                public String toString() {
2545                    return s;
2546                }
2547            }
2548
2549            public enum BigDecimalLayoutForm {
2550                SCIENTIFIC, DECIMAL_FLOAT
2551            };
2552
2553            private class FormatSpecifier implements  FormatString {
2554                private int index = -1;
2555                private Flags f = Flags.NONE;
2556                private int width;
2557                private int precision;
2558                private boolean dt = false;
2559                private char c;
2560
2561                private Formatter formatter;
2562
2563                // cache the line separator
2564                private String ls;
2565
2566                private int index(String s) {
2567                    if (s != null) {
2568                        try {
2569                            index = Integer.parseInt(s.substring(0,
2570                                    s.length() - 1));
2571                        } catch (NumberFormatException x) {
2572                            assert (false);
2573                        }
2574                    } else {
2575                        index = 0;
2576                    }
2577                    return index;
2578                }
2579
2580                public int index() {
2581                    return index;
2582                }
2583
2584                private Flags flags(String s) {
2585                    f = Flags.parse(s);
2586                    if (f.contains(Flags.PREVIOUS))
2587                        index = -1;
2588                    return f;
2589                }
2590
2591                Flags flags() {
2592                    return f;
2593                }
2594
2595                private int width(String s) {
2596                    width = -1;
2597                    if (s != null) {
2598                        try {
2599                            width = Integer.parseInt(s);
2600                            if (width < 0)
2601                                throw new IllegalFormatWidthException(width);
2602                        } catch (NumberFormatException x) {
2603                            assert (false);
2604                        }
2605                    }
2606                    return width;
2607                }
2608
2609                int width() {
2610                    return width;
2611                }
2612
2613                private int precision(String s) {
2614                    precision = -1;
2615                    if (s != null) {
2616                        try {
2617                            // remove the '.'
2618                            precision = Integer.parseInt(s.substring(1));
2619                            if (precision < 0)
2620                                throw new IllegalFormatPrecisionException(
2621                                        precision);
2622                        } catch (NumberFormatException x) {
2623                            assert (false);
2624                        }
2625                    }
2626                    return precision;
2627                }
2628
2629                int precision() {
2630                    return precision;
2631                }
2632
2633                private char conversion(String s) {
2634                    c = s.charAt(0);
2635                    if (!dt) {
2636                        if (!Conversion.isValid(c))
2637                            throw new UnknownFormatConversionException(String
2638                                    .valueOf(c));
2639                        if (Character.isUpperCase(c))
2640                            f.add(Flags.UPPERCASE);
2641                        c = Character.toLowerCase(c);
2642                        if (Conversion.isText(c))
2643                            index = -2;
2644                    }
2645                    return c;
2646                }
2647
2648                private char conversion() {
2649                    return c;
2650                }
2651
2652                FormatSpecifier(Formatter formatter, String[] sa) {
2653                    this .formatter = formatter;
2654                    int idx = 0;
2655
2656                    index(sa[idx++]);
2657                    flags(sa[idx++]);
2658                    width(sa[idx++]);
2659                    precision(sa[idx++]);
2660
2661                    if (sa[idx] != null) {
2662                        dt = true;
2663                        if (sa[idx].equals("T"))
2664                            f.add(Flags.UPPERCASE);
2665                    }
2666                    conversion(sa[++idx]);
2667
2668                    if (dt)
2669                        checkDateTime();
2670                    else if (Conversion.isGeneral(c))
2671                        checkGeneral();
2672                    else if (Conversion.isCharacter(c))
2673                        checkCharacter();
2674                    else if (Conversion.isInteger(c))
2675                        checkInteger();
2676                    else if (Conversion.isFloat(c))
2677                        checkFloat();
2678                    else if (Conversion.isText(c))
2679                        checkText();
2680                    else
2681                        throw new UnknownFormatConversionException(String
2682                                .valueOf(c));
2683                }
2684
2685                public void print(Object arg, Locale l) throws IOException {
2686                    if (dt) {
2687                        printDateTime(arg, l);
2688                        return;
2689                    }
2690                    switch (c) {
2691                    case Conversion.DECIMAL_INTEGER:
2692                    case Conversion.OCTAL_INTEGER:
2693                    case Conversion.HEXADECIMAL_INTEGER:
2694                        printInteger(arg, l);
2695                        break;
2696                    case Conversion.SCIENTIFIC:
2697                    case Conversion.GENERAL:
2698                    case Conversion.DECIMAL_FLOAT:
2699                    case Conversion.HEXADECIMAL_FLOAT:
2700                        printFloat(arg, l);
2701                        break;
2702                    case Conversion.CHARACTER:
2703                    case Conversion.CHARACTER_UPPER:
2704                        printCharacter(arg);
2705                        break;
2706                    case Conversion.BOOLEAN:
2707                        printBoolean(arg);
2708                        break;
2709                    case Conversion.STRING:
2710                        printString(arg, l);
2711                        break;
2712                    case Conversion.HASHCODE:
2713                        printHashCode(arg);
2714                        break;
2715                    case Conversion.LINE_SEPARATOR:
2716                        if (ls == null)
2717                            ls = System.getProperty("line.separator");
2718                        a.append(ls);
2719                        break;
2720                    case Conversion.PERCENT_SIGN:
2721                        a.append('%');
2722                        break;
2723                    default:
2724                        assert false;
2725                    }
2726                }
2727
2728                private void printInteger(Object arg, Locale l)
2729                        throws IOException {
2730                    if (arg == null)
2731                        print("null");
2732                    else if (arg instanceof  Byte)
2733                        print(((Byte) arg).byteValue(), l);
2734                    else if (arg instanceof  Short)
2735                        print(((Short) arg).shortValue(), l);
2736                    else if (arg instanceof  Integer)
2737                        print(((Integer) arg).intValue(), l);
2738                    else if (arg instanceof  Long)
2739                        print(((Long) arg).longValue(), l);
2740                    else if (arg instanceof  BigInteger)
2741                        print(((BigInteger) arg), l);
2742                    else
2743                        failConversion(c, arg);
2744                }
2745
2746                private void printFloat(Object arg, Locale l)
2747                        throws IOException {
2748                    if (arg == null)
2749                        print("null");
2750                    else if (arg instanceof  Float)
2751                        print(((Float) arg).floatValue(), l);
2752                    else if (arg instanceof  Double)
2753                        print(((Double) arg).doubleValue(), l);
2754                    else if (arg instanceof  BigDecimal)
2755                        print(((BigDecimal) arg), l);
2756                    else
2757                        failConversion(c, arg);
2758                }
2759
2760                private void printDateTime(Object arg, Locale l)
2761                        throws IOException {
2762                    if (arg == null) {
2763                        print("null");
2764                        return;
2765                    }
2766                    Calendar cal = null;
2767
2768                    // Instead of Calendar.setLenient(true), perhaps we should
2769                    // wrap the IllegalArgumentException that might be thrown?
2770                    if (arg instanceof  Long) {
2771                        // Note that the following method uses an instance of the
2772                        // default time zone (TimeZone.getDefaultRef().
2773                        cal = Calendar.getInstance(l == null ? Locale.US : l);
2774                        cal.setTimeInMillis((Long) arg);
2775                    } else if (arg instanceof  Date) {
2776                        // Note that the following method uses an instance of the
2777                        // default time zone (TimeZone.getDefaultRef().
2778                        cal = Calendar.getInstance(l == null ? Locale.US : l);
2779                        cal.setTime((Date) arg);
2780                    } else if (arg instanceof  Calendar) {
2781                        cal = (Calendar) ((Calendar) arg).clone();
2782                        cal.setLenient(true);
2783                    } else {
2784                        failConversion(c, arg);
2785                    }
2786                    // Use the provided locale so that invocations of 
2787                    // localizedMagnitude() use optimizations for null.
2788                    print(cal, c, l);
2789                }
2790
2791                private void printCharacter(Object arg) throws IOException {
2792                    if (arg == null) {
2793                        print("null");
2794                        return;
2795                    }
2796                    String s = null;
2797                    if (arg instanceof  Character) {
2798                        s = ((Character) arg).toString();
2799                    } else if (arg instanceof  Byte) {
2800                        byte i = ((Byte) arg).byteValue();
2801                        if (Character.isValidCodePoint(i))
2802                            s = new String(Character.toChars(i));
2803                        else
2804                            throw new IllegalFormatCodePointException(i);
2805                    } else if (arg instanceof  Short) {
2806                        short i = ((Short) arg).shortValue();
2807                        if (Character.isValidCodePoint(i))
2808                            s = new String(Character.toChars(i));
2809                        else
2810                            throw new IllegalFormatCodePointException(i);
2811                    } else if (arg instanceof  Integer) {
2812                        int i = ((Integer) arg).intValue();
2813                        if (Character.isValidCodePoint(i))
2814                            s = new String(Character.toChars(i));
2815                        else
2816                            throw new IllegalFormatCodePointException(i);
2817                    } else {
2818                        failConversion(c, arg);
2819                    }
2820                    print(s);
2821                }
2822
2823                private void printString(Object arg, Locale l)
2824                        throws IOException {
2825                    if (arg == null) {
2826                        print("null");
2827                    } else if (arg instanceof  Formattable) {
2828                        Formatter fmt = formatter;
2829                        if (formatter.locale() != l)
2830                            fmt = new Formatter(formatter.out(), l);
2831                        ((Formattable) arg).formatTo(fmt, f.valueOf(), width,
2832                                precision);
2833                    } else {
2834                        print(arg.toString());
2835                    }
2836                }
2837
2838                private void printBoolean(Object arg) throws IOException {
2839                    String s;
2840                    if (arg != null)
2841                        s = ((arg instanceof  Boolean) ? ((Boolean) arg)
2842                                .toString() : Boolean.toString(true));
2843                    else
2844                        s = Boolean.toString(false);
2845                    print(s);
2846                }
2847
2848                private void printHashCode(Object arg) throws IOException {
2849                    String s = (arg == null ? "null" : Integer.toHexString(arg
2850                            .hashCode()));
2851                    print(s);
2852                }
2853
2854                private void print(String s) throws IOException {
2855                    if (precision != -1 && precision < s.length())
2856                        s = s.substring(0, precision);
2857                    if (f.contains(Flags.UPPERCASE))
2858                        s = s.toUpperCase();
2859                    a.append(justify(s));
2860                }
2861
2862                private String justify(String s) {
2863                    if (width == -1)
2864                        return s;
2865                    StringBuilder sb = new StringBuilder();
2866                    boolean pad = f.contains(Flags.LEFT_JUSTIFY);
2867                    int sp = width - s.length();
2868                    if (!pad)
2869                        for (int i = 0; i < sp; i++)
2870                            sb.append(' ');
2871                    sb.append(s);
2872                    if (pad)
2873                        for (int i = 0; i < sp; i++)
2874                            sb.append(' ');
2875                    return sb.toString();
2876                }
2877
2878                public String toString() {
2879                    StringBuilder sb = new StringBuilder('%');
2880                    // Flags.UPPERCASE is set internally for legal conversions.
2881                    Flags dupf = f.dup().remove(Flags.UPPERCASE);
2882                    sb.append(dupf.toString());
2883                    if (index > 0)
2884                        sb.append(index).append('$');
2885                    if (width != -1)
2886                        sb.append(width);
2887                    if (precision != -1)
2888                        sb.append('.').append(precision);
2889                    if (dt)
2890                        sb.append(f.contains(Flags.UPPERCASE) ? 'T' : 't');
2891                    sb.append(f.contains(Flags.UPPERCASE) ? Character
2892                            .toUpperCase(c) : c);
2893                    return sb.toString();
2894                }
2895
2896                private void checkGeneral() {
2897                    if ((c == Conversion.BOOLEAN || c == Conversion.HASHCODE)
2898                            && f.contains(Flags.ALTERNATE))
2899                        failMismatch(Flags.ALTERNATE, c);
2900                    // '-' requires a width
2901                    if (width == -1 && f.contains(Flags.LEFT_JUSTIFY))
2902                        throw new MissingFormatWidthException(toString());
2903                    checkBadFlags(Flags.PLUS, Flags.LEADING_SPACE,
2904                            Flags.ZERO_PAD, Flags.GROUP, Flags.PARENTHESES);
2905                }
2906
2907                private void checkDateTime() {
2908                    if (precision != -1)
2909                        throw new IllegalFormatPrecisionException(precision);
2910                    if (!DateTime.isValid(c))
2911                        throw new UnknownFormatConversionException("t" + c);
2912                    checkBadFlags(Flags.ALTERNATE, Flags.PLUS,
2913                            Flags.LEADING_SPACE, Flags.ZERO_PAD, Flags.GROUP,
2914                            Flags.PARENTHESES);
2915                    // '-' requires a width
2916                    if (width == -1 && f.contains(Flags.LEFT_JUSTIFY))
2917                        throw new MissingFormatWidthException(toString());
2918                }
2919
2920                private void checkCharacter() {
2921                    if (precision != -1)
2922                        throw new IllegalFormatPrecisionException(precision);
2923                    checkBadFlags(Flags.ALTERNATE, Flags.PLUS,
2924                            Flags.LEADING_SPACE, Flags.ZERO_PAD, Flags.GROUP,
2925                            Flags.PARENTHESES);
2926                    // '-' requires a width
2927                    if (width == -1 && f.contains(Flags.LEFT_JUSTIFY))
2928                        throw new MissingFormatWidthException(toString());
2929                }
2930
2931                private void checkInteger() {
2932                    checkNumeric();
2933                    if (precision != -1)
2934                        throw new IllegalFormatPrecisionException(precision);
2935
2936                    if (c == Conversion.DECIMAL_INTEGER)
2937                        checkBadFlags(Flags.ALTERNATE);
2938                    else if (c == Conversion.OCTAL_INTEGER)
2939                        checkBadFlags(Flags.GROUP);
2940                    else
2941                        checkBadFlags(Flags.GROUP);
2942                }
2943
2944                private void checkBadFlags(Flags... badFlags) {
2945                    for (int i = 0; i < badFlags.length; i++)
2946                        if (f.contains(badFlags[i]))
2947                            failMismatch(badFlags[i], c);
2948                }
2949
2950                private void checkFloat() {
2951                    checkNumeric();
2952                    if (c == Conversion.DECIMAL_FLOAT) {
2953                    } else if (c == Conversion.HEXADECIMAL_FLOAT) {
2954                        checkBadFlags(Flags.PARENTHESES, Flags.GROUP);
2955                    } else if (c == Conversion.SCIENTIFIC) {
2956                        checkBadFlags(Flags.GROUP);
2957                    } else if (c == Conversion.GENERAL) {
2958                        checkBadFlags(Flags.ALTERNATE);
2959                    }
2960                }
2961
2962                private void checkNumeric() {
2963                    if (width != -1 && width < 0)
2964                        throw new IllegalFormatWidthException(width);
2965
2966                    if (precision != -1 && precision < 0)
2967                        throw new IllegalFormatPrecisionException(precision);
2968
2969                    // '-' and '0' require a width
2970                    if (width == -1
2971                            && (f.contains(Flags.LEFT_JUSTIFY) || f
2972                                    .contains(Flags.ZERO_PAD)))
2973                        throw new MissingFormatWidthException(toString());
2974
2975                    // bad combination
2976                    if ((f.contains(Flags.PLUS) && f
2977                            .contains(Flags.LEADING_SPACE))
2978                            || (f.contains(Flags.LEFT_JUSTIFY) && f
2979                                    .contains(Flags.ZERO_PAD)))
2980                        throw new IllegalFormatFlagsException(f.toString());
2981                }
2982
2983                private void checkText() {
2984                    if (precision != -1)
2985                        throw new IllegalFormatPrecisionException(precision);
2986                    switch (c) {
2987                    case Conversion.PERCENT_SIGN:
2988                        if (f.valueOf() != Flags.LEFT_JUSTIFY.valueOf()
2989                                && f.valueOf() != Flags.NONE.valueOf())
2990                            throw new IllegalFormatFlagsException(f.toString());
2991                        // '-' requires a width
2992                        if (width == -1 && f.contains(Flags.LEFT_JUSTIFY))
2993                            throw new MissingFormatWidthException(toString());
2994                        break;
2995                    case Conversion.LINE_SEPARATOR:
2996                        if (width != -1)
2997                            throw new IllegalFormatWidthException(width);
2998                        if (f.valueOf() != Flags.NONE.valueOf())
2999                            throw new IllegalFormatFlagsException(f.toString());
3000                        break;
3001                    default:
3002                        assert false;
3003                    }
3004                }
3005
3006                private void print(byte value, Locale l) throws IOException {
3007                    long v = value;
3008                    if (value < 0
3009                            && (c == Conversion.OCTAL_INTEGER || c == Conversion.HEXADECIMAL_INTEGER)) {
3010                        v += (1L << 8);
3011                        assert v >= 0 : v;
3012                    }
3013                    print(v, l);
3014                }
3015
3016                private void print(short value, Locale l) throws IOException {
3017                    long v = value;
3018                    if (value < 0
3019                            && (c == Conversion.OCTAL_INTEGER || c == Conversion.HEXADECIMAL_INTEGER)) {
3020                        v += (1L << 16);
3021                        assert v >= 0 : v;
3022                    }
3023                    print(v, l);
3024                }
3025
3026                private void print(int value, Locale l) throws IOException {
3027                    long v = value;
3028                    if (value < 0
3029                            && (c == Conversion.OCTAL_INTEGER || c == Conversion.HEXADECIMAL_INTEGER)) {
3030                        v += (1L << 32);
3031                        assert v >= 0 : v;
3032                    }
3033                    print(v, l);
3034                }
3035
3036                private void print(long value, Locale l) throws IOException {
3037
3038                    StringBuilder sb = new StringBuilder();
3039
3040                    if (c == Conversion.DECIMAL_INTEGER) {
3041                        boolean neg = value < 0;
3042                        char[] va;
3043                        if (value < 0)
3044                            va = Long.toString(value, 10).substring(1)
3045                                    .toCharArray();
3046                        else
3047                            va = Long.toString(value, 10).toCharArray();
3048
3049                        // leading sign indicator
3050                        leadingSign(sb, neg);
3051
3052                        // the value
3053                        localizedMagnitude(sb, va, f,
3054                                adjustWidth(width, f, neg), l);
3055
3056                        // trailing sign indicator
3057                        trailingSign(sb, neg);
3058                    } else if (c == Conversion.OCTAL_INTEGER) {
3059                        checkBadFlags(Flags.PARENTHESES, Flags.LEADING_SPACE,
3060                                Flags.PLUS);
3061                        String s = Long.toOctalString(value);
3062                        int len = (f.contains(Flags.ALTERNATE) ? s.length() + 1
3063                                : s.length());
3064
3065                        // apply ALTERNATE (radix indicator for octal) before ZERO_PAD
3066                        if (f.contains(Flags.ALTERNATE))
3067                            sb.append('0');
3068                        if (f.contains(Flags.ZERO_PAD))
3069                            for (int i = 0; i < width - len; i++)
3070                                sb.append('0');
3071                        sb.append(s);
3072                    } else if (c == Conversion.HEXADECIMAL_INTEGER) {
3073                        checkBadFlags(Flags.PARENTHESES, Flags.LEADING_SPACE,
3074                                Flags.PLUS);
3075                        String s = Long.toHexString(value);
3076                        int len = (f.contains(Flags.ALTERNATE) ? s.length() + 2
3077                                : s.length());
3078
3079                        // apply ALTERNATE (radix indicator for hex) before ZERO_PAD
3080                        if (f.contains(Flags.ALTERNATE))
3081                            sb
3082                                    .append(f.contains(Flags.UPPERCASE) ? "0X"
3083                                            : "0x");
3084                        if (f.contains(Flags.ZERO_PAD))
3085                            for (int i = 0; i < width - len; i++)
3086                                sb.append('0');
3087                        if (f.contains(Flags.UPPERCASE))
3088                            s = s.toUpperCase();
3089                        sb.append(s);
3090                    }
3091
3092                    // justify based on width
3093                    a.append(justify(sb.toString()));
3094                }
3095
3096                // neg := val < 0
3097                private StringBuilder leadingSign(StringBuilder sb, boolean neg) {
3098                    if (!neg) {
3099                        if (f.contains(Flags.PLUS)) {
3100                            sb.append('+');
3101                        } else if (f.contains(Flags.LEADING_SPACE)) {
3102                            sb.append(' ');
3103                        }
3104                    } else {
3105                        if (f.contains(Flags.PARENTHESES))
3106                            sb.append('(');
3107                        else
3108                            sb.append('-');
3109                    }
3110                    return sb;
3111                }
3112
3113                // neg := val < 0
3114                private StringBuilder trailingSign(StringBuilder sb, boolean neg) {
3115                    if (neg && f.contains(Flags.PARENTHESES))
3116                        sb.append(')');
3117                    return sb;
3118                }
3119
3120                private void print(BigInteger value, Locale l)
3121                        throws IOException {
3122                    StringBuilder sb = new StringBuilder();
3123                    boolean neg = value.signum() == -1;
3124                    BigInteger v = value.abs();
3125
3126                    // leading sign indicator
3127                    leadingSign(sb, neg);
3128
3129                    // the value
3130                    if (c == Conversion.DECIMAL_INTEGER) {
3131                        char[] va = v.toString().toCharArray();
3132                        localizedMagnitude(sb, va, f,
3133                                adjustWidth(width, f, neg), l);
3134                    } else if (c == Conversion.OCTAL_INTEGER) {
3135                        String s = v.toString(8);
3136
3137                        int len = s.length() + sb.length();
3138                        if (neg && f.contains(Flags.PARENTHESES))
3139                            len++;
3140
3141                        // apply ALTERNATE (radix indicator for octal) before ZERO_PAD
3142                        if (f.contains(Flags.ALTERNATE)) {
3143                            len++;
3144                            sb.append('0');
3145                        }
3146                        if (f.contains(Flags.ZERO_PAD)) {
3147                            for (int i = 0; i < width - len; i++)
3148                                sb.append('0');
3149                        }
3150                        sb.append(s);
3151                    } else if (c == Conversion.HEXADECIMAL_INTEGER) {
3152                        String s = v.toString(16);
3153
3154                        int len = s.length() + sb.length();
3155                        if (neg && f.contains(Flags.PARENTHESES))
3156                            len++;
3157
3158                        // apply ALTERNATE (radix indicator for hex) before ZERO_PAD
3159                        if (f.contains(Flags.ALTERNATE)) {
3160                            len += 2;
3161                            sb
3162                                    .append(f.contains(Flags.UPPERCASE) ? "0X"
3163                                            : "0x");
3164                        }
3165                        if (f.contains(Flags.ZERO_PAD))
3166                            for (int i = 0; i < width - len; i++)
3167                                sb.append('0');
3168                        if (f.contains(Flags.UPPERCASE))
3169                            s = s.toUpperCase();
3170                        sb.append(s);
3171                    }
3172
3173                    // trailing sign indicator
3174                    trailingSign(sb, (value.signum() == -1));
3175
3176                    // justify based on width
3177                    a.append(justify(sb.toString()));
3178                }
3179
3180                private void print(float value, Locale l) throws IOException {
3181                    print((double) value, l);
3182                }
3183
3184                private void print(double value, Locale l) throws IOException {
3185                    StringBuilder sb = new StringBuilder();
3186                    boolean neg = Double.compare(value, 0.0) == -1;
3187
3188                    if (!Double.isNaN(value)) {
3189                        double v = Math.abs(value);
3190
3191                        // leading sign indicator
3192                        leadingSign(sb, neg);
3193
3194                        // the value
3195                        if (!Double.isInfinite(v))
3196                            print(sb, v, l, f, c, precision, neg);
3197                        else
3198                            sb.append(f.contains(Flags.UPPERCASE) ? "INFINITY"
3199                                    : "Infinity");
3200
3201                        // trailing sign indicator
3202                        trailingSign(sb, neg);
3203                    } else {
3204                        sb.append(f.contains(Flags.UPPERCASE) ? "NAN" : "NaN");
3205                    }
3206
3207                    // justify based on width
3208                    a.append(justify(sb.toString()));
3209                }
3210
3211                // !Double.isInfinite(value) && !Double.isNaN(value)
3212                private void print(StringBuilder sb, double value, Locale l,
3213                        Flags f, char c, int precision, boolean neg)
3214                        throws IOException {
3215                    if (c == Conversion.SCIENTIFIC) {
3216                        // Create a new FormattedFloatingDecimal with the desired
3217                        // precision.
3218                        int prec = (precision == -1 ? 6 : precision);
3219
3220                        FormattedFloatingDecimal fd = new FormattedFloatingDecimal(
3221                                value, prec,
3222                                FormattedFloatingDecimal.Form.SCIENTIFIC);
3223
3224                        char[] v = new char[MAX_FD_CHARS];
3225                        int len = fd.getChars(v);
3226
3227                        char[] mant = addZeros(mantissa(v, len), prec);
3228
3229                        // If the precision is zero and the '#' flag is set, add the
3230                        // requested decimal point.
3231                        if (f.contains(Flags.ALTERNATE) && (prec == 0))
3232                            mant = addDot(mant);
3233
3234                        char[] exp = (value == 0.0) ? new char[] { '+', '0',
3235                                '0' } : exponent(v, len);
3236
3237                        int newW = width;
3238                        if (width != -1)
3239                            newW = adjustWidth(width - exp.length - 1, f, neg);
3240                        localizedMagnitude(sb, mant, f, newW, l);
3241
3242                        sb.append(f.contains(Flags.UPPERCASE) ? 'E' : 'e');
3243
3244                        Flags flags = f.dup().remove(Flags.GROUP);
3245                        char sign = exp[0];
3246                        assert (sign == '+' || sign == '-');
3247                        sb.append(sign);
3248
3249                        char[] tmp = new char[exp.length - 1];
3250                        System.arraycopy(exp, 1, tmp, 0, exp.length - 1);
3251                        sb.append(localizedMagnitude(null, tmp, flags, -1, l));
3252                    } else if (c == Conversion.DECIMAL_FLOAT) {
3253                        // Create a new FormattedFloatingDecimal with the desired
3254                        // precision.
3255                        int prec = (precision == -1 ? 6 : precision);
3256
3257                        FormattedFloatingDecimal fd = new FormattedFloatingDecimal(
3258                                value, prec,
3259                                FormattedFloatingDecimal.Form.DECIMAL_FLOAT);
3260
3261                        // MAX_FD_CHARS + 1 (round?)
3262                        char[] v = new char[MAX_FD_CHARS + 1
3263                                + Math.abs(fd.getExponent())];
3264                        int len = fd.getChars(v);
3265
3266                        char[] mant = addZeros(mantissa(v, len), prec);
3267
3268                        // If the precision is zero and the '#' flag is set, add the
3269                        // requested decimal point.
3270                        if (f.contains(Flags.ALTERNATE) && (prec == 0))
3271                            mant = addDot(mant);
3272
3273                        int newW = width;
3274                        if (width != -1)
3275                            newW = adjustWidth(width, f, neg);
3276                        localizedMagnitude(sb, mant, f, newW, l);
3277                    } else if (c == Conversion.GENERAL) {
3278                        int prec = precision;
3279                        if (precision == -1)
3280                            prec = 6;
3281                        else if (precision == 0)
3282                            prec = 1;
3283
3284                        FormattedFloatingDecimal fd = new FormattedFloatingDecimal(
3285                                value, prec,
3286                                FormattedFloatingDecimal.Form.GENERAL);
3287
3288                        // MAX_FD_CHARS + 1 (round?)
3289                        char[] v = new char[MAX_FD_CHARS + 1
3290                                + Math.abs(fd.getExponent())];
3291                        int len = fd.getChars(v);
3292
3293                        char[] exp = exponent(v, len);
3294                        if (exp != null) {
3295                            prec -= 1;
3296                        } else {
3297                            prec = prec
3298                                    - (value == 0 ? 0 : fd.getExponentRounded())
3299                                    - 1;
3300                        }
3301
3302                        char[] mant = addZeros(mantissa(v, len), prec);
3303                        // If the precision is zero and the '#' flag is set, add the
3304                        // requested decimal point.
3305                        if (f.contains(Flags.ALTERNATE) && (prec == 0))
3306                            mant = addDot(mant);
3307
3308                        int newW = width;
3309                        if (width != -1) {
3310                            if (exp != null)
3311                                newW = adjustWidth(width - exp.length - 1, f,
3312                                        neg);
3313                            else
3314                                newW = adjustWidth(width, f, neg);
3315                        }
3316                        localizedMagnitude(sb, mant, f, newW, l);
3317
3318                        if (exp != null) {
3319                            sb.append(f.contains(Flags.UPPERCASE) ? 'E' : 'e');
3320
3321                            Flags flags = f.dup().remove(Flags.GROUP);
3322                            char sign = exp[0];
3323                            assert (sign == '+' || sign == '-');
3324                            sb.append(sign);
3325
3326                            char[] tmp = new char[exp.length - 1];
3327                            System.arraycopy(exp, 1, tmp, 0, exp.length - 1);
3328                            sb.append(localizedMagnitude(null, tmp, flags, -1,
3329                                    l));
3330                        }
3331                    } else if (c == Conversion.HEXADECIMAL_FLOAT) {
3332                        int prec = precision;
3333                        if (precision == -1)
3334                            // assume that we want all of the digits
3335                            prec = 0;
3336                        else if (precision == 0)
3337                            prec = 1;
3338
3339                        String s = hexDouble(value, prec);
3340
3341                        char[] va;
3342                        boolean upper = f.contains(Flags.UPPERCASE);
3343                        sb.append(upper ? "0X" : "0x");
3344
3345                        if (f.contains(Flags.ZERO_PAD))
3346                            for (int i = 0; i < width - s.length() - 2; i++)
3347                                sb.append('0');
3348
3349                        int idx = s.indexOf('p');
3350                        va = s.substring(0, idx).toCharArray();
3351                        if (upper) {
3352                            String tmp = new String(va);
3353                            // don't localize hex
3354                            tmp = tmp.toUpperCase(Locale.US);
3355                            va = tmp.toCharArray();
3356                        }
3357                        sb.append(prec != 0 ? addZeros(va, prec) : va);
3358                        sb.append(upper ? 'P' : 'p');
3359                        sb.append(s.substring(idx + 1));
3360                    }
3361                }
3362
3363                private char[] mantissa(char[] v, int len) {
3364                    int i;
3365                    for (i = 0; i < len; i++) {
3366                        if (v[i] == 'e')
3367                            break;
3368                    }
3369                    char[] tmp = new char[i];
3370                    System.arraycopy(v, 0, tmp, 0, i);
3371                    return tmp;
3372                }
3373
3374                private char[] exponent(char[] v, int len) {
3375                    int i;
3376                    for (i = len - 1; i >= 0; i--) {
3377                        if (v[i] == 'e')
3378                            break;
3379                    }
3380                    if (i == -1)
3381                        return null;
3382                    char[] tmp = new char[len - i - 1];
3383                    System.arraycopy(v, i + 1, tmp, 0, len - i - 1);
3384                    return tmp;
3385                }
3386
3387                // Add zeros to the requested precision.
3388                private char[] addZeros(char[] v, int prec) {
3389                    // Look for the dot.  If we don't find one, the we'll need to add
3390                    // it before we add the zeros.
3391                    int i;
3392                    for (i = 0; i < v.length; i++) {
3393                        if (v[i] == '.')
3394                            break;
3395                    }
3396                    boolean needDot = false;
3397                    if (i == v.length) {
3398                        needDot = true;
3399                    }
3400
3401                    // Determine existing precision.
3402                    int outPrec = v.length - i - (needDot ? 0 : 1);
3403                    assert (outPrec <= prec);
3404                    if (outPrec == prec)
3405                        return v;
3406
3407                    // Create new array with existing contents.
3408                    char[] tmp = new char[v.length + prec - outPrec
3409                            + (needDot ? 1 : 0)];
3410                    System.arraycopy(v, 0, tmp, 0, v.length);
3411
3412                    // Add dot if previously determined to be necessary.
3413                    int start = v.length;
3414                    if (needDot) {
3415                        tmp[v.length] = '.';
3416                        start++;
3417                    }
3418
3419                    // Add zeros.
3420                    for (int j = start; j < tmp.length; j++)
3421                        tmp[j] = '0';
3422
3423                    return tmp;
3424                }
3425
3426                // Method assumes that d > 0.
3427                private String hexDouble(double d, int prec) {
3428                    // Let Double.toHexString handle simple cases
3429                    if (!FpUtils.isFinite(d) || d == 0.0 || prec == 0
3430                            || prec >= 13)
3431                        // remove "0x"
3432                        return Double.toHexString(d).substring(2);
3433                    else {
3434                        assert (prec >= 1 && prec <= 12);
3435
3436                        int exponent = FpUtils.getExponent(d);
3437                        boolean subnormal = (exponent == DoubleConsts.MIN_EXPONENT - 1);
3438
3439                        // If this is subnormal input so normalize (could be faster to
3440                        // do as integer operation).
3441                        if (subnormal) {
3442                            scaleUp = FpUtils.scalb(1.0, 54);
3443                            d *= scaleUp;
3444                            // Calculate the exponent.  This is not just exponent + 54
3445                            // since the former is not the normalized exponent.
3446                            exponent = FpUtils.getExponent(d);
3447                            assert exponent >= DoubleConsts.MIN_EXPONENT
3448                                    && exponent <= DoubleConsts.MAX_EXPONENT : exponent;
3449                        }
3450
3451                        int precision = 1 + prec * 4;
3452                        int shiftDistance = DoubleConsts.SIGNIFICAND_WIDTH
3453                                - precision;
3454                        assert (shiftDistance >= 1 && shiftDistance < DoubleConsts.SIGNIFICAND_WIDTH);
3455
3456                        long doppel = Double.doubleToLongBits(d);
3457                        // Deterime the number of bits to keep.
3458                        long newSignif = (doppel & (DoubleConsts.EXP_BIT_MASK | DoubleConsts.SIGNIF_BIT_MASK)) >> shiftDistance;
3459                        // Bits to round away.
3460                        long roundingBits = doppel & ~(~0L << shiftDistance);
3461
3462                        // To decide how to round, look at the low-order bit of the
3463                        // working significand, the highest order discarded bit (the
3464                        // round bit) and whether any of the lower order discarded bits
3465                        // are nonzero (the sticky bit).
3466
3467                        boolean leastZero = (newSignif & 0x1L) == 0L;
3468                        boolean round = ((1L << (shiftDistance - 1)) & roundingBits) != 0L;
3469                        boolean sticky = shiftDistance > 1
3470                                && (~(1L << (shiftDistance - 1)) & roundingBits) != 0;
3471                        if ((leastZero && round && sticky)
3472                                || (!leastZero && round)) {
3473                            newSignif++;
3474                        }
3475
3476                        long signBit = doppel & DoubleConsts.SIGN_BIT_MASK;
3477                        newSignif = signBit | (newSignif << shiftDistance);
3478                        double result = Double.longBitsToDouble(newSignif);
3479
3480                        if (Double.isInfinite(result)) {
3481                            // Infinite result generated by rounding
3482                            return "1.0p1024";
3483                        } else {
3484                            String res = Double.toHexString(result)
3485                                    .substring(2);
3486                            if (!subnormal)
3487                                return res;
3488                            else {
3489                                // Create a normalized subnormal string.
3490                                int idx = res.indexOf('p');
3491                                if (idx == -1) {
3492                                    // No 'p' character in hex string.
3493                                    assert false;
3494                                    return null;
3495                                } else {
3496                                    // Get exponent and append at the end.
3497                                    String exp = res.substring(idx + 1);
3498                                    int iexp = Integer.parseInt(exp) - 54;
3499                                    return res.substring(0, idx) + "p"
3500                                            + Integer.toString(iexp);
3501                                }
3502                            }
3503                        }
3504                    }
3505                }
3506
3507                private void print(BigDecimal value, Locale l)
3508                        throws IOException {
3509                    if (c == Conversion.HEXADECIMAL_FLOAT)
3510                        failConversion(c, value);
3511                    StringBuilder sb = new StringBuilder();
3512                    boolean neg = value.signum() == -1;
3513                    BigDecimal v = value.abs();
3514                    // leading sign indicator
3515                    leadingSign(sb, neg);
3516
3517                    // the value
3518                    print(sb, v, l, f, c, precision, neg);
3519
3520                    // trailing sign indicator
3521                    trailingSign(sb, neg);
3522
3523                    // justify based on width
3524                    a.append(justify(sb.toString()));
3525                }
3526
3527                // value > 0
3528                private void print(StringBuilder sb, BigDecimal value,
3529                        Locale l, Flags f, char c, int precision, boolean neg)
3530                        throws IOException {
3531                    if (c == Conversion.SCIENTIFIC) {
3532                        // Create a new BigDecimal with the desired precision.
3533                        int prec = (precision == -1 ? 6 : precision);
3534                        int scale = value.scale();
3535                        int origPrec = value.precision();
3536                        int nzeros = 0;
3537                        int compPrec;
3538
3539                        if (prec > origPrec - 1) {
3540                            compPrec = origPrec;
3541                            nzeros = prec - (origPrec - 1);
3542                        } else {
3543                            compPrec = prec + 1;
3544                        }
3545
3546                        MathContext mc = new MathContext(compPrec);
3547                        BigDecimal v = new BigDecimal(value.unscaledValue(),
3548                                scale, mc);
3549
3550                        BigDecimalLayout bdl = new BigDecimalLayout(v
3551                                .unscaledValue(), v.scale(),
3552                                BigDecimalLayoutForm.SCIENTIFIC);
3553
3554                        char[] mant = bdl.mantissa();
3555
3556                        // Add a decimal point if necessary.  The mantissa may not
3557                        // contain a decimal point if the scale is zero (the internal
3558                        // representation has no fractional part) or the original
3559                        // precision is one. Append a decimal point if '#' is set or if
3560                        // we require zero padding to get to the requested precision.
3561                        if ((origPrec == 1 || !bdl.hasDot())
3562                                && (nzeros > 0 || (f.contains(Flags.ALTERNATE))))
3563                            mant = addDot(mant);
3564
3565                        // Add trailing zeros in the case precision is greater than
3566                        // the number of available digits after the decimal separator.
3567                        mant = trailingZeros(mant, nzeros);
3568
3569                        char[] exp = bdl.exponent();
3570                        int newW = width;
3571                        if (width != -1)
3572                            newW = adjustWidth(width - exp.length - 1, f, neg);
3573                        localizedMagnitude(sb, mant, f, newW, l);
3574
3575                        sb.append(f.contains(Flags.UPPERCASE) ? 'E' : 'e');
3576
3577                        Flags flags = f.dup().remove(Flags.GROUP);
3578                        char sign = exp[0];
3579                        assert (sign == '+' || sign == '-');
3580                        sb.append(exp[0]);
3581
3582                        char[] tmp = new char[exp.length - 1];
3583                        System.arraycopy(exp, 1, tmp, 0, exp.length - 1);
3584                        sb.append(localizedMagnitude(null, tmp, flags, -1, l));
3585                    } else if (c == Conversion.DECIMAL_FLOAT) {
3586                        // Create a new BigDecimal with the desired precision.
3587                        int prec = (precision == -1 ? 6 : precision);
3588                        int scale = value.scale();
3589                        int compPrec = value.precision();
3590                        if (scale > prec)
3591                            compPrec -= (scale - prec);
3592                        MathContext mc = new MathContext(compPrec);
3593                        BigDecimal v = new BigDecimal(value.unscaledValue(),
3594                                scale, mc);
3595
3596                        BigDecimalLayout bdl = new BigDecimalLayout(v
3597                                .unscaledValue(), v.scale(),
3598                                BigDecimalLayoutForm.DECIMAL_FLOAT);
3599
3600                        char mant[] = bdl.mantissa();
3601                        int nzeros = (bdl.scale() < prec ? prec - bdl.scale()
3602                                : 0);
3603
3604                        // Add a decimal point if necessary.  The mantissa may not
3605                        // contain a decimal point if the scale is zero (the internal
3606                        // representation has no fractional part).  Append a decimal
3607                        // point if '#' is set or we require zero padding to get to the
3608                        // requested precision.
3609                        if (bdl.scale() == 0
3610                                && (f.contains(Flags.ALTERNATE) || nzeros > 0))
3611                            mant = addDot(bdl.mantissa());
3612
3613                        // Add trailing zeros if the precision is greater than the
3614                        // number of available digits after the decimal separator.
3615                        mant = trailingZeros(mant, nzeros);
3616
3617                        localizedMagnitude(sb, mant, f, adjustWidth(width, f,
3618                                neg), l);
3619                    } else if (c == Conversion.GENERAL) {
3620                        int prec = precision;
3621                        if (precision == -1)
3622                            prec = 6;
3623                        else if (precision == 0)
3624                            prec = 1;
3625
3626                        BigDecimal tenToTheNegFour = BigDecimal.valueOf(1, 4);
3627                        BigDecimal tenToThePrec = BigDecimal.valueOf(1, -prec);
3628                        if ((value.equals(BigDecimal.ZERO))
3629                                || ((value.compareTo(tenToTheNegFour) != -1) && (value
3630                                        .compareTo(tenToThePrec) == -1))) {
3631
3632                            int e = -value.scale()
3633                                    + (value.unscaledValue().toString()
3634                                            .length() - 1);
3635
3636                            // xxx.yyy
3637                            //   g precision (# sig digits) = #x + #y
3638                            //   f precision = #y
3639                            //   exponent = #x - 1
3640                            // => f precision = g precision - exponent - 1
3641                            // 0.000zzz
3642                            //   g precision (# sig digits) = #z
3643                            //   f precision = #0 (after '.') + #z
3644                            //   exponent = - #0 (after '.') - 1
3645                            // => f precision = g precision - exponent - 1
3646                            prec = prec - e - 1;
3647
3648                            print(sb, value, l, f, Conversion.DECIMAL_FLOAT,
3649                                    prec, neg);
3650                        } else {
3651                            print(sb, value, l, f, Conversion.SCIENTIFIC,
3652                                    prec - 1, neg);
3653                        }
3654                    } else if (c == Conversion.HEXADECIMAL_FLOAT) {
3655                        // This conversion isn't supported.  The error should be
3656                        // reported earlier.
3657                        assert false;
3658                    }
3659                }
3660
3661                private class BigDecimalLayout {
3662                    private StringBuilder mant;
3663                    private StringBuilder exp;
3664                    private boolean dot = false;
3665                    private int scale;
3666
3667                    public BigDecimalLayout(BigInteger intVal, int scale,
3668                            BigDecimalLayoutForm form) {
3669                        layout(intVal, scale, form);
3670                    }
3671
3672                    public boolean hasDot() {
3673                        return dot;
3674                    }
3675
3676                    public int scale() {
3677                        return scale;
3678                    }
3679
3680                    // char[] with canonical string representation
3681                    public char[] layoutChars() {
3682                        StringBuilder sb = new StringBuilder(mant);
3683                        if (exp != null) {
3684                            sb.append('E');
3685                            sb.append(exp);
3686                        }
3687                        return toCharArray(sb);
3688                    }
3689
3690                    public char[] mantissa() {
3691                        return toCharArray(mant);
3692                    }
3693
3694                    // The exponent will be formatted as a sign ('+' or '-') followed
3695                    // by the exponent zero-padded to include at least two digits.
3696                    public char[] exponent() {
3697                        return toCharArray(exp);
3698                    }
3699
3700                    private char[] toCharArray(StringBuilder sb) {
3701                        if (sb == null)
3702                            return null;
3703                        char[] result = new char[sb.length()];
3704                        sb.getChars(0, result.length, result, 0);
3705                        return result;
3706                    }
3707
3708                    private void layout(BigInteger intVal, int scale,
3709                            BigDecimalLayoutForm form) {
3710                        char coeff[] = intVal.toString().toCharArray();
3711                        this .scale = scale;
3712
3713                        // Construct a buffer, with sufficient capacity for all cases.
3714                        // If E-notation is needed, length will be: +1 if negative, +1
3715                        // if '.' needed, +2 for "E+", + up to 10 for adjusted
3716                        // exponent.  Otherwise it could have +1 if negative, plus
3717                        // leading "0.00000"
3718                        mant = new StringBuilder(coeff.length + 14);
3719
3720                        if (scale == 0) {
3721                            int len = coeff.length;
3722                            if (len > 1) {
3723                                mant.append(coeff[0]);
3724                                if (form == BigDecimalLayoutForm.SCIENTIFIC) {
3725                                    mant.append('.');
3726                                    dot = true;
3727                                    mant.append(coeff, 1, len - 1);
3728                                    exp = new StringBuilder("+");
3729                                    if (len < 10)
3730                                        exp.append("0").append(len - 1);
3731                                    else
3732                                        exp.append(len - 1);
3733                                } else {
3734                                    mant.append(coeff, 1, len - 1);
3735                                }
3736                            } else {
3737                                mant.append(coeff);
3738                                if (form == BigDecimalLayoutForm.SCIENTIFIC)
3739                                    exp = new StringBuilder("+00");
3740                            }
3741                            return;
3742                        }
3743                        long adjusted = -(long) scale + (coeff.length - 1);
3744                        if (form == BigDecimalLayoutForm.DECIMAL_FLOAT) {
3745                            // count of padding zeros
3746                            int pad = scale - coeff.length;
3747                            if (pad >= 0) {
3748                                // 0.xxx form
3749                                mant.append("0.");
3750                                dot = true;
3751                                for (; pad > 0; pad--)
3752                                    mant.append('0');
3753                                mant.append(coeff);
3754                            } else {
3755                                if (-pad < coeff.length) {
3756                                    // xx.xx form
3757                                    mant.append(coeff, 0, -pad);
3758                                    mant.append('.');
3759                                    dot = true;
3760                                    mant.append(coeff, -pad, scale);
3761                                } else {
3762                                    // xx form
3763                                    mant.append(coeff, 0, coeff.length);
3764                                    for (int i = 0; i < -scale; i++)
3765                                        mant.append('0');
3766                                    this .scale = 0;
3767                                }
3768                            }
3769                        } else {
3770                            // x.xxx form
3771                            mant.append(coeff[0]);
3772                            if (coeff.length > 1) {
3773                                mant.append('.');
3774                                dot = true;
3775                                mant.append(coeff, 1, coeff.length - 1);
3776                            }
3777                            exp = new StringBuilder();
3778                            if (adjusted != 0) {
3779                                long abs = Math.abs(adjusted);
3780                                // require sign
3781                                exp.append(adjusted < 0 ? '-' : '+');
3782                                if (abs < 10)
3783                                    exp.append('0');
3784                                exp.append(abs);
3785                            } else {
3786                                exp.append("+00");
3787                            }
3788                        }
3789                    }
3790                }
3791
3792                private int adjustWidth(int width, Flags f, boolean neg) {
3793                    int newW = width;
3794                    if (newW != -1 && neg && f.contains(Flags.PARENTHESES))
3795                        newW--;
3796                    return newW;
3797                }
3798
3799                // Add a '.' to th mantissa if required
3800                private char[] addDot(char[] mant) {
3801                    char[] tmp = mant;
3802                    tmp = new char[mant.length + 1];
3803                    System.arraycopy(mant, 0, tmp, 0, mant.length);
3804                    tmp[tmp.length - 1] = '.';
3805                    return tmp;
3806                }
3807
3808                // Add trailing zeros in the case precision is greater than the number
3809                // of available digits after the decimal separator.
3810                private char[] trailingZeros(char[] mant, int nzeros) {
3811                    char[] tmp = mant;
3812                    if (nzeros > 0) {
3813                        tmp = new char[mant.length + nzeros];
3814                        System.arraycopy(mant, 0, tmp, 0, mant.length);
3815                        for (int i = mant.length; i < tmp.length; i++)
3816                            tmp[i] = '0';
3817                    }
3818                    return tmp;
3819                }
3820
3821                private void print(Calendar t, char c, Locale l)
3822                        throws IOException {
3823                    StringBuilder sb = new StringBuilder();
3824                    print(sb, t, c, l);
3825
3826                    // justify based on width
3827                    String s = justify(sb.toString());
3828                    if (f.contains(Flags.UPPERCASE))
3829                        s = s.toUpperCase();
3830
3831                    a.append(s);
3832                }
3833
3834                private Appendable print(StringBuilder sb, Calendar t, char c,
3835                        Locale l) throws IOException {
3836                    assert (width == -1);
3837                    if (sb == null)
3838                        sb = new StringBuilder();
3839                    switch (c) {
3840                    case DateTime.HOUR_OF_DAY_0: // 'H' (00 - 23)
3841                    case DateTime.HOUR_0: // 'I' (01 - 12)
3842                    case DateTime.HOUR_OF_DAY: // 'k' (0 - 23) -- like H
3843                    case DateTime.HOUR: { // 'l' (1 - 12) -- like I
3844                        int i = t.get(Calendar.HOUR_OF_DAY);
3845                        if (c == DateTime.HOUR_0 || c == DateTime.HOUR)
3846                            i = (i == 0 || i == 12 ? 12 : i % 12);
3847                        Flags flags = (c == DateTime.HOUR_OF_DAY_0
3848                                || c == DateTime.HOUR_0 ? Flags.ZERO_PAD
3849                                : Flags.NONE);
3850                        sb.append(localizedMagnitude(null, i, flags, 2, l));
3851                        break;
3852                    }
3853                    case DateTime.MINUTE: { // 'M' (00 - 59)
3854                        int i = t.get(Calendar.MINUTE);
3855                        Flags flags = Flags.ZERO_PAD;
3856                        sb.append(localizedMagnitude(null, i, flags, 2, l));
3857                        break;
3858                    }
3859                    case DateTime.NANOSECOND: { // 'N' (000000000 - 999999999)
3860                        int i = t.get(Calendar.MILLISECOND) * 1000000;
3861                        Flags flags = Flags.ZERO_PAD;
3862                        sb.append(localizedMagnitude(null, i, flags, 9, l));
3863                        break;
3864                    }
3865                    case DateTime.MILLISECOND: { // 'L' (000 - 999)
3866                        int i = t.get(Calendar.MILLISECOND);
3867                        Flags flags = Flags.ZERO_PAD;
3868                        sb.append(localizedMagnitude(null, i, flags, 3, l));
3869                        break;
3870                    }
3871                    case DateTime.MILLISECOND_SINCE_EPOCH: { // 'Q' (0 - 99...?)
3872                        long i = t.getTimeInMillis();
3873                        Flags flags = Flags.NONE;
3874                        sb.append(localizedMagnitude(null, i, flags, width, l));
3875                        break;
3876                    }
3877                    case DateTime.AM_PM: { // 'p' (am or pm)
3878                        // Calendar.AM = 0, Calendar.PM = 1, LocaleElements defines upper
3879                        String[] ampm = { "AM", "PM" };
3880                        if (l != null && l != Locale.US) {
3881                            DateFormatSymbols dfs = DateFormatSymbols
3882                                    .getInstance(l);
3883                            ampm = dfs.getAmPmStrings();
3884                        }
3885                        String s = ampm[t.get(Calendar.AM_PM)];
3886                        sb.append(s.toLowerCase(l != null ? l : Locale.US));
3887                        break;
3888                    }
3889                    case DateTime.SECONDS_SINCE_EPOCH: { // 's' (0 - 99...?)
3890                        long i = t.getTimeInMillis() / 1000;
3891                        Flags flags = Flags.NONE;
3892                        sb.append(localizedMagnitude(null, i, flags, width, l));
3893                        break;
3894                    }
3895                    case DateTime.SECOND: { // 'S' (00 - 60 - leap second)
3896                        int i = t.get(Calendar.SECOND);
3897                        Flags flags = Flags.ZERO_PAD;
3898                        sb.append(localizedMagnitude(null, i, flags, 2, l));
3899                        break;
3900                    }
3901                    case DateTime.ZONE_NUMERIC: { // 'z' ({-|+}####) - ls minus?
3902                        int i = t.get(Calendar.ZONE_OFFSET);
3903                        boolean neg = i < 0;
3904                        sb.append(neg ? '-' : '+');
3905                        if (neg)
3906                            i = -i;
3907                        int min = i / 60000;
3908                        // combine minute and hour into a single integer
3909                        int offset = (min / 60) * 100 + (min % 60);
3910                        Flags flags = Flags.ZERO_PAD;
3911
3912                        sb
3913                                .append(localizedMagnitude(null, offset, flags,
3914                                        4, l));
3915                        break;
3916                    }
3917                    case DateTime.ZONE: { // 'Z' (symbol)
3918                        TimeZone tz = t.getTimeZone();
3919                        sb.append(tz.getDisplayName(
3920                                (t.get(Calendar.DST_OFFSET) != 0),
3921                                TimeZone.SHORT, (l == null) ? Locale.US : l));
3922                        break;
3923                    }
3924
3925                        // Date
3926                    case DateTime.NAME_OF_DAY_ABBREV: // 'a'
3927                    case DateTime.NAME_OF_DAY: { // 'A'
3928                        int i = t.get(Calendar.DAY_OF_WEEK);
3929                        Locale lt = ((l == null) ? Locale.US : l);
3930                        DateFormatSymbols dfs = DateFormatSymbols
3931                                .getInstance(lt);
3932                        if (c == DateTime.NAME_OF_DAY)
3933                            sb.append(dfs.getWeekdays()[i]);
3934                        else
3935                            sb.append(dfs.getShortWeekdays()[i]);
3936                        break;
3937                    }
3938                    case DateTime.NAME_OF_MONTH_ABBREV: // 'b'
3939                    case DateTime.NAME_OF_MONTH_ABBREV_X: // 'h' -- same b
3940                    case DateTime.NAME_OF_MONTH: { // 'B'
3941                        int i = t.get(Calendar.MONTH);
3942                        Locale lt = ((l == null) ? Locale.US : l);
3943                        DateFormatSymbols dfs = DateFormatSymbols
3944                                .getInstance(lt);
3945                        if (c == DateTime.NAME_OF_MONTH)
3946                            sb.append(dfs.getMonths()[i]);
3947                        else
3948                            sb.append(dfs.getShortMonths()[i]);
3949                        break;
3950                    }
3951                    case DateTime.CENTURY: // 'C' (00 - 99)
3952                    case DateTime.YEAR_2: // 'y' (00 - 99)
3953                    case DateTime.YEAR_4: { // 'Y' (0000 - 9999)
3954                        int i = t.get(Calendar.YEAR);
3955                        int size = 2;
3956                        switch (c) {
3957                        case DateTime.CENTURY:
3958                            i /= 100;
3959                            break;
3960                        case DateTime.YEAR_2:
3961                            i %= 100;
3962                            break;
3963                        case DateTime.YEAR_4:
3964                            size = 4;
3965                            break;
3966                        }
3967                        Flags flags = Flags.ZERO_PAD;
3968                        sb.append(localizedMagnitude(null, i, flags, size, l));
3969                        break;
3970                    }
3971                    case DateTime.DAY_OF_MONTH_0: // 'd' (01 - 31)
3972                    case DateTime.DAY_OF_MONTH: { // 'e' (1 - 31) -- like d
3973                        int i = t.get(Calendar.DATE);
3974                        Flags flags = (c == DateTime.DAY_OF_MONTH_0 ? Flags.ZERO_PAD
3975                                : Flags.NONE);
3976                        sb.append(localizedMagnitude(null, i, flags, 2, l));
3977                        break;
3978                    }
3979                    case DateTime.DAY_OF_YEAR: { // 'j' (001 - 366)
3980                        int i = t.get(Calendar.DAY_OF_YEAR);
3981                        Flags flags = Flags.ZERO_PAD;
3982                        sb.append(localizedMagnitude(null, i, flags, 3, l));
3983                        break;
3984                    }
3985                    case DateTime.MONTH: { // 'm' (01 - 12)
3986                        int i = t.get(Calendar.MONTH) + 1;
3987                        Flags flags = Flags.ZERO_PAD;
3988                        sb.append(localizedMagnitude(null, i, flags, 2, l));
3989                        break;
3990                    }
3991
3992                        // Composites
3993                    case DateTime.TIME: // 'T' (24 hour hh:mm:ss - %tH:%tM:%tS)
3994                    case DateTime.TIME_24_HOUR: { // 'R' (hh:mm same as %H:%M)
3995                        char sep = ':';
3996                        print(sb, t, DateTime.HOUR_OF_DAY_0, l).append(sep);
3997                        print(sb, t, DateTime.MINUTE, l);
3998                        if (c == DateTime.TIME) {
3999                            sb.append(sep);
4000                            print(sb, t, DateTime.SECOND, l);
4001                        }
4002                        break;
4003                    }
4004                    case DateTime.TIME_12_HOUR: { // 'r' (hh:mm:ss [AP]M)
4005                        char sep = ':';
4006                        print(sb, t, DateTime.HOUR_0, l).append(sep);
4007                        print(sb, t, DateTime.MINUTE, l).append(sep);
4008                        print(sb, t, DateTime.SECOND, l).append(' ');
4009                        // this may be in wrong place for some locales
4010                        StringBuilder tsb = new StringBuilder();
4011                        print(tsb, t, DateTime.AM_PM, l);
4012                        sb.append(tsb.toString().toUpperCase(
4013                                l != null ? l : Locale.US));
4014                        break;
4015                    }
4016                    case DateTime.DATE_TIME: { // 'c' (Sat Nov 04 12:02:33 EST 1999)
4017                        char sep = ' ';
4018                        print(sb, t, DateTime.NAME_OF_DAY_ABBREV, l)
4019                                .append(sep);
4020                        print(sb, t, DateTime.NAME_OF_MONTH_ABBREV, l).append(
4021                                sep);
4022                        print(sb, t, DateTime.DAY_OF_MONTH_0, l).append(sep);
4023                        print(sb, t, DateTime.TIME, l).append(sep);
4024                        print(sb, t, DateTime.ZONE, l).append(sep);
4025                        print(sb, t, DateTime.YEAR_4, l);
4026                        break;
4027                    }
4028                    case DateTime.DATE: { // 'D' (mm/dd/yy)
4029                        char sep = '/';
4030                        print(sb, t, DateTime.MONTH, l).append(sep);
4031                        print(sb, t, DateTime.DAY_OF_MONTH_0, l).append(sep);
4032                        print(sb, t, DateTime.YEAR_2, l);
4033                        break;
4034                    }
4035                    case DateTime.ISO_STANDARD_DATE: { // 'F' (%Y-%m-%d)
4036                        char sep = '-';
4037                        print(sb, t, DateTime.YEAR_4, l).append(sep);
4038                        print(sb, t, DateTime.MONTH, l).append(sep);
4039                        print(sb, t, DateTime.DAY_OF_MONTH_0, l);
4040                        break;
4041                    }
4042                    default:
4043                        assert false;
4044                    }
4045                    return sb;
4046                }
4047
4048                // -- Methods to support throwing exceptions --
4049
4050                private void failMismatch(Flags f, char c) {
4051                    String fs = f.toString();
4052                    throw new FormatFlagsConversionMismatchException(fs, c);
4053                }
4054
4055                private void failConversion(char c, Object arg) {
4056                    throw new IllegalFormatConversionException(c, arg
4057                            .getClass());
4058                }
4059
4060                private char getZero(Locale l) {
4061                    if ((l != null) && !l.equals(locale())) {
4062                        DecimalFormatSymbols dfs = DecimalFormatSymbols
4063                                .getInstance(l);
4064                        return dfs.getZeroDigit();
4065                    }
4066                    return zero;
4067                }
4068
4069                private StringBuilder localizedMagnitude(StringBuilder sb,
4070                        long value, Flags f, int width, Locale l) {
4071                    char[] va = Long.toString(value, 10).toCharArray();
4072                    return localizedMagnitude(sb, va, f, width, l);
4073                }
4074
4075                private StringBuilder localizedMagnitude(StringBuilder sb,
4076                        char[] value, Flags f, int width, Locale l) {
4077                    if (sb == null)
4078                        sb = new StringBuilder();
4079                    int begin = sb.length();
4080
4081                    char zero = getZero(l);
4082
4083                    // determine localized grouping separator and size
4084                    char grpSep = '\0';
4085                    int grpSize = -1;
4086                    char decSep = '\0';
4087
4088                    int len = value.length;
4089                    int dot = len;
4090                    for (int j = 0; j < len; j++) {
4091                        if (value[j] == '.') {
4092                            dot = j;
4093                            break;
4094                        }
4095                    }
4096
4097                    if (dot < len) {
4098                        if (l == null || l.equals(Locale.US)) {
4099                            decSep = '.';
4100                        } else {
4101                            DecimalFormatSymbols dfs = DecimalFormatSymbols
4102                                    .getInstance(l);
4103                            decSep = dfs.getDecimalSeparator();
4104                        }
4105                    }
4106
4107                    if (f.contains(Flags.GROUP)) {
4108                        if (l == null || l.equals(Locale.US)) {
4109                            grpSep = ',';
4110                            grpSize = 3;
4111                        } else {
4112                            DecimalFormatSymbols dfs = DecimalFormatSymbols
4113                                    .getInstance(l);
4114                            grpSep = dfs.getGroupingSeparator();
4115                            DecimalFormat df = (DecimalFormat) NumberFormat
4116                                    .getIntegerInstance(l);
4117                            grpSize = df.getGroupingSize();
4118                        }
4119                    }
4120
4121                    // localize the digits inserting group separators as necessary
4122                    for (int j = 0; j < len; j++) {
4123                        if (j == dot) {
4124                            sb.append(decSep);
4125                            // no more group separators after the decimal separator
4126                            grpSep = '\0';
4127                            continue;
4128                        }
4129
4130                        char c = value[j];
4131                        sb.append((char) ((c - '0') + zero));
4132                        if (grpSep != '\0' && j != dot - 1
4133                                && ((dot - j) % grpSize == 1))
4134                            sb.append(grpSep);
4135                    }
4136
4137                    // apply zero padding
4138                    len = sb.length();
4139                    if (width != -1 && f.contains(Flags.ZERO_PAD))
4140                        for (int k = 0; k < width - len; k++)
4141                            sb.insert(begin, zero);
4142
4143                    return sb;
4144                }
4145            }
4146
4147            private static class Flags {
4148                private int flags;
4149
4150                static final Flags NONE = new Flags(0); // ''
4151
4152                // duplicate declarations from Formattable.java
4153                static final Flags LEFT_JUSTIFY = new Flags(1 << 0); // '-'
4154                static final Flags UPPERCASE = new Flags(1 << 1); // '^'
4155                static final Flags ALTERNATE = new Flags(1 << 2); // '#'
4156
4157                // numerics
4158                static final Flags PLUS = new Flags(1 << 3); // '+'
4159                static final Flags LEADING_SPACE = new Flags(1 << 4); // ' '
4160                static final Flags ZERO_PAD = new Flags(1 << 5); // '0'
4161                static final Flags GROUP = new Flags(1 << 6); // ','
4162                static final Flags PARENTHESES = new Flags(1 << 7); // '('
4163
4164                // indexing
4165                static final Flags PREVIOUS = new Flags(1 << 8); // '<'
4166
4167                private Flags(int f) {
4168                    flags = f;
4169                }
4170
4171                public int valueOf() {
4172                    return flags;
4173                }
4174
4175                public boolean contains(Flags f) {
4176                    return (flags & f.valueOf()) == f.valueOf();
4177                }
4178
4179                public Flags dup() {
4180                    return new Flags(flags);
4181                }
4182
4183                private Flags add(Flags f) {
4184                    flags |= f.valueOf();
4185                    return this ;
4186                }
4187
4188                public Flags remove(Flags f) {
4189                    flags &= ~f.valueOf();
4190                    return this ;
4191                }
4192
4193                public static Flags parse(String s) {
4194                    char[] ca = s.toCharArray();
4195                    Flags f = new Flags(0);
4196                    for (int i = 0; i < ca.length; i++) {
4197                        Flags v = parse(ca[i]);
4198                        if (f.contains(v))
4199                            throw new DuplicateFormatFlagsException(v
4200                                    .toString());
4201                        f.add(v);
4202                    }
4203                    return f;
4204                }
4205
4206                // parse those flags which may be provided by users
4207                private static Flags parse(char c) {
4208                    switch (c) {
4209                    case '-':
4210                        return LEFT_JUSTIFY;
4211                    case '#':
4212                        return ALTERNATE;
4213                    case '+':
4214                        return PLUS;
4215                    case ' ':
4216                        return LEADING_SPACE;
4217                    case '0':
4218                        return ZERO_PAD;
4219                    case ',':
4220                        return GROUP;
4221                    case '(':
4222                        return PARENTHESES;
4223                    case '<':
4224                        return PREVIOUS;
4225                    default:
4226                        throw new UnknownFormatFlagsException(String.valueOf(c));
4227                    }
4228                }
4229
4230                // Returns a string representation of the current <tt>Flags</tt>.
4231                public static String toString(Flags f) {
4232                    return f.toString();
4233                }
4234
4235                public String toString() {
4236                    StringBuilder sb = new StringBuilder();
4237                    if (contains(LEFT_JUSTIFY))
4238                        sb.append('-');
4239                    if (contains(UPPERCASE))
4240                        sb.append('^');
4241                    if (contains(ALTERNATE))
4242                        sb.append('#');
4243                    if (contains(PLUS))
4244                        sb.append('+');
4245                    if (contains(LEADING_SPACE))
4246                        sb.append(' ');
4247                    if (contains(ZERO_PAD))
4248                        sb.append('0');
4249                    if (contains(GROUP))
4250                        sb.append(',');
4251                    if (contains(PARENTHESES))
4252                        sb.append('(');
4253                    if (contains(PREVIOUS))
4254                        sb.append('<');
4255                    return sb.toString();
4256                }
4257            }
4258
4259            private static class Conversion {
4260                // Byte, Short, Integer, Long, BigInteger
4261                // (and associated primitives due to autoboxing)
4262                static final char DECIMAL_INTEGER = 'd';
4263                static final char OCTAL_INTEGER = 'o';
4264                static final char HEXADECIMAL_INTEGER = 'x';
4265                static final char HEXADECIMAL_INTEGER_UPPER = 'X';
4266
4267                // Float, Double, BigDecimal
4268                // (and associated primitives due to autoboxing)
4269                static final char SCIENTIFIC = 'e';
4270                static final char SCIENTIFIC_UPPER = 'E';
4271                static final char GENERAL = 'g';
4272                static final char GENERAL_UPPER = 'G';
4273                static final char DECIMAL_FLOAT = 'f';
4274                static final char HEXADECIMAL_FLOAT = 'a';
4275                static final char HEXADECIMAL_FLOAT_UPPER = 'A';
4276
4277                // Character, Byte, Short, Integer
4278                // (and associated primitives due to autoboxing)
4279                static final char CHARACTER = 'c';
4280                static final char CHARACTER_UPPER = 'C';
4281
4282                // java.util.Date, java.util.Calendar, long
4283                static final char DATE_TIME = 't';
4284                static final char DATE_TIME_UPPER = 'T';
4285
4286                // if (arg.TYPE != boolean) return boolean
4287                // if (arg != null) return true; else return false;
4288                static final char BOOLEAN = 'b';
4289                static final char BOOLEAN_UPPER = 'B';
4290                // if (arg instanceof Formattable) arg.formatTo()
4291                // else arg.toString();
4292                static final char STRING = 's';
4293                static final char STRING_UPPER = 'S';
4294                // arg.hashCode()
4295                static final char HASHCODE = 'h';
4296                static final char HASHCODE_UPPER = 'H';
4297
4298                static final char LINE_SEPARATOR = 'n';
4299                static final char PERCENT_SIGN = '%';
4300
4301                static boolean isValid(char c) {
4302                    return (isGeneral(c) || isInteger(c) || isFloat(c)
4303                            || isText(c) || c == 't' || isCharacter(c));
4304                }
4305
4306                // Returns true iff the Conversion is applicable to all objects.
4307                static boolean isGeneral(char c) {
4308                    switch (c) {
4309                    case BOOLEAN:
4310                    case BOOLEAN_UPPER:
4311                    case STRING:
4312                    case STRING_UPPER:
4313                    case HASHCODE:
4314                    case HASHCODE_UPPER:
4315                        return true;
4316                    default:
4317                        return false;
4318                    }
4319                }
4320
4321                // Returns true iff the Conversion is applicable to character.
4322                static boolean isCharacter(char c) {
4323                    switch (c) {
4324                    case CHARACTER:
4325                    case CHARACTER_UPPER:
4326                        return true;
4327                    default:
4328                        return false;
4329                    }
4330                }
4331
4332                // Returns true iff the Conversion is an integer type.
4333                static boolean isInteger(char c) {
4334                    switch (c) {
4335                    case DECIMAL_INTEGER:
4336                    case OCTAL_INTEGER:
4337                    case HEXADECIMAL_INTEGER:
4338                    case HEXADECIMAL_INTEGER_UPPER:
4339                        return true;
4340                    default:
4341                        return false;
4342                    }
4343                }
4344
4345                // Returns true iff the Conversion is a floating-point type.
4346                static boolean isFloat(char c) {
4347                    switch (c) {
4348                    case SCIENTIFIC:
4349                    case SCIENTIFIC_UPPER:
4350                    case GENERAL:
4351                    case GENERAL_UPPER:
4352                    case DECIMAL_FLOAT:
4353                    case HEXADECIMAL_FLOAT:
4354                    case HEXADECIMAL_FLOAT_UPPER:
4355                        return true;
4356                    default:
4357                        return false;
4358                    }
4359                }
4360
4361                // Returns true iff the Conversion does not require an argument
4362                static boolean isText(char c) {
4363                    switch (c) {
4364                    case LINE_SEPARATOR:
4365                    case PERCENT_SIGN:
4366                        return true;
4367                    default:
4368                        return false;
4369                    }
4370                }
4371            }
4372
4373            private static class DateTime {
4374                static final char HOUR_OF_DAY_0 = 'H'; // (00 - 23)
4375                static final char HOUR_0 = 'I'; // (01 - 12)
4376                static final char HOUR_OF_DAY = 'k'; // (0 - 23) -- like H
4377                static final char HOUR = 'l'; // (1 - 12) -- like I
4378                static final char MINUTE = 'M'; // (00 - 59)
4379                static final char NANOSECOND = 'N'; // (000000000 - 999999999)
4380                static final char MILLISECOND = 'L'; // jdk, not in gnu (000 - 999)
4381                static final char MILLISECOND_SINCE_EPOCH = 'Q'; // (0 - 99...?)
4382                static final char AM_PM = 'p'; // (am or pm)
4383                static final char SECONDS_SINCE_EPOCH = 's'; // (0 - 99...?)
4384                static final char SECOND = 'S'; // (00 - 60 - leap second)
4385                static final char TIME = 'T'; // (24 hour hh:mm:ss)
4386                static final char ZONE_NUMERIC = 'z'; // (-1200 - +1200) - ls minus?
4387                static final char ZONE = 'Z'; // (symbol)
4388
4389                // Date
4390                static final char NAME_OF_DAY_ABBREV = 'a'; // 'a'
4391                static final char NAME_OF_DAY = 'A'; // 'A'
4392                static final char NAME_OF_MONTH_ABBREV = 'b'; // 'b'
4393                static final char NAME_OF_MONTH = 'B'; // 'B'
4394                static final char CENTURY = 'C'; // (00 - 99)
4395                static final char DAY_OF_MONTH_0 = 'd'; // (01 - 31)
4396                static final char DAY_OF_MONTH = 'e'; // (1 - 31) -- like d
4397                // *    static final char ISO_WEEK_OF_YEAR_2    = 'g'; // cross %y %V
4398                // *    static final char ISO_WEEK_OF_YEAR_4    = 'G'; // cross %Y %V
4399                static final char NAME_OF_MONTH_ABBREV_X = 'h'; // -- same b
4400                static final char DAY_OF_YEAR = 'j'; // (001 - 366)
4401                static final char MONTH = 'm'; // (01 - 12)
4402                // *    static final char DAY_OF_WEEK_1         = 'u'; // (1 - 7) Monday
4403                // *    static final char WEEK_OF_YEAR_SUNDAY   = 'U'; // (0 - 53) Sunday+
4404                // *    static final char WEEK_OF_YEAR_MONDAY_01 = 'V'; // (01 - 53) Monday+
4405                // *    static final char DAY_OF_WEEK_0         = 'w'; // (0 - 6) Sunday
4406                // *    static final char WEEK_OF_YEAR_MONDAY   = 'W'; // (00 - 53) Monday
4407                static final char YEAR_2 = 'y'; // (00 - 99)
4408                static final char YEAR_4 = 'Y'; // (0000 - 9999)
4409
4410                // Composites
4411                static final char TIME_12_HOUR = 'r'; // (hh:mm:ss [AP]M)
4412                static final char TIME_24_HOUR = 'R'; // (hh:mm same as %H:%M)
4413                // *    static final char LOCALE_TIME   = 'X'; // (%H:%M:%S) - parse format?
4414                static final char DATE_TIME = 'c';
4415                // (Sat Nov 04 12:02:33 EST 1999)
4416                static final char DATE = 'D'; // (mm/dd/yy)
4417                static final char ISO_STANDARD_DATE = 'F'; // (%Y-%m-%d)
4418                // *    static final char LOCALE_DATE           = 'x'; // (mm/dd/yy)
4419
4420                static boolean isValid(char c) {
4421                    switch (c) {
4422                    case HOUR_OF_DAY_0:
4423                    case HOUR_0:
4424                    case HOUR_OF_DAY:
4425                    case HOUR:
4426                    case MINUTE:
4427                    case NANOSECOND:
4428                    case MILLISECOND:
4429                    case MILLISECOND_SINCE_EPOCH:
4430                    case AM_PM:
4431                    case SECONDS_SINCE_EPOCH:
4432                    case SECOND:
4433                    case TIME:
4434                    case ZONE_NUMERIC:
4435                    case ZONE:
4436
4437                        // Date
4438                    case NAME_OF_DAY_ABBREV:
4439                    case NAME_OF_DAY:
4440                    case NAME_OF_MONTH_ABBREV:
4441                    case NAME_OF_MONTH:
4442                    case CENTURY:
4443                    case DAY_OF_MONTH_0:
4444                    case DAY_OF_MONTH:
4445                        // *        case ISO_WEEK_OF_YEAR_2:
4446                        // *        case ISO_WEEK_OF_YEAR_4:
4447                    case NAME_OF_MONTH_ABBREV_X:
4448                    case DAY_OF_YEAR:
4449                    case MONTH:
4450                        // *        case DAY_OF_WEEK_1:
4451                        // *        case WEEK_OF_YEAR_SUNDAY:
4452                        // *        case WEEK_OF_YEAR_MONDAY_01:
4453                        // *        case DAY_OF_WEEK_0:
4454                        // *        case WEEK_OF_YEAR_MONDAY:
4455                    case YEAR_2:
4456                    case YEAR_4:
4457
4458                        // Composites
4459                    case TIME_12_HOUR:
4460                    case TIME_24_HOUR:
4461                        // *        case LOCALE_TIME:
4462                    case DATE_TIME:
4463                    case DATE:
4464                    case ISO_STANDARD_DATE:
4465                        // *        case LOCALE_DATE:
4466                        return true;
4467                    default:
4468                        return false;
4469                    }
4470                }
4471            }
4472        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.