1 /*****************************************************************************************
3 * Copyright (C) 1996-2013, International Business Machines
4 * Corporation and others. All Rights Reserved.
8 * Port From: JDK 1.4b1 : java.text.Format.NumberRegression
9 * Source File: java/text/format/NumberRegression.java
14 * @bug 4052223 4059870 4061302 4062486 4066646 4068693 4070798 4071005 4071014
15 * 4071492 4071859 4074454 4074620 4075713 4083018 4086575 4087244 4087245
16 * 4087251 4087535 4088161 4088503 4090489 4090504 4092480 4092561 4095713
17 * 4098741 4099404 4101481 4106658 4106662 4106664 4108738 4110936 4122840
18 * 4125885 4134034 4134300 4140009 4141750 4145457 4147295 4147706 4162198
19 * 4162852 4167494 4170798 4176114 4179818 4185761 4212072 4212073 4216742
20 * 4217661 4243011 4243108 4330377 4233840
21 * @summary Regression tests for NumberFormat and associated classes
24 package com.ibm.icu.dev.test.format;
26 import java.io.ByteArrayInputStream;
27 import java.io.ByteArrayOutputStream;
28 import java.io.IOException;
29 import java.io.InvalidObjectException;
30 import java.io.ObjectInputStream;
31 import java.io.ObjectOutputStream;
32 import java.io.Serializable;
33 import java.math.BigInteger;
34 import java.text.FieldPosition;
35 import java.text.ParseException;
36 import java.text.ParsePosition;
37 import java.util.Date;
38 import java.util.Locale;
40 import com.ibm.icu.impl.ICUResourceBundle;
41 import com.ibm.icu.text.DateFormat;
42 import com.ibm.icu.text.DecimalFormat;
43 import com.ibm.icu.text.DecimalFormatSymbols;
44 import com.ibm.icu.text.NumberFormat;
45 import com.ibm.icu.util.GregorianCalendar;
46 import com.ibm.icu.util.ULocale;
47 import com.ibm.icu.util.VersionInfo;
49 public class NumberRegression extends com.ibm.icu.dev.test.TestFmwk {
51 public static void main(String[] args) throws Exception {
52 new NumberRegression().run(args);
55 private static final char EURO = '\u20ac';
58 * NumberFormat.equals comparing with null should always return false.
60 public void Test4075713(){
63 MyNumberFormatTest tmp = new MyNumberFormatTest();
64 if (!tmp.equals(null))
65 logln("NumberFormat.equals passed");
66 } catch (NullPointerException e) {
67 errln("(new MyNumberFormatTest()).equals(null) throws unexpected exception");
72 * NumberFormat.equals comparing two obj equal even the setGroupingUsed
75 public void Test4074620() {
77 MyNumberFormatTest nf1 = new MyNumberFormatTest();
78 MyNumberFormatTest nf2 = new MyNumberFormatTest();
80 nf1.setGroupingUsed(false);
81 nf2.setGroupingUsed(true);
83 if (nf1.equals(nf2)) errln("Test for bug 4074620 failed");
84 else logln("Test for bug 4074620 passed.");
90 * DecimalFormat.format() incorrectly uses maxFractionDigits setting.
93 public void Test4088161 (){
94 DecimalFormat df = new DecimalFormat();
96 df.setMinimumFractionDigits(0);
97 df.setMaximumFractionDigits(16);
98 StringBuffer sBuf1 = new StringBuffer("");
99 FieldPosition fp1 = new FieldPosition(0);
101 logln("maxFractionDigits = " + df.getMaximumFractionDigits());
102 logln(" format(d) = '" + df.format(d, sBuf1, fp1) + "'");
103 df.setMaximumFractionDigits(17);
104 StringBuffer sBuf2 = new StringBuffer("");
105 FieldPosition fp2 = new FieldPosition(0);
106 logln("maxFractionDigits = " + df.getMaximumFractionDigits());
107 df.format(d, sBuf2, fp2);
108 if (!sBuf2.toString().equals("100"))
109 errln(" format(d) = '" + sBuf2 + "'");
112 * DecimalFormatSymbols should be cloned in the ctor DecimalFormat.
113 * DecimalFormat(String, DecimalFormatSymbols).
115 public void Test4087245 (){
116 DecimalFormatSymbols symbols = new DecimalFormatSymbols();
117 DecimalFormat df = new DecimalFormat("#,##0.0", symbols);
119 StringBuffer buf1 = new StringBuffer();
120 StringBuffer buf2 = new StringBuffer();
121 logln("format(" + n + ") = " +
122 df.format(n, buf1, new FieldPosition(0)));
123 symbols.setDecimalSeparator('p'); // change value of field
124 logln("format(" + n + ") = " +
125 df.format(n, buf2, new FieldPosition(0)));
126 if (!buf1.toString().equals(buf2.toString()))
127 errln("Test for bug 4087245 failed");
130 * DecimalFormat.format() incorrectly formats 0.0
132 public void Test4087535 ()
134 DecimalFormat df = new DecimalFormat();
135 df.setMinimumIntegerDigits(0);
138 String buffer = new String();
139 buffer = df.format(n);
140 if (buffer.length() == 0)
141 errln(n + ": '" + buffer + "'");
143 buffer = df.format(n);
144 if (buffer.length() == 0)
145 errln(n + ": '" + buffer + "'");
149 * DecimalFormat.format fails when groupingSize is set to 0.
151 public void Test4088503 (){
152 DecimalFormat df = new DecimalFormat();
153 df.setGroupingSize(0);
154 StringBuffer sBuf = new StringBuffer("");
155 FieldPosition fp = new FieldPosition(0);
157 logln(df.format(123, sBuf, fp).toString());
158 } catch (Exception foo) {
159 errln("Test for bug 4088503 failed.");
164 * NumberFormat.getCurrencyInstance is wrong.
166 public void Test4066646 () {
167 //float returnfloat = 0.0f; //The variable is never used
168 assignFloatValue(2.04f);
169 assignFloatValue(2.03f);
170 assignFloatValue(2.02f);
171 assignFloatValue(0.0f);
174 public float assignFloatValue(float returnfloat)
176 logln(" VALUE " + returnfloat);
177 NumberFormat nfcommon = NumberFormat.getCurrencyInstance(Locale.US);
178 nfcommon.setGroupingUsed(false);
180 String stringValue = nfcommon.format(returnfloat).substring(1);
181 if (Float.valueOf(stringValue).floatValue() != returnfloat)
182 errln(" DISPLAYVALUE " + stringValue);
184 } // End Of assignFloatValue()
187 * DecimalFormat throws exception when parsing "0"
189 public void Test4059870() {
190 DecimalFormat format = new DecimalFormat("00");
192 logln(format.parse("0").toString());
193 } catch (Exception e) { errln("Test for bug 4059870 failed : " + e); }
196 * DecimalFormatSymbol.equals should always return false when
197 * comparing with null.
200 public void Test4083018 (){
201 DecimalFormatSymbols dfs = new DecimalFormatSymbols();
203 if (!dfs.equals(null))
204 logln("Test Passed!");
205 } catch (Exception foo) {
206 errln("Test for bug 4083018 failed => Message : " + foo.getMessage());
210 * DecimalFormat does not round up correctly.
212 public void Test4071492 (){
213 double x = 0.00159999;
214 NumberFormat nf = NumberFormat.getInstance();
215 nf.setMaximumFractionDigits(4);
216 String out = nf.format(x);
217 logln("0.00159999 formats with 4 fractional digits to " + out);
218 String expected = "0.0016";
219 if (!out.equals(expected))
220 errln("FAIL: Expected " + expected);
224 * A space as a group separator for localized pattern causes
225 * wrong format. WorkAround : use non-breaking space.
227 public void Test4086575() {
229 NumberFormat nf = NumberFormat.getInstance(Locale.FRANCE);
230 logln("nf toPattern1: " + ((DecimalFormat)nf).toPattern());
231 logln("nf toLocPattern1: " + ((DecimalFormat)nf).toLocalizedPattern());
233 // No group separator
234 logln("...applyLocalizedPattern ###,00;(###,00) ");
235 ((DecimalFormat)nf).applyLocalizedPattern("###,00;(###,00)");
236 logln("nf toPattern2: " + ((DecimalFormat)nf).toPattern());
237 logln("nf toLocPattern2: " + ((DecimalFormat)nf).toLocalizedPattern());
239 logln("nf: " + nf.format(1234)); // 1234,00
240 logln("nf: " + nf.format(-1234)); // (1234,00)
242 // Space as group separator
244 logln("...applyLocalizedPattern # ###,00;(# ###,00) ");
245 ((DecimalFormat)nf).applyLocalizedPattern("#\u00a0###,00;(#\u00a0###,00)");
246 logln("nf toPattern2: " + ((DecimalFormat)nf).toPattern());
247 logln("nf toLocPattern2: " + ((DecimalFormat)nf).toLocalizedPattern());
248 String buffer = nf.format(1234);
249 if (!buffer.equals("1\u00a0234,00"))
250 errln("nf : " + buffer); // Expect 1 234,00
251 buffer = nf.format(-1234);
252 if (!buffer.equals("(1\u00a0234,00)"))
253 errln("nf : " + buffer); // Expect (1 234,00)
255 // Erroneously prints:
261 * DecimalFormat.parse returns wrong value
263 public void Test4068693()
265 logln("----- Test Application -----");
267 DecimalFormat df = new DecimalFormat();
268 Number d = df.parse("123.55456", new ParsePosition(0));
269 if (!d.toString().equals("123.55456")) {
270 errln("Result -> " + d.doubleValue());
274 /* bugs 4069754, 4067878
275 * null pointer thrown when accessing a deserialized DecimalFormat
278 public void Test4069754() throws Exception
281 ByteArrayOutputStream baos = new ByteArrayOutputStream();
282 ObjectOutputStream oos = new ObjectOutputStream(baos);
283 myformat it = new myformat();
289 byte [] bytes = baos.toByteArray();
290 ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
291 myformat o = (myformat)ois.readObject();
295 if (!o._dateFormat.equals(it._dateFormat)) {
296 throw new Exception("The saved and loaded object are not equals!");
298 logln("Compare OK!");
299 //} catch (Exception foo) {
300 //errln("Test for bug 4069754 or 4057878 failed => Exception: " + foo.getMessage());
305 * DecimalFormat.applyPattern(String) allows illegal patterns
307 public void Test4087251 (){
308 DecimalFormat df = new DecimalFormat();
310 df.applyPattern("#.#.#");
311 logln("toPattern() returns \"" + df.toPattern() + "\"");
312 errln("applyPattern(\"#.#.#\") doesn't throw IllegalArgumentException");
313 } catch (IllegalArgumentException e) {
314 logln("Caught Illegal Argument Error !");
316 // Second test; added 5/11/98 when reported to fail on 1.2b3
318 df.applyPattern("#0.0#0#0");
319 logln("toPattern() returns \"" + df.toPattern() + "\"");
320 errln("applyPattern(\"#0.0#0#0\") doesn't throw IllegalArgumentException");
321 } catch (IllegalArgumentException e) {
322 logln("Ok - IllegalArgumentException for #0.0#0#0");
327 * DecimalFormat.format() loses precision
329 public void Test4090489 (){
330 DecimalFormat df = new DecimalFormat();
331 df.setMinimumFractionDigits(10);
332 df.setGroupingUsed(false);
333 double d = 1.000000000000001E7;
334 java.math.BigDecimal bd = new java.math.BigDecimal(d);
335 StringBuffer sb = new StringBuffer("");
336 FieldPosition fp = new FieldPosition(0);
338 logln("BigDecimal.toString(): " + bd.toString());
339 df.format(d, sb, fp);
340 if (!sb.toString().equals("10000000.0000000100")) {
341 errln("DecimalFormat.format(): " + sb.toString());
346 * DecimalFormat.format() loses precision
348 public void Test4090504 ()
352 DecimalFormat df = new DecimalFormat();
356 for (int i = 17; i <= 20; i++) {
357 df.setMaximumFractionDigits(i);
358 sb = new StringBuffer("");
359 fp = new FieldPosition(0);
360 logln(" getMaximumFractionDigits() = " + i);
361 logln(" formated: " + df.format(d, sb, fp));
363 } catch (Exception foo) {
364 errln("Bug 4090504 regression test failed. Message : " + foo.getMessage());
368 * DecimalFormat.parse(String str, ParsePosition pp) loses precision
370 public void Test4095713 ()
372 DecimalFormat df = new DecimalFormat();
373 String str = "0.1234";
374 Double d1 = new Double(str);
375 Number d2 = df.parse(str, new ParsePosition(0));
376 logln(d1.toString());
377 if (d2.doubleValue() != d1.doubleValue())
378 errln("Bug 4095713 test failed, new double value : " + d2.doubleValue());
382 * DecimalFormat.parse() fails when multiplier is not set to 1
384 public void Test4092561 ()
386 Locale savedLocale = Locale.getDefault();
387 Locale.setDefault(Locale.US);
388 DecimalFormat df = new DecimalFormat();
389 String str = Long.toString(Long.MIN_VALUE);
390 logln("Long.MIN_VALUE : " + df.parse(str, new ParsePosition(0)).toString());
391 df.setMultiplier(100);
392 Number num = df.parse(str, new ParsePosition(0));
393 if (num.doubleValue() != -9.223372036854776E16) {
394 errln("Bug 4092561 test failed when multiplier is set to not 1.");
396 Locale.setDefault(savedLocale);
400 * DecimalFormat: Negative format ignored.
402 public void Test4092480 ()
404 DecimalFormat dfFoo = new DecimalFormat("000");
407 dfFoo.applyPattern("0000;-000");
408 if (!dfFoo.toPattern().equals("#0000"))
409 errln("dfFoo.toPattern : " + dfFoo.toPattern());
410 logln(dfFoo.format(42));
411 logln(dfFoo.format(-42));
412 dfFoo.applyPattern("000;-000");
413 if (!dfFoo.toPattern().equals("#000"))
414 errln("dfFoo.toPattern : " + dfFoo.toPattern());
415 logln(dfFoo.format(42));
416 logln(dfFoo.format(-42));
418 dfFoo.applyPattern("000;-0000");
419 if (!dfFoo.toPattern().equals("#000"))
420 errln("dfFoo.toPattern : " + dfFoo.toPattern());
421 logln(dfFoo.format(42));
422 logln(dfFoo.format(-42));
424 dfFoo.applyPattern("0000;-000");
425 if (!dfFoo.toPattern().equals("#0000"))
426 errln("dfFoo.toPattern : " + dfFoo.toPattern());
427 logln(dfFoo.format(42));
428 logln(dfFoo.format(-42));
429 } catch (Exception foo) {
430 errln("Message " + foo.getMessage());
434 * NumberFormat.getCurrencyInstance() produces format that uses
435 * decimal separator instead of monetary decimal separator.
437 * Rewrote this test not to depend on the actual pattern. Pattern should
438 * never contain the monetary separator! Decimal separator in pattern is
439 * interpreted as monetary separator if currency symbol is seen!
441 public void Test4087244 () {
442 Locale de = new Locale("pt", "PT");
443 DecimalFormat df = (DecimalFormat) NumberFormat.getCurrencyInstance(de);
444 DecimalFormatSymbols sym = df.getDecimalFormatSymbols();
445 sym.setMonetaryDecimalSeparator('$');
446 df.setDecimalFormatSymbols(sym);
447 char decSep = sym.getDecimalSeparator();
448 char monSep = sym.getMonetaryDecimalSeparator();
449 //char zero = sym.getZeroDigit(); //The variable is never used
450 if (decSep == monSep) {
451 errln("ERROR in test: want decimal sep != monetary sep");
453 df.setMinimumIntegerDigits(1);
454 df.setMinimumFractionDigits(2);
455 String str = df.format(1.23);
456 String monStr = "1" + monSep + "23";
457 String decStr = "1" + decSep + "23";
458 if (str.indexOf(monStr) >= 0 && str.indexOf(decStr) < 0) {
459 logln("OK: 1.23 -> \"" + str + "\" contains \"" +
460 monStr + "\" and not \"" + decStr + '"');
462 errln("FAIL: 1.23 -> \"" + str + "\", should contain \"" +
464 "\" and not \"" + decStr + '"');
469 * Number format data rounding errors for locale FR
471 public void Test4070798 () {
472 NumberFormat formatter;
475 String expectedDefault = "-5\u00a0789,987";
476 String expectedCurrency = "5\u00a0789,98\u00a0F";
477 String expectedPercent = "-578\u00a0998%";
479 String expectedDefault = "-5\u00a0789,988";
480 String expectedCurrency = "5\u00a0789,99\u00a0" + EURO; // euro
481 String expectedPercent = "-578\u00a0999\u00a0%";
483 formatter = NumberFormat.getNumberInstance(Locale.FRANCE);
484 tempString = formatter.format (-5789.9876);
486 if (tempString.equals(expectedDefault)) {
487 logln ("Bug 4070798 default test passed.");
490 " Expected " + expectedDefault +
491 " Received " + tempString );
495 formatter = NumberFormat.getCurrencyInstance(Locale.FRANCE);
496 tempString = formatter.format( 5789.9876 );
498 if (tempString.equals(expectedCurrency) ) {
499 logln ("Bug 4070798 currency test assed.");
502 " Expected " + expectedCurrency +
503 " Received " + tempString );
507 formatter = NumberFormat.getPercentInstance(Locale.FRANCE);
508 tempString = formatter.format (-5789.9876);
510 if (tempString.equals(expectedPercent) ) {
511 logln ("Bug 4070798 percentage test passed.");
514 " Expected " + expectedPercent +
515 " Received " + tempString );
519 * Data rounding errors for French (Canada) locale
521 public void Test4071005 () {
523 NumberFormat formatter;
526 String expectedDefault = "-5 789,987";
527 String expectedCurrency = "5 789,98\u00a0$";
528 String expectedPercent = "-578 998%";
530 String expectedDefault = "-5\u00a0789,988";
531 String expectedCurrency = "5\u00a0789,99\u00a0$";
532 String expectedPercent = "-578\u00a0999\u00A0%";
534 formatter = NumberFormat.getNumberInstance(Locale.CANADA_FRENCH);
535 tempString = formatter.format (-5789.9876);
536 if (tempString.equals(expectedDefault)) {
537 logln ("Bug 4071005 default test passed.");
540 " Expected " + expectedDefault +
541 " Received " + tempString );
544 formatter = NumberFormat.getCurrencyInstance(Locale.CANADA_FRENCH);
545 tempString = formatter.format( 5789.9876 ) ;
547 if (tempString.equals(expectedCurrency) ) {
548 logln ("Bug 4071005 currency test passed.");
551 " Expected " + expectedCurrency +
552 " Received " + tempString );
554 formatter = NumberFormat.getPercentInstance(Locale.CANADA_FRENCH);
555 tempString = formatter.format (-5789.9876);
557 if (tempString.equals(expectedPercent) ) {
558 logln ("Bug 4071005 percentage test passed.");
561 " Expected " + expectedPercent +
562 " Received " + tempString );
567 * Data rounding errors for German (Germany) locale
569 public void Test4071014 () {
570 NumberFormat formatter;
573 String expectedDefault = "-5.789,987";
574 String expectedCurrency = "5.789,98\u00a0DM";
575 String expectedPercent = "-578.998%";
577 String expectedDefault = "-5.789,988";
578 String expectedCurrency = "5.789,99\u00a0" + EURO;
579 String expectedPercent = "-578.999\u00a0%";
581 formatter = NumberFormat.getNumberInstance(Locale.GERMANY);
582 tempString = formatter.format (-5789.9876);
584 if (tempString.equals(expectedDefault)) {
585 logln ("Bug 4071014 default test passed.");
588 " Expected " + expectedDefault +
589 " Received " + tempString );
592 formatter = NumberFormat.getCurrencyInstance(Locale.GERMANY);
593 tempString = formatter.format( 5789.9876 ) ;
595 if (tempString.equals(expectedCurrency) ) {
596 logln ("Bug 4071014 currency test passed.");
599 " Expected " + expectedCurrency +
600 " Received " + tempString );
603 formatter = NumberFormat.getPercentInstance(Locale.GERMANY);
604 tempString = formatter.format (-5789.9876);
606 if (tempString.equals(expectedPercent) ) {
607 logln ("Bug 4071014 percentage test passed.");
610 " Expected " + expectedPercent +
611 " Received " + tempString );
616 * Data rounding errors for Italian locale number formats
617 * Note- with the Euro, there is no need for currency rounding anymore
619 public void Test4071859 () {
620 NumberFormat formatter;
623 String expectedDefault = "-5.789,987";
624 String expectedCurrency = "-L.\u00a05.789,98";
625 String expectedPercent = "-578.998%";
627 String expectedDefault = "-5.789,988";
628 String expectedCurrency = "-5.789,99\u00A0" + EURO;
629 String expectedPercent = "-578.999%";
631 formatter = NumberFormat.getNumberInstance(Locale.ITALY);
632 tempString = formatter.format (-5789.9876);
634 if (tempString.equals(expectedDefault)) {
635 logln ("Bug 4071859 default test passed.");
638 " Expected " + expectedDefault +
639 " Received " + tempString );
642 formatter = NumberFormat.getCurrencyInstance(Locale.ITALY);
643 tempString = formatter.format( -5789.9876 ) ;
645 if (tempString.equals(expectedCurrency) ) {
646 logln ("Bug 4071859 currency test passed.");
649 " Expected " + expectedCurrency +
650 " Received " + tempString );
653 formatter = NumberFormat.getPercentInstance(Locale.ITALY);
654 tempString = formatter.format (-5789.9876);
656 if (tempString.equals(expectedPercent) ) {
657 logln ("Bug 4071859 percentage test passed.");
660 " Expected " + expectedPercent +
661 " Received " + tempString );
666 * Test rounding for nearest even.
668 public void Test4093610()
670 DecimalFormat df = new DecimalFormat("#0.#");
671 roundingTest(df, 12.35, "12.4");
672 roundingTest(df, 12.45, "12.4");
673 roundingTest(df, 12.452,"12.5");
674 roundingTest(df, 12.55, "12.6");
675 roundingTest(df, 12.65, "12.6");
676 roundingTest(df, 12.652,"12.7");
677 roundingTest(df, 12.75, "12.8");
678 roundingTest(df, 12.752,"12.8");
679 roundingTest(df, 12.85, "12.8");
680 roundingTest(df, 12.852,"12.9");
681 roundingTest(df, 12.95, "13");
682 roundingTest(df, 12.952,"13");
685 void roundingTest(DecimalFormat df, double x, String expected)
687 String out = df.format(x);
688 logln("" + x + " formats with 1 fractional digits to " + out);
689 if (!out.equals(expected)) errln("FAIL: Expected " + expected);
692 * Tests the setMaximumFractionDigits limit.
694 public void Test4098741()
697 NumberFormat fmt = NumberFormat.getPercentInstance();
698 fmt.setMaximumFractionDigits(20);
699 logln(fmt.format(.001));
700 } catch (Exception foo) {
701 warnln("Bug 4098471 failed with exception thrown : " + foo.getMessage());
705 * Tests illegal pattern exception.
706 * Fix comment : HShih A31 Part1 will not be fixed and javadoc needs to be updated.
707 * Part2 has been fixed.
709 public void Test4074454()
712 DecimalFormat fmt = new DecimalFormat("#,#00.00;-#.#");
713 logln("format 3456.78: " + fmt.format(3456.78)); //fix "The variable 'fmt' is never used"
714 logln("Inconsistent negative pattern is fine.");
715 DecimalFormat newFmt = new DecimalFormat("#,#00.00 p''ieces;-#,#00.00 p''ieces");
716 String tempString = newFmt.format(3456.78);
717 if (!tempString.equals("3,456.78 p'ieces"))
718 errln("Failed! 3456.78 p'ieces expected, but got : " + tempString);
719 } catch (Exception foo) {
720 warnln("An exception was thrown for any inconsistent negative pattern.");
724 * Tests all different comments.
725 * Response to some comments :
726 * [1] DecimalFormat.parse API documentation is more than just one line.
727 * This is not a reproducable doc error in 116 source code.
728 * [2] See updated javadoc.
730 * [4] NumberFormat.parse(String, ParsePosition) : If parsing fails,
731 * a null object will be returned. The unchanged parse position also
733 * NumberFormat.parse(String) : If parsing fails, an ParseException
735 * See updated javadoc for more details.
736 * [5] See updated javadoc.
737 * [6] See updated javadoc.
738 * [7] This is a correct behavior if the DateFormat object is linient.
739 * Otherwise, an IllegalArgumentException will be thrown when formatting
740 * "January 35". See GregorianCalendar class javadoc for more details.
742 public void Test4099404()
745 DecimalFormat fmt = new DecimalFormat("000.0#0");
746 logln("format 3456.78: " + fmt.format(3456.78)); //fix "The variable 'fmt' is never used"
747 errln("Bug 4099404 failed applying illegal pattern \"000.0#0\"");
748 } catch (Exception foo) {
749 logln("Bug 4099404 pattern \"000.0#0\" passed");
752 DecimalFormat fmt = new DecimalFormat("0#0.000");
753 logln("format 3456.78: " + fmt.format(3456.78)); //fix "The variable 'fmt' is never used"
754 errln("Bug 4099404 failed applying illegal pattern \"0#0.000\"");
755 } catch (Exception foo) {
756 logln("Bug 4099404 pattern \"0#0.000\" passed");
760 * DecimalFormat.applyPattern doesn't set minimum integer digits
762 public void Test4101481()
764 DecimalFormat sdf = new DecimalFormat("#,##0");
765 if (sdf.getMinimumIntegerDigits() != 1)
766 errln("Minimum integer digits : " + sdf.getMinimumIntegerDigits());
769 * Tests ParsePosition.setErrorPosition() and ParsePosition.getErrorPosition().
771 public void Test4052223()
774 DecimalFormat fmt = new DecimalFormat("#,#00.00");
775 Number num = fmt.parse("abc3");
776 errln("Bug 4052223 failed : can't parse string \"a\". Got " + num);
777 } catch (ParseException foo) {
778 logln("Caught expected ParseException : " + foo.getMessage() + " at index : " + foo.getErrorOffset());
782 * API tests for API addition request A9.
784 public void Test4061302()
786 DecimalFormatSymbols fmt = new DecimalFormatSymbols();
787 String currency = fmt.getCurrencySymbol();
788 String intlCurrency = fmt.getInternationalCurrencySymbol();
789 char monDecSeparator = fmt.getMonetaryDecimalSeparator();
790 if (currency.equals("") ||
791 intlCurrency.equals("") ||
792 monDecSeparator == 0) {
793 errln("getCurrencySymbols failed, got empty string.");
795 logln("Before set ==> Currency : " + currency + " Intl Currency : " + intlCurrency + " Monetary Decimal Separator : " + monDecSeparator);
796 fmt.setCurrencySymbol("XYZ");
797 fmt.setInternationalCurrencySymbol("ABC");
798 fmt.setMonetaryDecimalSeparator('*');
799 currency = fmt.getCurrencySymbol();
800 intlCurrency = fmt.getInternationalCurrencySymbol();
801 monDecSeparator = fmt.getMonetaryDecimalSeparator();
802 if (!currency.equals("XYZ") ||
803 !intlCurrency.equals("ABC") ||
804 monDecSeparator != '*') {
805 errln("setCurrencySymbols failed.");
807 logln("After set ==> Currency : " + currency + " Intl Currency : " + intlCurrency + " Monetary Decimal Separator : " + monDecSeparator);
810 * API tests for API addition request A23. FieldPosition.getBeginIndex and
811 * FieldPosition.getEndIndex.
813 public void Test4062486()
815 DecimalFormat fmt = new DecimalFormat("#,##0.00");
816 StringBuffer formatted = new StringBuffer();
817 FieldPosition field = new FieldPosition(0);
818 Double num = new Double(1234.5);
819 fmt.format(num, formatted, field);
820 if (field.getBeginIndex() != 0 && field.getEndIndex() != 5)
821 errln("Format 1234.5 failed. Begin index: " + field.getBeginIndex() + " End index: " + field.getEndIndex());
822 field.setBeginIndex(7);
823 field.setEndIndex(4);
824 if (field.getBeginIndex() != 7 && field.getEndIndex() != 4)
825 errln("Set begin/end field indexes failed. Begin index: " + field.getBeginIndex() + " End index: " + field.getEndIndex());
829 * DecimalFormat.parse incorrectly works with a group separator.
831 public void Test4108738()
834 DecimalFormat df = new DecimalFormat("#,##0.###", new
835 DecimalFormatSymbols(java.util.Locale.US));
836 String text = "1.222,111";
837 Number num = df.parse(text,new ParsePosition(0));
838 if (!num.toString().equals("1.222"))
839 errln("\"" + text + "\" is parsed as " + num);
841 num = df.parse(text,new ParsePosition(0));
842 if (!num.toString().equals("1.222"))
843 errln("\"" + text + "\" is parsed as " + num);
847 * DecimalFormat.format() incorrectly formats negative doubles.
849 public void Test4106658()
851 Locale savedLocale = Locale.getDefault();
852 Locale.setDefault(Locale.US);
853 DecimalFormat df = new DecimalFormat(); // Corrected; see 4147706
856 StringBuffer buffer = new StringBuffer();
857 logln("pattern: \"" + df.toPattern() + "\"");
858 df.format(d1, buffer, new FieldPosition(0));
859 if (!buffer.toString().equals("-0")) { // Corrected; see 4147706
860 errln(d1 + " is formatted as " + buffer);
863 df.format(d2, buffer, new FieldPosition(0));
864 if (!buffer.toString().equals("-0")) { // Corrected; see 4147706
865 errln(d2 + " is formatted as " + buffer);
867 Locale.setDefault(savedLocale);
871 * DecimalFormat.parse returns 0 if string parameter is incorrect.
873 public void Test4106662()
875 DecimalFormat df = new DecimalFormat();
877 ParsePosition pos1 = new ParsePosition(0), pos2 = new ParsePosition(0);
879 logln("pattern: \"" + df.toPattern() + "\"");
880 Number num = df.parse(text, pos1);
882 errln("Test Failed: \"" + text + "\" is parsed as " + num);
885 df = new DecimalFormat("$###.00");
886 num = df.parse("$", pos2);
888 errln("Test Failed: \"$\" is parsed as " + num);
893 * NumberFormat.parse doesn't return null
895 public void Test4114639()
897 NumberFormat format = NumberFormat.getInstance();
898 String text = "time 10:x";
899 ParsePosition pos = new ParsePosition(8);
900 Number result = format.parse(text, pos);
901 if (result != null) errln("Should return null but got : " + result); // Should be null; it isn't
905 * DecimalFormat.format(long n) fails if n * multiplier > MAX_LONG.
907 public void Test4106664()
909 DecimalFormat df = new DecimalFormat();
910 long n = 1234567890123456L;
912 BigInteger bigN = BigInteger.valueOf(n);
913 bigN = bigN.multiply(BigInteger.valueOf(m));
915 df.setGroupingUsed(false);
917 df.format(n, new StringBuffer(), new FieldPosition(0)));
918 logln("expected: " + bigN.toString());
921 * DecimalFormat.format incorrectly formats -0.0.
923 public void Test4106667()
925 Locale savedLocale = Locale.getDefault();
926 Locale.setDefault(Locale.US);
927 DecimalFormat df = new DecimalFormat();
928 df.setPositivePrefix("+");
930 logln("pattern: \"" + df.toPattern() + "\"");
931 StringBuffer buffer = new StringBuffer();
932 df.format(d, buffer, new FieldPosition(0));
933 if (!buffer.toString().equals("-0")) { // Corrected; see 4147706
934 errln(d + " is formatted as " + buffer);
936 Locale.setDefault(savedLocale);
940 * DecimalFormat.setMaximumIntegerDigits() works incorrectly.
942 public void Test4110936()
944 NumberFormat nf = NumberFormat.getInstance();
945 nf.setMaximumIntegerDigits(128);
946 logln("setMaximumIntegerDigits(128)");
947 if (nf.getMaximumIntegerDigits() != 128)
948 errln("getMaximumIntegerDigits() returns " +
949 nf.getMaximumIntegerDigits());
953 * Locale data should use generic currency symbol
955 * 1) Make sure that all currency formats use the generic currency symbol.
956 * 2) Make sure we get the same results using the generic symbol or a
959 public void Test4122840()
961 Locale[] locales = NumberFormat.getAvailableLocales();
963 for (int i = 0; i < locales.length; i++) {
964 ICUResourceBundle rb = (ICUResourceBundle)ICUResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME,locales[i]);
967 // Get the currency pattern for this locale. We have to fish it
968 // out of the ResourceBundle directly, since DecimalFormat.toPattern
969 // will return the localized symbol, not \00a4
971 String pattern = rb.getStringWithFallback("NumberElements/latn/patterns/currencyFormat");
972 if (pattern.indexOf('\u00A4') == -1 ) { // 'x' not "x" -- workaround bug in IBM JDK 1.4.1
973 errln("Currency format for " + locales[i] +
974 " does not contain generic currency symbol:" +
978 // Create a DecimalFormat using the pattern we got and format a number
979 DecimalFormatSymbols symbols = new DecimalFormatSymbols(locales[i]);
980 DecimalFormat fmt1 = new DecimalFormat(pattern, symbols);
982 String result1 = fmt1.format(1.111);
985 // Now substitute in the locale's currency symbol and create another
986 // pattern. Replace the decimal separator with the monetary separator.
988 //char decSep = symbols.getDecimalSeparator(); //The variable is never used
989 char monSep = symbols.getMonetaryDecimalSeparator();
990 StringBuffer buf = new StringBuffer(pattern);
991 for (int j = 0; j < buf.length(); j++) {
992 if (buf.charAt(j) == '\u00a4') {
993 String cur = "'" + symbols.getCurrencySymbol() + "'";
994 buf.replace(j, j+1, cur);
995 j += cur.length() - 1;
998 symbols.setDecimalSeparator(monSep);
999 DecimalFormat fmt2 = new DecimalFormat(buf.toString(), symbols);
1001 // Actual width of decimal fractions and rounding option are inherited
1002 // from the currency, not the pattern itself. So we need to force
1003 // maximum/minimumFractionDigits and rounding option for the second
1004 // DecimalForamt instance. The fix for ticket#7282 requires this test
1005 // code change to make it work properly.
1006 fmt2.setMaximumFractionDigits(fmt1.getMaximumFractionDigits());
1007 fmt2.setMinimumFractionDigits(fmt1.getMinimumFractionDigits());
1008 fmt2.setRoundingIncrement(fmt1.getRoundingIncrement());
1010 String result2 = fmt2.format(1.111);
1012 // NOTE: en_IN is a special case (ChoiceFormat currency display name)
1013 if (!result1.equals(result2) &&
1014 !locales[i].toString().equals("en_IN")) {
1015 errln("Results for " + locales[i] + " differ: " +
1016 result1 + " vs " + result2);
1022 * DecimalFormat.format() delivers wrong string.
1024 public void Test4125885()
1026 double rate = 12.34;
1027 DecimalFormat formatDec = new DecimalFormat ("000.00");
1028 logln("toPattern: " + formatDec.toPattern());
1029 String rateString= formatDec.format(rate);
1030 if (!rateString.equals("012.34"))
1031 errln("result : " + rateString + " expected : 012.34");
1034 formatDec = new DecimalFormat ("+000.00%;-000.00%");
1035 logln("toPattern: " + formatDec.toPattern());
1036 rateString= formatDec.format(rate);
1037 if (!rateString.equals("+012.34%"))
1038 errln("result : " + rateString + " expected : +012.34%");
1043 * DecimalFormat produces extra zeros when formatting numbers.
1045 public void Test4134034() {
1046 DecimalFormat nf = new DecimalFormat("##,###,###.00");
1048 String f = nf.format(9.02);
1049 if (f.equals("9.02")) logln(f + " ok"); else errln("9.02 -> " + f + "; want 9.02");
1052 if (f.equals(".00")) logln(f + " ok"); else errln("0 -> " + f + "; want .00");
1056 * CANNOT REPRODUCE - This bug could not be reproduced. It may be
1057 * a duplicate of 4134034.
1059 * JDK 1.1.6 Bug, did NOT occur in 1.1.5
1060 * Possibly related to bug 4125885.
1062 * This class demonstrates a regression in version 1.1.6
1063 * of DecimalFormat class.
1066 * Value 1.2 Format #.00 Result '01.20' !!!wrong
1067 * Value 1.2 Format 0.00 Result '001.20' !!!wrong
1068 * Value 1.2 Format 00.00 Result '0001.20' !!!wrong
1069 * Value 1.2 Format #0.0# Result '1.2'
1070 * Value 1.2 Format #0.00 Result '001.20' !!!wrong
1073 * Value 1.2 Format #.00 Result '1.20'
1074 * Value 1.2 Format 0.00 Result '1.20'
1075 * Value 1.2 Format 00.00 Result '01.20'
1076 * Value 1.2 Format #0.0# Result '1.2'
1077 * Value 1.2 Format #0.00 Result '1.20'
1079 public void Test4134300() {
1081 // Pattern Expected string
1088 for (int i=0; i<DATA.length; i+=2) {
1089 String result = new DecimalFormat(DATA[i]).format(1.2);
1090 if (!result.equals(DATA[i+1])) {
1091 errln("Fail: 1.2 x " + DATA[i] + " = " + result +
1092 "; want " + DATA[i+1]);
1095 logln("Ok: 1.2 x " + DATA[i] + " = " + result);
1101 * Empty pattern produces double negative prefix.
1103 public void Test4140009() {
1104 final double IN[] = { 123.456, -123.456 };
1105 final String OUT[] = { "123.456", "-123.456" };
1106 for (int i=0; i<2; ++i) {
1107 DecimalFormat f = null;
1110 f = new DecimalFormat("",
1111 new DecimalFormatSymbols(Locale.ENGLISH));
1114 f = new DecimalFormat("#.#",
1115 new DecimalFormatSymbols(Locale.ENGLISH));
1119 for (int j=0; j<2; ++j) {
1120 assertEquals("<empty pat " + i + ">.format(" + IN[j] + ")",
1121 OUT[j], f.format(IN[j]));
1127 * BigDecimal numbers get their fractions truncated by NumberFormat.
1129 public void Test4141750() {
1131 String str = "12345.67";
1132 java.math.BigDecimal bd = new java.math.BigDecimal(str);
1133 String sd = NumberFormat.getInstance(Locale.US).format(bd);
1134 if (!sd.endsWith("67")) errln("Fail: " + str + " x format -> " + sd);
1136 catch (Exception e) {
1137 warnln(e.toString());
1138 //e.printStackTrace();
1143 * DecimalFormat toPattern() doesn't quote special characters or handle
1146 public void Test4145457() {
1148 DecimalFormat nf = (DecimalFormat)NumberFormat.getInstance();
1149 DecimalFormatSymbols sym = nf.getDecimalFormatSymbols();
1150 sym.setDecimalSeparator('\'');
1151 nf.setDecimalFormatSymbols(sym);
1152 double pi = 3.14159;
1154 String[] PATS = { "#.00 'num''ber'", "''#.00''" };
1156 for (int i=0; i<PATS.length; ++i) {
1157 nf.applyPattern(PATS[i]);
1158 String out = nf.format(pi);
1159 String pat = nf.toPattern();
1160 double val = nf.parse(out).doubleValue();
1162 nf.applyPattern(pat);
1163 String out2 = nf.format(pi);
1164 String pat2 = nf.toPattern();
1165 double val2 = nf.parse(out2).doubleValue();
1167 if (!pat.equals(pat2))
1168 errln("Fail with \"" + PATS[i] + "\": Patterns should concur, \"" +
1169 pat + "\" vs. \"" + pat2 + "\"");
1171 logln("Ok \"" + PATS[i] + "\" toPattern() -> \"" + pat + '"');
1173 if (val == val2 && out.equals(out2)) {
1174 logln("Ok " + pi + " x \"" + PATS[i] + "\" -> \"" +
1175 out + "\" -> " + val + " -> \"" +
1176 out2 + "\" -> " + val2);
1179 errln("Fail " + pi + " x \"" + PATS[i] + "\" -> \"" +
1180 out + "\" -> " + val + " -> \"" +
1181 out2 + "\" -> " + val2);
1185 catch (ParseException e) {
1186 errln("Fail: " + e);
1187 e.printStackTrace();
1192 * DecimalFormat.applyPattern() sets minimum integer digits incorrectly.
1194 * This bug is a duplicate of 4139344, which is a duplicate of 4134300
1196 public void Test4147295() {
1197 DecimalFormat sdf = new DecimalFormat();
1198 String pattern = "#,###";
1199 logln("Applying pattern \"" + pattern + "\"");
1200 sdf.applyPattern(pattern);
1201 int minIntDig = sdf.getMinimumIntegerDigits();
1202 if (minIntDig != 0) {
1203 errln("Test failed");
1204 errln(" Minimum integer digits : " + minIntDig);
1205 errln(" new pattern: " + sdf.toPattern());
1207 logln("Test passed");
1208 logln(" Minimum integer digits : " + minIntDig);
1213 * DecimalFormat formats -0.0 as +0.0
1214 * See also older related bug 4106658, 4106667
1216 public void Test4147706() {
1217 DecimalFormat df = new DecimalFormat("#,##0.0##");
1218 df.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.ENGLISH));
1220 double d2 = -0.0001;
1221 StringBuffer f1 = df.format(d1, new StringBuffer(), new FieldPosition(0));
1222 StringBuffer f2 = df.format(d2, new StringBuffer(), new FieldPosition(0));
1223 if (!f1.toString().equals("-0.0")) {
1224 errln(d1 + " x \"" + df.toPattern() + "\" is formatted as \"" + f1 + '"');
1226 if (!f2.toString().equals("-0.0")) {
1227 errln(d2 + " x \"" + df.toPattern() + "\" is formatted as \"" + f2 + '"');
1232 * NumberFormat cannot format Double.MAX_VALUE
1234 public void Test4162198() {
1235 double dbl = Double.MAX_VALUE;
1236 NumberFormat f = NumberFormat.getInstance();
1237 f.setMaximumFractionDigits(Integer.MAX_VALUE);
1238 f.setMaximumIntegerDigits(Integer.MAX_VALUE);
1239 String s = f.format(dbl);
1240 logln("The number " + dbl + " formatted to " + s);
1244 } catch (java.text.ParseException e) {
1245 errln("Caught a ParseException:");
1246 e.printStackTrace();
1248 logln("The string " + s + " parsed as " + n);
1249 if (n.doubleValue() != dbl) {
1250 errln("Round trip failure");
1255 * NumberFormat does not parse negative zero.
1257 public void Test4162852() throws ParseException {
1258 for (int i=0; i<2; ++i) {
1259 NumberFormat f = (i == 0) ? NumberFormat.getInstance()
1260 : NumberFormat.getPercentInstance();
1262 String s = f.format(d);
1263 double e = f.parse(s).doubleValue();
1266 '"' + s + '"' + " -> " +
1268 if (e != 0.0 || 1.0/e > 0.0) {
1269 logln("Failed to parse negative zero");
1275 * NumberFormat truncates data
1277 public void Test4167494() throws Exception {
1278 NumberFormat fmt = NumberFormat.getInstance(Locale.US);
1280 double a = Double.MAX_VALUE;
1281 String s = fmt.format(a);
1282 double b = fmt.parse(s).doubleValue();
1283 boolean match = a == b;
1285 logln("" + a + " -> \"" + s + "\" -> " + b + " ok");
1287 errln("" + a + " -> \"" + s + "\" -> " + b + " FAIL");
1290 // We don't test Double.MIN_VALUE because the locale data for the US
1291 // currently doesn't specify enough digits to display Double.MIN_VALUE.
1292 // This is correct for now; however, we leave this here as a reminder
1293 // in case we want to address this later.
1295 a = Double.MIN_VALUE;
1297 b = fmt.parse(s).doubleValue();
1300 logln("" + a + " -> \"" + s + "\" -> " + b + " ok");
1302 errln("" + a + " -> \"" + s + "\" -> " + b + " FAIL");
1308 * DecimalFormat.parse() fails when ParseIntegerOnly set to true
1310 public void Test4170798() {
1311 Locale savedLocale = Locale.getDefault();
1312 Locale.setDefault(Locale.US);
1313 DecimalFormat df = new DecimalFormat();
1314 df.setParseIntegerOnly(true);
1315 Number n = df.parse("-0.0", new ParsePosition(0));
1316 if (!(n instanceof Double)
1317 || n.intValue() != 0) {
1318 errln("FAIL: parse(\"-0.0\") returns " +
1319 n + " (" + n.getClass().getName() + ')');
1321 Locale.setDefault(savedLocale);
1325 * toPattern only puts the first grouping separator in.
1327 public void Test4176114() {
1330 "000", "#000", // No grouping
1331 "#000", "#000", // No grouping
1335 "00,000", "#00,000",
1336 "000,000", "#,000,000",
1337 "0,000,000,000,000.0000", "#0,000,000,000,000.0000", // Reported
1339 for (int i=0; i<DATA.length; i+=2) {
1340 DecimalFormat df = new DecimalFormat(DATA[i]);
1341 String s = df.toPattern();
1342 if (!s.equals(DATA[i+1])) {
1343 errln("FAIL: " + DATA[i] + " -> " + s + ", want " + DATA[i+1]);
1349 * DecimalFormat is incorrectly rounding numbers like 1.2501 to 1.2
1351 public void Test4179818() {
1353 // Input Pattern Expected output
1354 "1.2511", "#.#", "1.3",
1355 "1.2501", "#.#", "1.3",
1358 DecimalFormat fmt = new DecimalFormat("#",
1359 new DecimalFormatSymbols(Locale.US));
1360 for (int i=0; i<DATA.length; i+=3) {
1361 double in = Double.valueOf(DATA[i]).doubleValue();
1362 String pat = DATA[i+1];
1363 String exp = DATA[i+2];
1364 fmt.applyPattern(pat);
1365 String out = fmt.format(in);
1366 if (out.equals(exp)) {
1367 logln("Ok: " + in + " x " + pat + " = " + out);
1369 errln("FAIL: " + in + " x " + pat + " = " + out +
1370 ", expected " + exp);
1375 public void Test4185761() throws IOException, ClassNotFoundException {
1376 ByteArrayOutputStream baos = new ByteArrayOutputStream();
1377 ObjectOutputStream oos = new ObjectOutputStream(baos);
1379 NumberFormat nf = NumberFormat.getInstance(Locale.US);
1381 // Set special values we are going to search for in the output byte stream
1382 // These are all legal values.
1383 nf.setMinimumIntegerDigits(0x111); // Keep under 309
1384 nf.setMaximumIntegerDigits(0x112); // Keep under 309
1385 nf.setMinimumFractionDigits(0x113); // Keep under 340
1386 nf.setMaximumFractionDigits(0x114); // Keep under 340
1388 oos.writeObject(nf);
1392 byte[] bytes = baos.toByteArray();
1394 // Scan for locations of min/max int/fract values in the byte array.
1395 // At the moment (ICU4J 2.1), there is only one instance of each target pair
1396 // in the byte stream, so assume first match is it. Note this is not entirely
1397 // failsafe, and needs to be checked if we change the package or structure of
1399 // Current positions are 890, 880, 886, 876
1400 int[] offsets = new int[4];
1401 for (int i = 0; i < bytes.length - 1; ++i) {
1402 if (bytes[i] == 0x01) { // high byte
1403 for (int j = 0; j < offsets.length; ++j) {
1404 if ((offsets[j] == 0) && (bytes[i+1] == (0x11 + j))) { // low byte
1413 ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
1414 Object o = ois.readObject();
1417 if (!nf.equals(o)) {
1418 errln("Fail: NumberFormat serialization/equality bug");
1420 logln("NumberFormat serialization/equality is OKAY.");
1424 // Change the values in the byte stream so that min > max.
1425 // Numberformat should catch this and throw an exception.
1426 for (int i = 0; i < offsets.length; ++i) {
1427 bytes[offsets[i]] = (byte)(4 - i);
1431 ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
1433 NumberFormat format = (NumberFormat) ois.readObject();
1434 logln("format: " + format.format(1234.56)); //fix "The variable is never used"
1435 errln("FAIL: Deserialized bogus NumberFormat with minXDigits > maxXDigits");
1436 } catch (InvalidObjectException e) {
1437 logln("Ok: " + e.getMessage());
1441 // Set values so they are too high, but min <= max
1442 // Format should pass the min <= max test, and DecimalFormat should reset to current maximum
1443 // (for compatibility with versions streamed out before the maximums were imposed).
1444 for (int i = 0; i < offsets.length; ++i) {
1445 bytes[offsets[i]] = 4;
1449 ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
1450 NumberFormat format = (NumberFormat) ois.readObject();
1451 //For compatibility with previous version
1452 if ((format.getMaximumIntegerDigits() != 309)
1453 || format.getMaximumFractionDigits() != 340) {
1454 errln("FAIL: Deserialized bogus NumberFormat with values out of range," +
1455 " intMin: " + format.getMinimumIntegerDigits() +
1456 " intMax: " + format.getMaximumIntegerDigits() +
1457 " fracMin: " + format.getMinimumFractionDigits() +
1458 " fracMax: " + format.getMaximumFractionDigits());
1460 logln("Ok: Digit count out of range");
1467 * Some DecimalFormatSymbols changes are not picked up by DecimalFormat.
1468 * This includes the minus sign, currency symbol, international currency
1469 * symbol, percent, and permille. This is filed as bugs 4212072 and
1472 public void Test4212072() throws IOException, ClassNotFoundException {
1473 DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
1474 DecimalFormat fmt = new DecimalFormat("#", sym);
1476 sym.setMinusSign('^');
1477 fmt.setDecimalFormatSymbols(sym);
1478 if (!fmt.format(-1).equals("^1")) {
1479 errln("FAIL: -1 x (minus=^) -> " + fmt.format(-1) +
1482 if (!fmt.getNegativePrefix().equals("^")) {
1483 errln("FAIL: (minus=^).getNegativePrefix -> " +
1484 fmt.getNegativePrefix() + ", exp ^");
1486 sym.setMinusSign('-');
1488 fmt.applyPattern("#%");
1489 sym.setPercent('^');
1490 fmt.setDecimalFormatSymbols(sym);
1491 if (!fmt.format(0.25).equals("25^")) {
1492 errln("FAIL: 0.25 x (percent=^) -> " + fmt.format(0.25) +
1495 if (!fmt.getPositiveSuffix().equals("^")) {
1496 errln("FAIL: (percent=^).getPositiveSuffix -> " +
1497 fmt.getPositiveSuffix() + ", exp ^");
1499 sym.setPercent('%');
1501 fmt.applyPattern("#\u2030");
1502 sym.setPerMill('^');
1503 fmt.setDecimalFormatSymbols(sym);
1504 if (!fmt.format(0.25).equals("250^")) {
1505 errln("FAIL: 0.25 x (permill=^) -> " + fmt.format(0.25) +
1508 if (!fmt.getPositiveSuffix().equals("^")) {
1509 errln("FAIL: (permill=^).getPositiveSuffix -> " +
1510 fmt.getPositiveSuffix() + ", exp ^");
1512 sym.setPerMill('\u2030');
1514 fmt.applyPattern("\u00A4#.00");
1515 sym.setCurrencySymbol("usd");
1516 fmt.setDecimalFormatSymbols(sym);
1517 if (!fmt.format(12.5).equals("usd12.50")) {
1518 errln("FAIL: 12.5 x (currency=usd) -> " + fmt.format(12.5) +
1521 if (!fmt.getPositivePrefix().equals("usd")) {
1522 errln("FAIL: (currency=usd).getPositivePrefix -> " +
1523 fmt.getPositivePrefix() + ", exp usd");
1525 sym.setCurrencySymbol("$");
1527 fmt.applyPattern("\u00A4\u00A4#.00");
1528 sym.setInternationalCurrencySymbol("DOL");
1529 fmt.setDecimalFormatSymbols(sym);
1530 if (!fmt.format(12.5).equals("DOL12.50")) {
1531 errln("FAIL: 12.5 x (intlcurrency=DOL) -> " + fmt.format(12.5) +
1534 if (!fmt.getPositivePrefix().equals("DOL")) {
1535 errln("FAIL: (intlcurrency=DOL).getPositivePrefix -> " +
1536 fmt.getPositivePrefix() + ", exp DOL");
1538 sym.setInternationalCurrencySymbol("USD");
1540 if (VersionInfo.ICU_VERSION == VersionInfo.getInstance(2,2)) {
1541 // bug in 2.2 that fails this test
1542 // to be fixed in the later versions
1543 System.out.println("\n Test skipped for release 2.2");
1547 // Since the pattern logic has changed, make sure that patterns round
1548 // trip properly. Test stream in/out integrity too.
1549 Locale[] avail = NumberFormat.getAvailableLocales();
1550 for (int i=0; i<avail.length; ++i) {
1551 for (int j=0; j<3; ++j) {
1555 nf = NumberFormat.getInstance(avail[i]);
1558 nf = NumberFormat.getCurrencyInstance(avail[i]);
1561 nf = NumberFormat.getPercentInstance(avail[i]);
1564 DecimalFormat df = (DecimalFormat) nf;
1566 // Test toPattern/applyPattern round trip
1567 String pat = df.toPattern();
1568 DecimalFormatSymbols symb = new DecimalFormatSymbols(avail[i]);
1569 DecimalFormat f2 = new DecimalFormat(pat, symb);
1570 if (!df.equals(f2)) {
1571 errln("FAIL: " + avail[i] + " #" + j + " -> \"" + pat +
1572 "\" -> \"" + f2.toPattern() + '"');
1575 // Test toLocalizedPattern/applyLocalizedPattern round trip
1576 pat = df.toLocalizedPattern();
1578 f2.applyLocalizedPattern(pat);
1580 String s1 = f2.format(123456);
1581 String s2 = df.format(123456);
1583 errln("FAIL: " + avail[i] + " #" + j + " -> localized \"" + s2 +
1584 "\" -> \"" + s2 + '"'+ " in locale "+df.getLocale(ULocale.ACTUAL_LOCALE));
1587 if (!df.equals(f2)) {
1588 errln("FAIL: " + avail[i] + " #" + j + " -> localized \"" + pat +
1589 "\" -> \"" + f2.toLocalizedPattern() + '"'+ " in locale "+df.getLocale(ULocale.ACTUAL_LOCALE));
1590 errln("s1: "+s1+" s2: "+s2);
1593 }catch(IllegalArgumentException ex){
1594 errln(ex.getMessage()+" for locale "+ df.getLocale(ULocale.ACTUAL_LOCALE));
1598 // Test writeObject/readObject round trip
1599 ByteArrayOutputStream baos = new ByteArrayOutputStream();
1600 ObjectOutputStream oos = new ObjectOutputStream(baos);
1601 oos.writeObject(df);
1604 byte[] bytes = baos.toByteArray();
1605 ObjectInputStream ois =
1606 new ObjectInputStream(new ByteArrayInputStream(bytes));
1607 f2 = (DecimalFormat) ois.readObject();
1608 if (!df.equals(f2)) {
1609 errln("FAIL: Stream in/out " + avail[i] + " -> \"" + pat +
1611 (f2 != null ? ("\""+f2.toPattern()+'"') : "null"));
1618 // Make sure that all special characters, when quoted in a suffix or
1619 // prefix, lose their special meaning.
1620 char[] SPECIALS = { '0', ',', '.', '\u2030', '%', '#',
1621 ';', 'E', '*', '+', '-' };
1622 sym = new DecimalFormatSymbols(Locale.US);
1623 for (int j=0; j<SPECIALS.length; ++j) {
1624 char special = SPECIALS[j];
1625 String pat = "'" + special + "'#0'" + special + "'";
1627 fmt = new DecimalFormat(pat, sym);
1628 String pat2 = fmt.toPattern();
1629 if (!pat.equals(pat2)) {
1630 errln("FAIL: Pattern \"" + pat + "\" => toPattern() => \"" +
1633 String s = fmt.format(123);
1634 String exp = "" + special + "123" + special;
1635 if (!s.equals(exp)) {
1636 errln("FAIL: 123 x \"" + pat + "\" => \"" + s + "\", exp \"" +
1639 } catch (IllegalArgumentException e) {
1640 errln("FAIL: Pattern \"" + pat + "\" => " + e.getMessage());
1646 * DecimalFormat.parse() fails for mulipliers 2^n.
1648 public void Test4216742() throws ParseException {
1649 DecimalFormat fmt = (DecimalFormat) NumberFormat.getInstance(Locale.US);
1650 long[] DATA = { Long.MIN_VALUE, Long.MAX_VALUE, -100000000L, 100000000L};
1651 for (int i=0; i<DATA.length; ++i) {
1652 String str = Long.toString(DATA[i]);
1653 for (int m = 1; m <= 100; m++) {
1654 fmt.setMultiplier(m);
1655 long n = ((Number) fmt.parse(str)).longValue();
1656 if (n > 0 != DATA[i] > 0) {
1657 errln("\"" + str + "\" parse(x " + fmt.getMultiplier() +
1665 * DecimalFormat formats 1.001 to "1.00" instead of "1" with 2 fraction
1668 public void Test4217661() {
1670 new Double(0.001), "0",
1671 new Double(1.001), "1",
1672 new Double(0.006), "0.01",
1673 new Double(1.006), "1.01",
1675 NumberFormat fmt = NumberFormat.getInstance(Locale.US);
1676 fmt.setMaximumFractionDigits(2);
1677 for (int i=0; i<DATA.length; i+=2) {
1678 String s = fmt.format(((Double) DATA[i]).doubleValue());
1679 if (!s.equals(DATA[i+1])) {
1680 errln("FAIL: Got " + s + ", exp " + DATA[i+1]);
1686 * 4243011: Formatting .5 rounds to "1" instead of "0"
1688 public void Test4243011() {
1689 double DATA[] = {0.5, 1.5, 2.5, 3.5, 4.5};
1690 String EXPECTED[] = {"0.", "2.", "2.", "4.", "4."};
1692 DecimalFormat format = new DecimalFormat("0.");
1693 for (int i = 0; i < DATA.length; i++) {
1694 String result = format.format(DATA[i]);
1695 if (result.equals(EXPECTED[i])) {
1696 logln("OK: got " + result);
1698 errln("FAIL: got " + result);
1704 * 4243108: format(0.0) gives "0.1" if preceded by parse("99.99")
1706 public void Test4243108() {
1707 DecimalFormat f = new DecimalFormat("#.#");
1708 String result = f.format(0.0);
1709 if (result.equals("0")) {
1710 logln("OK: got " + result);
1712 errln("FAIL: got " + result);
1715 double dResult = f.parse("99.99").doubleValue();
1716 if (dResult == 99.99) {
1717 logln("OK: got " + dResult);
1719 errln("FAIL: got " + dResult);
1721 } catch (ParseException e) {
1722 errln("Caught a ParseException:");
1723 e.printStackTrace();
1725 result = f.format(0.0);
1726 if (result.equals("0")) {
1727 logln("OK: got " + result);
1729 errln("FAIL: got " + result);
1734 * 4330377: DecimalFormat engineering notation gives incorrect results
1736 public void test4330377() {
1738 double[] input = {5000.0, 500.0, 50.0, 5.0, 0.5, 0.05, 0.005, 0.0005,
1739 5050.0, 505.0, 50.5, 5.05, 0.505, 0.0505, 0.00505, 0.000505};
1740 String[] pattern = {"000.#E0", "##0.#E0", "#00.#E0"};
1741 String[][] expected = {
1742 // it's questionable whether "#00.#E0" should result in post-decimal
1743 // zeroes, i.e., whether "5.0E3", "5.0E0", "5.0E-3" are really good
1744 {"500E1", "5E3", "5.0E3"},
1745 {"500E0", "500E0", "500E0"},
1746 {"500E-1", "50E0", "50E0"},
1747 {"500E-2", "5E0", "5.0E0"},
1748 {"500E-3", "500E-3", "500E-3"},
1749 {"500E-4", "50E-3", "50E-3"},
1750 {"500E-5", "5E-3", "5.0E-3"},
1751 {"500E-6", "500E-6", "500E-6"},
1752 {"505E1", "5.05E3", "5.05E3"},
1753 {"505E0", "505E0", "505E0"},
1754 {"505E-1", "50.5E0", "50.5E0"},
1755 {"505E-2", "5.05E0", "5.05E0"},
1756 {"505E-3", "505E-3", "505E-3"},
1757 {"505E-4", "50.5E-3", "50.5E-3"},
1758 {"505E-5", "5.05E-3", "5.05E-3"},
1759 {"505E-6", "505E-6", "505E-6"}
1761 for (int i = 0; i < input.length; i++) {
1762 for (int j = 0; j < pattern.length; j++) {
1763 DecimalFormat format = new DecimalFormat(pattern[j]);
1764 String result = format.format(input[i]);
1765 if (!result.equals(expected[i][j])) {
1766 errln("FAIL: input: " + input[i] +
1767 ", pattern: " + pattern[j] +
1768 ", expected: " + expected[i][j] +
1769 ", got: " + result);
1777 * 4233840: NumberFormat does not round correctly
1779 public void test4233840() {
1782 NumberFormat nf = new DecimalFormat("0.##", new DecimalFormatSymbols(Locale.US));
1783 nf.setMinimumFractionDigits(2);
1785 String result = nf.format(f);
1787 if (!result.equals("0.01")) {
1788 errln("FAIL: input: " + f + ", expected: 0.01, got: " + result);
1793 * 4241880: Decimal format doesnt round a double properly when the number is less than 1
1795 public void test4241880() {
1796 Locale savedLocale = Locale.getDefault();
1797 Locale.setDefault(Locale.US);
1799 .019, .009, .015, .016, .014,
1800 .004, .005, .006, .007, .008,
1801 .5, 1.5, .05, .15, .005,
1804 String[] pattern = {
1805 "##0%", "##0%", "##0%", "##0%", "##0%",
1806 "##0%", "##0%", "##0%", "##0%", "##0%",
1807 "#,##0", "#,##0", "#,##0.0", "#,##0.0", "#,##0.00",
1808 "#,##0.00", "#,##0.000", "#,##0.000",
1810 String[] expected = {
1811 "2%", "1%", "2%", "2%", "1%",
1812 "0%", "0%", "1%", "1%", "1%",
1813 "0", "2", "0.0", "0.2", "0.00",
1814 "0.02", "0.000", "0.002",
1816 for (int i = 0; i < input.length; i++) {
1817 DecimalFormat format = new DecimalFormat(pattern[i]);
1818 String result = format.format(input[i]);
1819 if (!result.equals(expected[i])) {
1820 errln("FAIL: input: " + input[i] +
1821 ", pattern: " + pattern[i] +
1822 ", expected: " + expected[i] +
1823 ", got: " + result);
1826 Locale.setDefault(savedLocale);
1830 class myformat implements Serializable
1835 private static final long serialVersionUID = 4120813612616076506L;
1836 DateFormat _dateFormat = DateFormat.getDateInstance();
1840 GregorianCalendar calendar = new GregorianCalendar();
1841 Date t = calendar.getTime();
1842 String nowStr = _dateFormat.format(t);
1847 class MyNumberFormatTest extends NumberFormat {
1851 private static final long serialVersionUID = 1251303884737169952L;
1852 public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
1853 return new StringBuffer("");
1855 public StringBuffer format(long number,StringBuffer toAppendTo, FieldPosition pos) {
1856 return new StringBuffer("");
1858 public Number parse(String text, ParsePosition parsePosition) {
1859 return new Integer(0);
1861 public StringBuffer format(java.math.BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) {
1862 return new StringBuffer("");
1864 public StringBuffer format(BigInteger number, StringBuffer toAppendTo, FieldPosition pos) {
1865 return new StringBuffer("");
1867 public StringBuffer format(com.ibm.icu.math.BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) {
1868 return new StringBuffer("");