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