1/*
2 * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/**
25 * @test
26 * @bug 4823811 8008577
27 * @summary Confirm that text which includes numbers with a trailing minus sign is parsed correctly.
28 * @modules jdk.localedata
29 * @run main/othervm -Duser.timezone=GMT+09:00 -Djava.locale.providers=JRE,SPI Bug4823811
30 */
31
32import java.text.*;
33import java.util.*;
34
35public class Bug4823811 {
36
37    private static Locale localeEG = new Locale("ar", "EG");
38    private static Locale localeUS = Locale.US;
39
40    private static String JuneInArabic = "\u064a\u0648\u0646\u064a\u0648";
41    private static String JulyInArabic = "\u064a\u0648\u0644\u064a\u0648";
42    private static String JuneInEnglish = "June";
43    private static String JulyInEnglish = "July";
44
45    private static String BORDER =
46        "============================================================";
47
48    /*
49     * I don't use static import here intentionally so that this test program
50     * can be run on JDK 1.4.2.
51     */
52    private static int ERA = Calendar.ERA;
53    private static int BC = GregorianCalendar.BC;
54//    private static int JAN = Calendar.JANUARY;
55//    private static int FEB = Calendar.FEBRUARY;
56//    private static int MAR = Calendar.MARCH;
57    private static int APR = Calendar.APRIL;
58    private static int MAY = Calendar.MAY;
59    private static int JUN = Calendar.JUNE;
60    private static int JUL = Calendar.JULY;
61//    private static int AUG = Calendar.AUGUST;
62//    private static int SEP = Calendar.SEPTEMBER;
63//    private static int OCT = Calendar.OCTOBER;
64//    private static int NOV = Calendar.NOVEMBER;
65//    private static int DEC = Calendar.DECEMBER;
66
67    private static String[] patterns = {
68        "yyyy MMMM d H m s",
69        "yyyy MM dd hh mm ss",
70
71        /*
72         * Because 1-based HOUR_OF_DAY, 1-based HOUR, MONTH, and YEAR fields
73         * are parsed using different code from the code for other numeric
74         * fields, I prepared YEAR-preceding patterns and SECOND-preceding
75         * patterns.
76         */
77        "yyyy M d h m s",
78        " yyyy M d h m s",
79        "yyyy M d h m s ",
80
81        "s m h d M yyyy",
82        " s m h d M yyyy",
83        "s m h d M yyyy ",
84    };
85
86    private static char originalMinusSign1 = ':';
87    private static char originalMinusSign2 = '\uff0d';  // fullwidth minus
88    private static String[] delimiters = {"-", "/", ":", "/", "\uff0d", "/"};
89    private static String[][] specialDelimiters = {
90        // for Arabic formatter and modified English formatter
91        {"--", "-/", "::", ":/", "\uff0d\uff0d", "\uff0d/"},
92
93        // for English formatter and modified Arabic formatter
94        {"--", "/-", "::", "/:", "\uff0d\uff0d", "/\uff0d"},
95    };
96
97    /*
98     * Format:
99     *   +-------------------------------------------------------------------+
100     *   | Input               | Output                                      |
101     *   +---------------------+---------------------------------------------|
102     *   | datesEG & datesUS   | formattedDatesEG & formattedDatesUS         |
103     *   +-------------------------------------------------------------------+
104     *
105     * Parse:
106     *   +-------------------------------------------------------------------+
107     *   | Input               | Output                                      |
108     *   |---------------------+---------------------------------------------|
109     *   | datesToParse        | datesEG & datesUS                           |
110     *   +-------------------------------------------------------------------+
111     */
112    private static String[][] datesToParse = {
113        // "JUNE" and "JULY" are replaced with a localized month name later.
114        {"2008 JULY 20 3 12 83",
115         "2008  JULY 20 3 12 83",
116         "2008 JULY  20 3 12 83"},
117
118        {"2008 07 20 03 12 83",
119         "2008  07 20 03 12 83",
120         "2008 07  20 03 12 83"},
121
122        {"2008 7 20 3 12 83",
123         "2008  7 20  3 12 83",
124         "2008 7  20  3 12 83"},
125
126        {" 2008 7 20 3 12 83",
127         "  2008 7 20 3 12 83",
128         " 2008  7 20 3 12 83",
129         "2008 7 20 3 12 83"},
130
131        {"2008 7 20 3 12 83 ",
132         "2008 7 20 3 12 83  ",
133         "2008 7 20 3 12 83"},
134
135        {"83 12 3 20 7 2008",
136         "83  12 3  20 7 2008",
137         "83 12  3  20 7 2008"},
138
139        {" 83 12 3 20 7 2008",
140         "  83 12 3 20 7 2008",
141         " 83  12 3 20 7 2008",
142         "83 12 3 20 7 2008"},
143
144        {"83 12 3 20 7 2008 ",
145         "83 12 3 20 7 2008  ",
146         "83 12 3 20 7 2008"},
147    };
148
149    // For formatting
150    private static String[][] formattedDatesEG = {
151        {"2008 JULY 20 3 13 23",
152         "2009 JULY 20 3 13 23",
153         null},
154
155        {"2008 07 20 03 13 23",
156         "2009 07 20 03 13 23",
157         "2007 05 20 03 13 23"},
158
159        {"2008 7 20 3 13 23",
160         "2009 6 10 3 13 23",
161         "2007 4 10 3 13 23"},
162
163        {" 2008 7 20 3 13 23",
164         null,
165         " 2009 7 20 3 13 23",
166         null},
167
168        {"2008 7 20 3 13 23 ",
169         "2008 7 20 3 10 37 ",
170         null},
171
172        {"23 13 3 20 7 2008",
173         "37 10 9 19 7 2008",
174         "23 49 8 19 7 2008"},
175
176        {" 23 13 3 20 7 2008",
177         null,
178         " 37 10 3 20 7 2008",
179         null},
180
181        {"23 13 3 20 7 2008 ",
182         "23 13 3 20 7 2009 ",
183         null},
184    };
185
186    private static String[][] formattedDatesUS = {
187        {"2008 JULY 20 3 13 23",
188         null,
189         "2008 JUNE 10 3 13 23"},
190
191        {"2008 07 20 03 13 23",
192         "2007 05 20 03 13 23",
193         "2008 06 10 03 13 23"},
194
195        {"2008 7 20 3 13 23",
196         "2007 5 19 9 13 23",
197         "2008 6 9 9 13 23"},
198
199        {" 2008 7 20 3 13 23",
200         " 2009 7 20 3 13 23",
201         " 2007 5 20 3 13 23",
202         null},
203
204        {"2008 7 20 3 13 23 ",
205         "2008 7 20 3 13 23 ",
206         null},
207
208        {"23 13 3 20 7 2008",
209         "23 49 2 10 6 2008",
210         "23 13 9 9 6 2008"},
211
212        {" 23 13 3 20 7 2008",
213         " 37 10 3 20 7 2008",
214         " 23 49 2 20 7 2008",
215         null},
216
217        {"23 13 3 20 7 2008 ",
218         "23 13 3 20 7 2008 ",
219         null},
220    };
221
222    private static GregorianCalendar[][] datesEG = {
223        {new GregorianCalendar( 2008, JUL,  20,  3,  12,  83),
224         new GregorianCalendar(-2008, JUL,  20,  3,  12,  83),
225         null},
226
227        {new GregorianCalendar( 2008, JUL,  20,  3,  12,  83),
228         new GregorianCalendar(-2008, JUL,  20,  3,  12,  83),
229         new GregorianCalendar( 2007, MAY,  20,  3,  12,  83)},
230
231        {new GregorianCalendar( 2008, JUL,  20,  3,  12,  83),
232         new GregorianCalendar(-2008, JUL, -20,  3,  12,  83),
233         new GregorianCalendar( 2007, APR,  10,  3,  12,  83)},
234
235        {new GregorianCalendar( 2008, JUL,  20,  3,  12,  83),
236         null,
237         new GregorianCalendar(-2008, JUL,  20,  3,  12,  83),
238         null},
239
240        {new GregorianCalendar( 2008, JUL,  20,  3,  12,  83),
241         new GregorianCalendar( 2008, JUL,  20,  3,  12, -83),
242         null},
243
244        {new GregorianCalendar( 2008, JUL,  20,  3,  12,  83),
245         new GregorianCalendar( 2008, JUL,  20, -3,  12, -83),
246         new GregorianCalendar( 2008, JUL,  20, -3, -12,  83)},
247
248        {new GregorianCalendar( 2008, JUL,  20,  3,  12,  83),
249         null,
250         new GregorianCalendar( 2008, JUL,  20,  3,  12, -83),
251         null},
252
253        {new GregorianCalendar( 2008, JUL,  20,  3,  12,  83),
254         new GregorianCalendar(-2008, JUL,  20,  3,  12,  83),
255         null},
256    };
257
258    private static GregorianCalendar[][] datesUS = {
259        {new GregorianCalendar( 2008, JUL,  20,  3,  12,  83),
260         null,
261         new GregorianCalendar( 2008, JUN,  10,  3,  12,  83)},
262
263        {new GregorianCalendar( 2008, JUL,  20,  3,  12,  83),
264         new GregorianCalendar( 2007, MAY,  20,  3,  12,  83),
265         new GregorianCalendar( 2008, JUN,  10,  3,  12,  83)},
266
267        {new GregorianCalendar( 2008, JUL,  20,  3,  12,  83),
268         new GregorianCalendar( 2007, MAY,  20, -3,  12,  83),
269         new GregorianCalendar( 2008, JUL, -20, -3,  12,  83)},
270
271        {new GregorianCalendar( 2008, JUL,  20,  3,  12,  83),
272         new GregorianCalendar(-2008, JUL,  20,  3,  12,  83),
273         new GregorianCalendar( 2007, MAY,  20,  3,  12,  83),
274         null},
275
276        {new GregorianCalendar( 2008, JUL,  20,  3,  12,  83),
277         new GregorianCalendar( 2008, JUL,  20,  3,  12,  83),
278         null},
279
280        {new GregorianCalendar( 2008, JUL,  20,  3,  12,  83),
281         new GregorianCalendar( 2008, JUL, -20,  3, -12,  83),
282         new GregorianCalendar( 2008, JUL, -20, -3,  12,  83)},
283
284        {new GregorianCalendar( 2008, JUL,  20,  3,  12,  83),
285         new GregorianCalendar( 2008, JUL,  20,  3,  12, -83),
286         new GregorianCalendar( 2008, JUL,  20,  3, -12,  83),
287         null},
288
289        {new GregorianCalendar( 2008, JUL,  20,  3,  12,  83),
290         new GregorianCalendar( 2008, JUL,  20,  3,  12,  83),
291         null},
292    };
293
294    /* flags */
295    private static boolean err = false;
296    private static boolean verbose = false;
297
298
299    public static void main(String[] args) {
300        if (args.length == 1 && args[0].equals("-v")) {
301            verbose = true;
302        }
303
304        Locale defaultLocale = Locale.getDefault();
305        TimeZone defaultTimeZone = TimeZone.getDefault();
306
307        TimeZone.setDefault(TimeZone.getTimeZone("Asia/Tokyo"));
308
309        try {
310            /*
311             * Test SimpleDateFormat.parse() and format() for original
312             * SimpleDateFormat instances
313             */
314            testDateFormat1();
315
316            /*
317             * Test SimpleDateFormat.parse() and format() for modified
318             * SimpleDateFormat instances using an original minus sign,
319             * pattern, and diffenrent month names in DecimalFormat
320             */
321            testDateFormat2();
322
323            /*
324             * Test SimpleDateFormat.parse() and format() for modified
325             * SimpleDateFormat instances using a fullwidth minus sign
326             */
327            testDateFormat3();
328
329            /*
330             * Just to confirm that regressions aren't introduced in
331             * DecimalFormat. This cannot happen, though. Because I didn't
332             * change DecimalFormat at all.
333             */
334            testNumberFormat();
335        }
336        catch (Exception e) {
337            err = true;
338            System.err.println("Unexpected exception: " + e);
339        }
340        finally {
341            Locale.setDefault(defaultLocale);
342            TimeZone.setDefault(defaultTimeZone);
343
344            if (err) {
345                System.err.println(BORDER + " Test failed.");
346                throw new RuntimeException("Date/Number formatting/parsing error.");
347            } else {
348                System.out.println(BORDER + " Test passed.");
349            }
350        }
351    }
352
353
354    //
355    // DateFormat test
356    //
357    private static void testDateFormat1() {
358        for (int i = 0; i < patterns.length; i++) {
359            System.out.println(BORDER);
360            for (int j = 0; j <= 1; j++) {
361                // Generate a pattern
362                String pattern = patterns[i].replaceAll(" ", delimiters[j]);
363                System.out.println("Pattern=\"" + pattern + "\"");
364
365                System.out.println("*** DateFormat.format test in ar_EG");
366                testDateFormatFormattingInRTL(pattern, i, j, null, localeEG, false);
367
368                System.out.println("*** DateFormat.parse test in ar_EG");
369                testDateFormatParsingInRTL(pattern, i, j, null, localeEG, false);
370
371                System.out.println("*** DateFormat.format test in en_US");
372                testDateFormatFormattingInLTR(pattern, i, j, null, localeUS, true);
373
374                System.out.println("*** DateFormat.parse test in en_US");
375                testDateFormatParsingInLTR(pattern, i, j, null, localeUS, true);
376            }
377        }
378    }
379
380    private static void testDateFormat2() {
381        /*
382         * modified ar_EG Date&Time formatter :
383         *   minus sign:  ':'
384         *   pattern:     "#,##0.###"
385         *   month names: In Arabic
386         *
387         * modified en_US Date&Time formatter :
388         *   minus sign:  ':'
389         *   pattern:     "#,##0.###;#,##0.###-"
390         *   month names: In English
391         */
392        DecimalFormat dfEG = (DecimalFormat)NumberFormat.getInstance(localeEG);
393        DecimalFormat dfUS = (DecimalFormat)NumberFormat.getInstance(localeUS);
394
395        DecimalFormatSymbols dfsEG = dfEG.getDecimalFormatSymbols();
396        DecimalFormatSymbols dfsUS = dfUS.getDecimalFormatSymbols();
397        dfsEG.setMinusSign(originalMinusSign1);
398        dfsUS.setMinusSign(originalMinusSign1);
399        dfEG.setDecimalFormatSymbols(dfsUS);
400        dfUS.setDecimalFormatSymbols(dfsEG);
401
402        String patternEG = dfEG.toPattern();
403        String patternUS = dfUS.toPattern();
404
405        dfEG.applyPattern(patternUS);
406        dfUS.applyPattern(patternEG);
407
408        for (int i = 0; i < patterns.length; i++) {
409            System.out.println(BORDER);
410            for (int j = 2; j <= 3; j++) {
411                // Generate a pattern
412                String pattern = patterns[i].replaceAll(" ", delimiters[j]);
413                System.out.println("Pattern=\"" + pattern + "\"");
414
415                System.out.println("*** DateFormat.format test in modified en_US");
416                testDateFormatFormattingInRTL(pattern, i, j, dfUS, localeUS, true);
417
418                System.out.println("*** DateFormat.parse test in modified en_US");
419                testDateFormatParsingInRTL(pattern, i, j, dfUS, localeUS, true);
420
421                System.out.println("*** DateFormat.format test in modified ar_EG");
422                testDateFormatFormattingInLTR(pattern, i, j, dfEG, localeEG, false);
423
424                System.out.println("*** DateFormat.parse test in modified ar_EG");
425                testDateFormatParsingInLTR(pattern, i, j, dfEG, localeEG, false);
426            }
427        }
428    }
429
430    private static void testDateFormat3() {
431        /*
432         * modified ar_EG Date&Time formatter :
433         *   minus sign:  '\uff0d'  // fullwidth minus
434         *   pattern:     "#,##0.###;#,##0.###-"
435         *   month names: In Arabic
436         *
437         * modified en_US Date&Time formatter :
438         *   minus sign:  '\uff0d'  // fullwidth minus
439         *   pattern:     "#,##0.###"
440         *   month names: In English
441         */
442        DecimalFormat dfEG = (DecimalFormat)NumberFormat.getInstance(localeEG);
443        DecimalFormat dfUS = (DecimalFormat)NumberFormat.getInstance(localeUS);
444
445        DecimalFormatSymbols dfsEG = dfEG.getDecimalFormatSymbols();
446        DecimalFormatSymbols dfsUS = dfUS.getDecimalFormatSymbols();
447        dfsEG.setMinusSign(originalMinusSign2);
448        dfsUS.setMinusSign(originalMinusSign2);
449        dfEG.setDecimalFormatSymbols(dfsEG);
450        dfUS.setDecimalFormatSymbols(dfsUS);
451
452        for (int i = 0; i < patterns.length; i++) {
453            System.out.println(BORDER);
454            for (int j = 4; j <= 5; j++) {
455                // Generate a pattern
456                String pattern = patterns[i].replaceAll(" ", delimiters[j]);
457                System.out.println("Pattern=\"" + pattern + "\"");
458
459                System.out.println("*** DateFormat.format test in modified ar_EG");
460                testDateFormatFormattingInRTL(pattern, i, j, dfEG, localeEG, false);
461
462                System.out.println("*** DateFormat.parse test in modified ar_EG");
463                testDateFormatParsingInRTL(pattern, i, j, dfEG, localeEG, false);
464
465                System.out.println("*** DateFormat.format test in modified en_US");
466                testDateFormatFormattingInLTR(pattern, i, j, dfUS, localeUS, true);
467
468                System.out.println("*** DateFormat.parse test in modified en_US");
469                testDateFormatParsingInLTR(pattern, i, j, dfUS, localeUS, true);
470            }
471        }
472    }
473
474    private static void testDateFormatFormattingInRTL(String pattern,
475                                                      int basePattern,
476                                                      int delimiter,
477                                                      NumberFormat nf,
478                                                      Locale locale,
479                                                      boolean useEnglishMonthName) {
480        Locale.setDefault(locale);
481
482        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
483        if (nf != null) {
484            sdf.setNumberFormat(nf);
485        }
486        for (int i = 0; i < datesToParse[basePattern].length; i++) {
487            if (datesEG[basePattern][i] == null) {
488                continue;
489            }
490
491            String expected = formattedDatesEG[basePattern][i]
492                              .replaceAll("JUNE", (useEnglishMonthName ?
493                                                   JuneInEnglish : JuneInArabic))
494                              .replaceAll("JULY", (useEnglishMonthName ?
495                                                   JulyInEnglish : JulyInArabic))
496                              .replaceAll(" ", delimiters[delimiter]);
497            testDateFormatFormatting(sdf, pattern, datesEG[basePattern][i],
498                expected, locale.toString());
499        }
500    }
501
502    private static void testDateFormatFormattingInLTR(String pattern,
503                                                      int basePattern,
504                                                      int delimiter,
505                                                      NumberFormat nf,
506                                                      Locale locale,
507                                                      boolean useEnglishMonthName) {
508        Locale.setDefault(locale);
509
510        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
511        if (nf != null) {
512            sdf.setNumberFormat(nf);
513        }
514        for (int i = 0; i < datesToParse[basePattern].length; i++) {
515            if (datesUS[basePattern][i] == null) {
516                continue;
517            }
518
519            String expected = formattedDatesUS[basePattern][i]
520                              .replaceAll("JUNE", (useEnglishMonthName ?
521                                                   JuneInEnglish : JuneInArabic))
522                              .replaceAll("JULY", (useEnglishMonthName ?
523                                                   JulyInEnglish : JulyInArabic))
524                              .replaceAll(" ", delimiters[delimiter]);
525            testDateFormatFormatting(sdf, pattern, datesUS[basePattern][i],
526                expected, locale.toString());
527        }
528    }
529
530    private static void testDateFormatFormatting(SimpleDateFormat sdf,
531                                                 String pattern,
532                                                 GregorianCalendar givenGC,
533                                                 String expected,
534                                                 String locale) {
535        Date given = givenGC.getTime();
536        String str = sdf.format(given);
537        if (expected.equals(str)) {
538            if (verbose) {
539                System.out.print("  Passed: SimpleDateFormat(");
540                System.out.print(locale + ", \"" + pattern + "\").format(");
541                System.out.println(given + ")");
542
543                System.out.print("      ---> \"" + str + "\" ");
544                System.out.println((givenGC.get(ERA) == BC) ? "(BC)" : "(AD)");
545            }
546        } else {
547            err = true;
548
549            System.err.print("  Failed: Unexpected SimpleDateFormat(");
550            System.out.print(locale + ", \"" + pattern + "\").format(");
551            System.out.println(given + ") result.");
552
553            System.out.println("      Expected: \"" + expected + "\"");
554
555            System.out.print("      Got:      \"" + str + "\" ");
556            System.out.println((givenGC.get(ERA) == BC) ? "(BC)" : "(AD)");
557        }
558    }
559
560    private static void testDateFormatParsingInRTL(String pattern,
561                                                   int basePattern,
562                                                   int delimiter,
563                                                   NumberFormat nf,
564                                                   Locale locale,
565                                                   boolean useEnglishMonthName) {
566        Locale.setDefault(locale);
567
568        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
569        if (nf != null) {
570            sdf.setNumberFormat(nf);
571        }
572        for (int i = 0; i < datesToParse[basePattern].length; i++) {
573            String given = datesToParse[basePattern][i]
574                           .replaceAll("  ", specialDelimiters[0][delimiter])
575                           .replaceAll(" ", delimiters[delimiter]);
576
577            testDateFormatParsing(sdf, pattern,
578                given.replaceAll("JULY", (useEnglishMonthName ?
579                                          JulyInEnglish :  JulyInArabic)),
580                datesEG[basePattern][i], locale.toString());
581        }
582    }
583
584    private static void testDateFormatParsingInLTR(String pattern,
585                                                   int basePattern,
586                                                   int delimiter,
587                                                   NumberFormat nf,
588                                                   Locale locale,
589                                                   boolean useEnglishMonthName) {
590        Locale.setDefault(locale);
591
592        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
593        if (nf != null) {
594            sdf.setNumberFormat(nf);
595        }
596        for (int i = 0; i < datesToParse[basePattern].length; i++) {
597            String given = datesToParse[basePattern][i]
598                           .replaceAll("  ", specialDelimiters[1][delimiter])
599                           .replaceAll(" ", delimiters[delimiter]);
600
601            testDateFormatParsing(sdf, pattern,
602                given.replaceAll("JULY", (useEnglishMonthName ?
603                                          JulyInEnglish :  JulyInArabic)),
604                datesUS[basePattern][i], locale.toString());
605        }
606    }
607
608    private static void testDateFormatParsing(SimpleDateFormat sdf,
609                                              String pattern,
610                                              String given,
611                                              GregorianCalendar expectedGC,
612                                              String locale) {
613        try {
614            Date d = sdf.parse(given);
615            if (expectedGC == null) {
616                err = true;
617                System.err.print("  Failed: SimpleDateFormat(" + locale);
618                System.err.print(", \"" + pattern + "\").parse(\"" + given);
619                System.err.println("\") should have thrown ParseException");
620            } else if (expectedGC.getTime().equals(d)) {
621                if (verbose) {
622                    System.out.print("  Passed: SimpleDateFormat(" + locale);
623                    System.out.print(", \"" + pattern + "\").parse(\"" + given);
624                    System.out.println("\")");
625
626                    System.out.print("      ---> " + d + " (" + d.getTime());
627                    System.out.println(")");
628                }
629            } else {
630                err = true;
631                System.err.print("  Failed: SimpleDateFormat(" + locale);
632                System.err.print(", \"" + pattern + "\").parse(\"" + given);
633                System.err.println("\")");
634
635                System.err.print("      Expected: " + expectedGC.getTime());
636                System.err.println(" (" + d.getTime() + ")");
637
638                System.err.print("      Got:      " + d + " (" + d.getTime());
639                System.err.println(")");
640
641                System.err.print("      Pattern:  \"");
642                System.err.print(((DecimalFormat)sdf.getNumberFormat()).toPattern());
643                System.err.println("\"");
644            }
645        }
646        catch (ParseException pe) {
647            if (expectedGC == null) {
648                if (verbose) {
649                    System.out.print("  Passed: SimpleDateFormat(" + locale);
650                    System.out.print(", \"" + pattern + "\").parse(\"" + given);
651                    System.out.println("\")");
652
653                    System.out.println("      threw ParseException as expected");
654                }
655            } else {
656                err = true;
657                System.err.println("  Failed: Unexpected exception with");
658
659                System.err.print("    SimpleDateFormat(" + locale);
660                System.err.print(", \"" + pattern + "\").parse(\"");
661                System.err.println(given + "\"):");
662
663                System.err.println("      " + pe);
664
665                System.err.print("      Pattern: \"");
666                System.err.print(((DecimalFormat)sdf.getNumberFormat()).toPattern());
667                System.err.println("\"");
668
669                System.err.print("      Month 0: ");
670                System.err.println(sdf.getDateFormatSymbols().getMonths()[0]);
671            }
672        }
673    }
674
675
676    //
677    // NumberFormat test
678    //
679    private static void testNumberFormat() {
680        NumberFormat nfEG = NumberFormat.getInstance(localeEG);
681        NumberFormat nfUS = NumberFormat.getInstance(localeUS);
682
683        System.out.println("*** DecimalFormat.format test in ar_EG");
684        testNumberFormatFormatting(nfEG, -123456789, "123,456,789-", "ar_EG");
685        testNumberFormatFormatting(nfEG, -456, "456-", "ar_EG");
686
687        System.out.println("*** DecimalFormat.parse test in ar_EG");
688        testNumberFormatParsing(nfEG, "123-", -123L, "ar_EG");
689        testNumberFormatParsing(nfEG, "123--",-123L, "ar_EG");
690        testNumberFormatParsingCheckException(nfEG, "-123", 0, "ar_EG");
691
692        System.out.println("*** DecimalFormat.format test in en_US");
693        testNumberFormatFormatting(nfUS, -123456789, "-123,456,789", "en_US");
694        testNumberFormatFormatting(nfUS, -456, "-456", "en_US");
695
696        System.out.println("*** DecimalFormat.parse test in en_US");
697        testNumberFormatParsing(nfUS, "123-", 123L, "en_US");
698        testNumberFormatParsing(nfUS, "-123",-123L, "en_US");
699        testNumberFormatParsingCheckException(nfUS, "--123", 0, "en_US");
700    }
701
702    private static void testNumberFormatFormatting(NumberFormat nf,
703                                                   int given,
704                                                   String expected,
705                                                   String locale) {
706        String str = nf.format(given);
707        if (expected.equals(str)) {
708            if (verbose) {
709                System.out.print("  Passed: NumberFormat(" + locale);
710                System.out.println(").format(" + given + ")");
711
712                System.out.println("      ---> \"" + str + "\"");
713            }
714        } else {
715            err = true;
716            System.err.print("  Failed: Unexpected NumberFormat(" + locale);
717            System.err.println(").format(" + given + ") result.");
718
719            System.err.println("      Expected: \"" + expected + "\"");
720
721            System.err.println("      Got:      \"" + str + "\"");
722        }
723    }
724
725    private static void testNumberFormatParsing(NumberFormat nf,
726                                                String given,
727                                                Number expected,
728                                                String locale) {
729        try {
730            Number n = nf.parse(given);
731            if (n.equals(expected)) {
732                if (verbose) {
733                    System.out.print("  Passed: NumberFormat(" + locale);
734                    System.out.println(").parse(\"" + given + "\")");
735
736                    System.out.println("      ---> " + n);
737                }
738            } else {
739                err = true;
740                System.err.print("  Failed: Unexpected NumberFormat(" + locale);
741                System.err.println(").parse(\"" + given + "\") result.");
742
743                System.err.println("      Expected: " + expected);
744
745                System.err.println("      Got:      " + n);
746            }
747        }
748        catch (ParseException pe) {
749            err = true;
750            System.err.print("  Failed: Unexpected exception with NumberFormat(");
751            System.err.println(locale + ").parse(\"" + given + "\") :");
752
753            System.err.println("    " + pe);
754        }
755    }
756
757    private static void testNumberFormatParsingCheckException(NumberFormat nf,
758                                                              String given,
759                                                              int expected,
760                                                              String locale) {
761        try {
762            Number n = nf.parse(given);
763            err = true;
764
765            System.err.print("  Failed: NumberFormat(" + locale);
766            System.err.println(").parse(\"" + given + "\")");
767
768            System.err.println("      should have thrown ParseException");
769        }
770        catch (ParseException pe) {
771            int errorOffset = pe.getErrorOffset();
772            if (errorOffset == expected) {
773                if (verbose) {
774                    System.out.print("  Passed: NumberFormat(" + locale);
775                    System.out.println(").parse(\"" + given + "\")");
776
777                    System.out.print("      threw ParseException as expected, and its errorOffset was correct: ");
778                    System.out.println(errorOffset);
779                }
780            } else {
781                err = true;
782                System.err.print("  Failed: NumberFormat(" + locale);
783                System.err.println(").parse(\"" + given + "\")");
784
785                System.err.print("      threw ParseException as expected, but its errorOffset was incorrect: ");
786                System.err.println(errorOffset);
787            }
788        }
789    }
790
791}
792