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