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