1/* GENERATED SOURCE. DO NOT MODIFY. */
2// © 2016 and later: Unicode, Inc. and others.
3// License & terms of use: http://www.unicode.org/copyright.html#License
4/*
5 *******************************************************************************
6 * Copyright (C) 2001-2015, International Business Machines Corporation and    *
7 * others. All Rights Reserved.                                                *
8 *******************************************************************************
9 */
10
11/**
12 * Port From:   ICU4C v1.8.1 : format : DateFormatRegressionTest
13 * Source File: $ICU4CRoot/source/test/intltest/dtfmrgts.cpp
14 **/
15
16package android.icu.dev.test.format;
17
18import java.io.ByteArrayInputStream;
19import java.io.ByteArrayOutputStream;
20import java.io.IOException;
21import java.io.ObjectInputStream;
22import java.io.ObjectOutputStream;
23import java.io.OptionalDataException;
24import java.text.FieldPosition;
25import java.text.Format;
26import java.text.ParseException;
27import java.text.ParsePosition;
28import java.util.Date;
29import java.util.Locale;
30
31import org.junit.Test;
32
33import android.icu.text.DateFormat;
34import android.icu.text.SimpleDateFormat;
35import android.icu.util.Calendar;
36import android.icu.util.GregorianCalendar;
37import android.icu.util.IslamicCalendar;
38import android.icu.util.JapaneseCalendar;
39import android.icu.util.SimpleTimeZone;
40import android.icu.util.TimeZone;
41import android.icu.util.ULocale;
42
43/**
44 * Performs regression test for DateFormat
45 **/
46public class DateFormatRegressionTest extends android.icu.dev.test.TestFmwk {
47    /**
48     * @bug 4029195
49     */
50    @Test
51    public void Test4029195() {
52        Calendar cal = Calendar.getInstance();
53        Date today = cal.getTime();
54        logln("today: " + today);
55        SimpleDateFormat sdf = (SimpleDateFormat) DateFormat.getDateInstance();
56        String pat = sdf.toPattern();
57        logln("pattern: " + pat);
58        StringBuffer fmtd = new StringBuffer("");
59        FieldPosition pos = new FieldPosition(0);
60        fmtd = sdf.format(today, fmtd, pos);
61        logln("today: " + fmtd);
62
63        sdf.applyPattern("G yyyy DDD");
64        StringBuffer todayS = new StringBuffer("");
65        todayS = sdf.format(today, todayS, pos);
66        logln("today: " + todayS);
67        try {
68            today = sdf.parse(todayS.toString());
69            logln("today date: " + today);
70        } catch (Exception e) {
71            errln("Error reparsing date: " + e.getMessage());
72        }
73
74        try {
75            StringBuffer rt = new StringBuffer("");
76            rt = sdf.format(sdf.parse(todayS.toString()), rt, pos);
77            logln("round trip: " + rt);
78            if (!rt.toString().equals(todayS.toString()))
79                errln("Fail: Want " + todayS + " Got " + rt);
80        } catch (ParseException e) {
81            errln("Fail: " + e);
82            e.printStackTrace();
83        }
84    }
85
86    /**
87     * @bug 4052408
88     */
89    @Test
90    public void Test4052408() {
91
92        DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.US);
93        Calendar cal = Calendar.getInstance();
94        cal.clear();
95        cal.set(97 + 1900, Calendar.MAY, 3, 8, 55);
96        Date dt = cal.getTime();
97        String str = fmt.format(dt);
98        logln(str);
99
100        if (!str.equals("5/3/97, 8:55 AM"))
101            errln("Fail: Test broken; Want 5/3/97, 8:55 AM Got " + str);
102
103        String expected[] = {
104            "", //"ERA_FIELD",
105            "97", //"YEAR_FIELD",
106            "5", //"MONTH_FIELD",
107            "3", //"DATE_FIELD",
108            "", //"HOUR_OF_DAY1_FIELD",
109            "", //"HOUR_OF_DAY0_FIELD",
110            "55", //"MINUTE_FIELD",
111            "", //"SECOND_FIELD",
112            "", //"MILLISECOND_FIELD",
113            "", //"DAY_OF_WEEK_FIELD",
114            "", //"DAY_OF_YEAR_FIELD",
115            "", //"DAY_OF_WEEK_IN_MONTH_FIELD",
116            "", //"WEEK_OF_YEAR_FIELD",
117            "", //"WEEK_OF_MONTH_FIELD",
118            "AM", //"AM_PM_FIELD",
119            "8", //"HOUR1_FIELD",
120            "", //"HOUR0_FIELD",
121            "" //"TIMEZONE_FIELD"
122            };
123        String fieldNames[] = {
124                "ERA_FIELD",
125                "YEAR_FIELD",
126                "MONTH_FIELD",
127                "DATE_FIELD",
128                "HOUR_OF_DAY1_FIELD",
129                "HOUR_OF_DAY0_FIELD",
130                "MINUTE_FIELD",
131                "SECOND_FIELD",
132                "MILLISECOND_FIELD",
133                "DAY_OF_WEEK_FIELD",
134                "DAY_OF_YEAR_FIELD",
135                "DAY_OF_WEEK_IN_MONTH_FIELD",
136                "WEEK_OF_YEAR_FIELD",
137                "WEEK_OF_MONTH_FIELD",
138                "AM_PM_FIELD",
139                "HOUR1_FIELD",
140                "HOUR0_FIELD",
141                "TIMEZONE_FIELD"};
142
143        boolean pass = true;
144        for (int i = 0; i <= 17; ++i) {
145            FieldPosition pos = new FieldPosition(i);
146            StringBuffer buf = new StringBuffer("");
147            fmt.format(dt, buf, pos);
148            //char[] dst = new char[pos.getEndIndex() - pos.getBeginIndex()];
149            String dst = buf.substring(pos.getBeginIndex(), pos.getEndIndex());
150            str = dst;
151            log(i + ": " + fieldNames[i] + ", \"" + str + "\", "
152                    + pos.getBeginIndex() + ", " + pos.getEndIndex());
153            String exp = expected[i];
154            if ((exp.length() == 0 && str.length() == 0) || str.equals(exp))
155                logln(" ok");
156            else {
157                logln(" expected " + exp);
158                pass = false;
159            }
160        }
161        if (!pass)
162            errln("Fail: FieldPosition not set right by DateFormat");
163    }
164
165    /**
166     * @bug 4056591
167     * Verify the function of the [s|g]et2DigitYearStart() API.
168     */
169    @Test
170    public void Test4056591() {
171
172        try {
173            SimpleDateFormat fmt = new SimpleDateFormat("yyMMdd", Locale.US);
174            Calendar cal = Calendar.getInstance();
175            cal.clear();
176            cal.set(1809, Calendar.DECEMBER, 25);
177            Date start = cal.getTime();
178            fmt.set2DigitYearStart(start);
179            if ((fmt.get2DigitYearStart() != start))
180                errln("get2DigitYearStart broken");
181            cal.clear();
182            cal.set(1809, Calendar.DECEMBER, 25);
183            Date d1 = cal.getTime();
184            cal.clear();
185            cal.set(1909, Calendar.DECEMBER, 24);
186            Date d2 = cal.getTime();
187            cal.clear();
188            cal.set(1809, Calendar.DECEMBER, 26);
189            Date d3 = cal.getTime();
190            cal.clear();
191            cal.set(1861, Calendar.DECEMBER, 25);
192            Date d4 = cal.getTime();
193
194            Date dates[] = {d1, d2, d3, d4};
195
196            String strings[] = {"091225", "091224", "091226", "611225"};
197
198            for (int i = 0; i < 4; i++) {
199                String s = strings[i];
200                Date exp = dates[i];
201                Date got = fmt.parse(s);
202                logln(s + " . " + got + "; exp " + exp);
203                if (got.getTime() != exp.getTime())
204                    errln("set2DigitYearStart broken");
205            }
206        } catch (ParseException e) {
207            errln("Fail: " + e);
208            e.printStackTrace();
209        }
210    }
211
212    /**
213     * @bug 4059917
214     */
215    @Test
216    public void Test4059917() {
217        SimpleDateFormat fmt;
218        String myDate;
219        fmt = new SimpleDateFormat("yyyy/MM/dd");
220        myDate = "1997/01/01";
221        aux917( fmt, myDate );
222        fmt = new SimpleDateFormat("yyyyMMdd");
223        myDate = "19970101";
224        aux917( fmt, myDate );
225    }
226
227    public void aux917(SimpleDateFormat fmt, String str) {
228
229        String pat = fmt.toPattern();
230        logln("==================");
231        logln("testIt: pattern=" + pat + " string=" + str);
232        ParsePosition pos = new ParsePosition(0);
233        Object o = fmt.parseObject(str, pos);
234        //logln( UnicodeString("Parsed object: ") + o );
235
236        StringBuffer formatted = new StringBuffer("");
237        FieldPosition poss = new FieldPosition(0);
238        formatted = fmt.format(o, formatted, poss);
239
240        logln("Formatted string: " + formatted);
241        if (!formatted.toString().equals(str))
242            errln("Fail: Want " + str + " Got " + formatted);
243    }
244
245    /**
246     * @bug 4060212
247     */
248    @Test
249    public void Test4060212() {
250        String dateString = "1995-040.05:01:29";
251        logln("dateString= " + dateString);
252        logln("Using yyyy-DDD.hh:mm:ss");
253        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-DDD.hh:mm:ss");
254        ParsePosition pos = new ParsePosition(0);
255        Date myDate = formatter.parse(dateString, pos);
256        DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.LONG);
257        String myString = fmt.format(myDate);
258        logln(myString);
259        Calendar cal = new GregorianCalendar();
260        cal.setTime(myDate);
261        if ((cal.get(Calendar.DAY_OF_YEAR) != 40))
262            errln("Fail: Got " + cal.get(Calendar.DAY_OF_YEAR) + " Want 40");
263
264        logln("Using yyyy-ddd.hh:mm:ss");
265        formatter = new SimpleDateFormat("yyyy-ddd.hh:mm:ss");
266        pos.setIndex(0);
267        myDate = formatter.parse(dateString, pos);
268        myString = fmt.format(myDate);
269        logln(myString);
270        cal.setTime(myDate);
271        if ((cal.get(Calendar.DAY_OF_YEAR) != 40))
272            errln("Fail: Got " + cal.get(Calendar.DAY_OF_YEAR) + " Want 40");
273    }
274    /**
275     * @bug 4061287
276     */
277    @Test
278    public void Test4061287() {
279
280        SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy");
281        try {
282            logln(df.parse("35/01/1971").toString());
283        } catch (ParseException e) {
284            errln("Fail: " + e);
285            e.printStackTrace();
286        }
287        df.setLenient(false);
288        boolean ok = false;
289        try {
290            logln(df.parse("35/01/1971").toString());
291        } catch (ParseException e) {
292            ok = true;
293        }
294        if (!ok)
295            errln("Fail: Lenient not working");
296    }
297
298    /**
299     * @bug 4065240
300     */
301    @Test
302    public void Test4065240() {
303        Date curDate;
304        DateFormat shortdate, fulldate;
305        String strShortDate, strFullDate;
306        Locale saveLocale = Locale.getDefault();
307        TimeZone saveZone = TimeZone.getDefault();
308
309        try {
310            Locale curLocale = new Locale("de", "DE");
311            Locale.setDefault(curLocale);
312            // {sfb} adoptDefault instead of setDefault
313            //TimeZone.setDefault(TimeZone.createTimeZone("EST"));
314            TimeZone.setDefault(TimeZone.getTimeZone("EST"));
315            Calendar cal = Calendar.getInstance();
316            cal.clear();
317            cal.set(98 + 1900, 0, 1);
318            curDate = cal.getTime();
319            shortdate = DateFormat.getDateInstance(DateFormat.SHORT);
320            fulldate = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
321            strShortDate = "The current date (short form) is ";
322            String temp;
323            temp = shortdate.format(curDate);
324            strShortDate += temp;
325            strFullDate = "The current date (long form) is ";
326            String temp2 = fulldate.format(curDate);
327            strFullDate += temp2;
328
329            logln(strShortDate);
330            logln(strFullDate);
331
332            // {sfb} What to do with resource bundle stuff?????
333
334            // Check to see if the resource is present; if not, we can't test
335            //ResourceBundle bundle = //The variable is never used
336            //    ICULocaleData.getBundle("DateFormatZoneData", curLocale);
337
338            // {sfb} API change to ResourceBundle -- add getLocale()
339            /*if (bundle.getLocale().getLanguage().equals("de")) {
340                // UPDATE THIS AS ZONE NAME RESOURCE FOR <EST> in de_DE is updated
341                if (!strFullDate.endsWith("GMT-05:00"))
342                    errln("Fail: Want GMT-05:00");
343            } else {
344                logln("*** TEST COULD NOT BE COMPLETED BECAUSE DateFormatZoneData ***");
345                logln("*** FOR LOCALE de OR de_DE IS MISSING ***");
346            }*/
347        } catch (Exception e) {
348            logln(e.getMessage());
349        } finally {
350            Locale.setDefault(saveLocale);
351            TimeZone.setDefault(saveZone);
352        }
353
354    }
355
356    /*
357      DateFormat.equals is too narrowly defined.  As a result, MessageFormat
358      does not work correctly.  DateFormat.equals needs to be written so
359      that the Calendar sub-object is not compared using Calendar.equals,
360      but rather compared for equivalency.  This may necessitate adding a
361      (package private) method to Calendar to test for equivalency.
362
363      Currently this bug breaks MessageFormat.toPattern
364      */
365    /**
366     * @bug 4071441
367     */
368    @Test
369    public void Test4071441() {
370        DateFormat fmtA = DateFormat.getInstance();
371        DateFormat fmtB = DateFormat.getInstance();
372
373        // {sfb} Is it OK to cast away const here?
374        Calendar calA = fmtA.getCalendar();
375        Calendar calB = fmtB.getCalendar();
376        calA.clear();
377        calA.set(1900, 0 ,0);
378        calB.clear();
379        calB.set(1900, 0, 0);
380        if (!calA.equals(calB))
381            errln("Fail: Can't complete test; Calendar instances unequal");
382        if (!fmtA.equals(fmtB))
383            errln("Fail: DateFormat unequal when Calendars equal");
384        calB.clear();
385        calB.set(1961, Calendar.DECEMBER, 25);
386        if (calA.equals(calB))
387            errln("Fail: Can't complete test; Calendar instances equal");
388        if (!fmtA.equals(fmtB))
389            errln("Fail: DateFormat unequal when Calendars equivalent");
390        logln("DateFormat.equals ok");
391    }
392
393    /* The java.text.DateFormat.parse(String) method expects for the
394      US locale a string formatted according to mm/dd/yy and parses it
395      correctly.
396
397      When given a string mm/dd/yyyy it only parses up to the first
398      two y's, typically resulting in a date in the year 1919.
399
400      Please extend the parsing method(s) to handle strings with
401      four-digit year values (probably also applicable to various
402      other locales.  */
403    /**
404     * @bug 4073003
405     */
406    @Test
407    public void Test4073003() {
408        try {
409            DateFormat fmt = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US);
410            String tests[] = {"12/25/61", "12/25/1961", "4/3/2010", "4/3/10"};
411            for (int i = 0; i < 4; i += 2) {
412                Date d = fmt.parse(tests[i]);
413                Date dd = fmt.parse(tests[i + 1]);
414                String s;
415                s = fmt.format(d);
416                String ss;
417                ss = fmt.format(dd);
418                if (d.getTime() != dd.getTime())
419                    errln("Fail: " + d + " != " + dd);
420                if (!s.equals(ss))
421                    errln("Fail: " + s + " != " + ss);
422                logln("Ok: " + s + " " + d);
423            }
424        } catch (ParseException e) {
425            errln("Fail: " + e);
426            e.printStackTrace();
427        }
428    }
429
430    /**
431     * @bug 4089106
432     */
433    @Test
434    public void Test4089106() {
435        TimeZone def = TimeZone.getDefault();
436        try {
437            TimeZone z = new SimpleTimeZone((int) (1.25 * 3600000), "FAKEZONE");
438            TimeZone.setDefault(z);
439            // Android patch (http://b/28949992) start.
440            // ICU TimeZone.setDefault() not supported on Android.
441            z = TimeZone.getDefault();
442            // Android patch (http://b/28949992) end.
443            SimpleDateFormat f = new SimpleDateFormat();
444            if (!f.getTimeZone().equals(z))
445                errln("Fail: SimpleTimeZone should use TimeZone.getDefault()");
446        } finally {
447            TimeZone.setDefault(def);
448        }
449    }
450
451    /**
452     * @bug 4100302
453     */
454    @Test
455    public void Test4100302() {
456
457        Locale locales[] = {
458            Locale.CANADA, Locale.CANADA_FRENCH, Locale.CHINA,
459            Locale.CHINESE, Locale.ENGLISH, Locale.FRANCE, Locale.FRENCH,
460            Locale.GERMAN, Locale.GERMANY, Locale.ITALIAN, Locale.ITALY,
461            Locale.JAPAN, Locale.JAPANESE, Locale.KOREA, Locale.KOREAN,
462            Locale.PRC, Locale.SIMPLIFIED_CHINESE, Locale.TAIWAN,
463            Locale.TRADITIONAL_CHINESE, Locale.UK, Locale.US};
464        try {
465            boolean pass = true;
466            for (int i = 0; i < 21; i++) {
467                Format format = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, locales[i]);
468                byte[] bytes;
469                ByteArrayOutputStream baos = new ByteArrayOutputStream();
470                ObjectOutputStream oos = new ObjectOutputStream(baos);
471                oos.writeObject(format);
472                oos.flush();
473                baos.close();
474                bytes = baos.toByteArray();
475                ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
476                Object o = ois.readObject();
477                if (!format.equals(o)) {
478                    pass = false;
479                    logln("DateFormat instance for locale " + locales[i] + " is incorrectly serialized/deserialized.");
480                } else {
481                    logln("DateFormat instance for locale " + locales[i] + " is OKAY.");
482                }
483            }
484            if (!pass)
485                errln("Fail: DateFormat serialization/equality bug");
486        } catch (OptionalDataException e) {
487            errln("Fail: " + e);
488        } catch (IOException e) {
489            errln("Fail: " + e);
490        } catch (ClassNotFoundException e) {
491            errln("Fail: " + e);
492        }
493
494    }
495
496    /**
497     * @bug 4101483
498     */
499    @Test
500    public void Test4101483() {
501        SimpleDateFormat sdf = new SimpleDateFormat("z", Locale.US);
502        FieldPosition fp = new FieldPosition(DateFormat.TIMEZONE_FIELD);
503        Date d = new Date(9234567890L);
504        StringBuffer buf = new StringBuffer("");
505        sdf.format(d, buf, fp);
506        logln(sdf.format(d, buf, fp).toString());
507        logln("beginIndex = " + fp.getBeginIndex());
508        logln("endIndex = " + fp.getEndIndex());
509        if (fp.getBeginIndex() == fp.getEndIndex())
510            errln("Fail: Empty field");
511    }
512
513    /**
514     * @bug 4103340
515     * @bug 4138203
516     * This bug really only works in Locale.US, since that's what the locale
517     * used for Date.toString() is.  Bug 4138203 reports that it fails on Korean
518     * NT; it would actually have failed on any non-US locale.  Now it should
519     * work on all locales.
520     */
521    @Test
522    public void Test4103340() {
523
524        // choose a date that is the FIRST of some month
525        // and some arbitrary time
526        Calendar cal = Calendar.getInstance();
527        cal.clear();
528        cal.set(1997, 3, 1, 1, 1, 1);
529        Date d = cal.getTime();
530        SimpleDateFormat df = new SimpleDateFormat("MMMM", Locale.US);
531        String s = d.toString();
532        StringBuffer s2 = new StringBuffer("");
533        FieldPosition pos = new FieldPosition(0);
534        s2 = df.format(d, s2, pos);
535        logln("Date=" + s);
536        logln("DF=" + s2);
537        String substr = s2.substring(0,2);
538        if (s.indexOf(substr) == -1)
539          errln("Months should match");
540    }
541
542    /**
543     * @bug 4103341
544     */
545    @Test
546    public void Test4103341() {
547        TimeZone saveZone = TimeZone.getDefault();
548        try {
549            // {sfb} changed from adoptDefault to setDefault
550            TimeZone.setDefault(TimeZone.getTimeZone("CST"));
551            SimpleDateFormat simple = new SimpleDateFormat("MM/dd/yyyy HH:mm");
552            TimeZone temp = TimeZone.getDefault();
553            if (!simple.getTimeZone().equals(temp))
554                errln("Fail: SimpleDateFormat not using default zone");
555        } finally {
556            TimeZone.setDefault(saveZone);
557        }
558    }
559
560    /**
561     * @bug 4104136
562     */
563    @Test
564    public void Test4104136() {
565        SimpleDateFormat sdf = new SimpleDateFormat();
566        String pattern = "'time' hh:mm";
567        sdf.applyPattern(pattern);
568        logln("pattern: \"" + pattern + "\"");
569        String strings[] = {"time 10:30", "time 10:x", "time 10x"};
570        ParsePosition ppos[] = {new ParsePosition(10), new ParsePosition(0), new ParsePosition(0)};
571        Calendar cal = Calendar.getInstance();
572        cal.clear();
573        cal.set(1970, Calendar.JANUARY, 1, 10, 30);
574        Date dates[] = {cal.getTime(), new Date(-1), new Date(-1)};
575        for (int i = 0; i < 3; i++) {
576            String text = strings[i];
577            ParsePosition finish = ppos[i];
578            Date exp = dates[i];
579            ParsePosition pos = new ParsePosition(0);
580            Date d = sdf.parse(text, pos);
581            logln(" text: \"" + text + "\"");
582            logln(" index: %d" + pos.getIndex());
583            logln(" result: " + d);
584            if (pos.getIndex() != finish.getIndex())
585                errln("Fail: Expected pos " + finish.getIndex());
586            if (!((d == null && exp.equals(new Date(-1))) || (d.equals(exp))))
587                errln( "Fail: Expected result " + exp);
588        }
589    }
590
591    /**
592     * @bug 4104522
593     * CANNOT REPRODUCE
594     * According to the bug report, this test should throw a
595     * StringIndexOutOfBoundsException during the second parse.  However,
596     * this is not seen.
597     */
598    @Test
599    public void Test4104522() {
600        SimpleDateFormat sdf = new SimpleDateFormat();
601        String pattern = "'time' hh:mm";
602        sdf.applyPattern(pattern);
603        logln("pattern: \"" + pattern + "\"");
604        // works correctly
605        ParsePosition pp = new ParsePosition(0);
606        String text = "time ";
607        Date dt = sdf.parse(text, pp);
608        logln(" text: \"" + text + "\"" + " date: " + dt);
609        // works wrong
610        pp.setIndex(0);
611        text = "time";
612        dt = sdf.parse(text, pp);
613        logln(" text: \"" + text + "\"" + " date: " + dt);
614    }
615
616    /**
617     * @bug 4106807
618     */
619    @Test
620    public void Test4106807() {
621        Date dt;
622        DateFormat df = DateFormat.getDateTimeInstance();
623
624        SimpleDateFormat sdfs[] = {
625                new SimpleDateFormat("yyyyMMddHHmmss"),
626                new SimpleDateFormat("yyyyMMddHHmmss'Z'"),
627                new SimpleDateFormat("yyyyMMddHHmmss''"),
628                new SimpleDateFormat("yyyyMMddHHmmss'a''a'"),
629                new SimpleDateFormat("yyyyMMddHHmmss %")};
630        String strings[] = {
631                "19980211140000",
632                "19980211140000",
633                "19980211140000",
634                "19980211140000a",
635                "19980211140000 "};
636        GregorianCalendar gc = new GregorianCalendar();
637        TimeZone timeZone = TimeZone.getDefault();
638        TimeZone gmt = (TimeZone) timeZone.clone();
639        gmt.setRawOffset(0);
640        for (int i = 0; i < 5; i++) {
641            SimpleDateFormat format = sdfs[i];
642            String dateString = strings[i];
643            try {
644                format.setTimeZone(gmt);
645                dt = format.parse(dateString);
646                // {sfb} some of these parses will fail purposely
647
648                StringBuffer fmtd = new StringBuffer("");
649                FieldPosition pos = new FieldPosition(0);
650                fmtd = df.format(dt, fmtd, pos);
651                logln(fmtd.toString());
652                //logln(df.format(dt));
653                gc.setTime(dt);
654                logln("" + gc.get(Calendar.ZONE_OFFSET));
655                StringBuffer s = new StringBuffer("");
656                s = format.format(dt, s, pos);
657                logln(s.toString());
658            } catch (ParseException e) {
659                logln("No way Jose");
660            }
661        }
662    }
663
664    /*
665      Synopsis: Chinese time zone CTT is not recogonized correctly.
666      Description: Platform Chinese Windows 95 - ** Time zone set to CST **
667      */
668    /**
669     * @bug 4108407
670     */
671
672    // {sfb} what to do with this one ??
673    @Test
674    public void Test4108407() {
675        /*
676    // TODO user.timezone is a protected system property, catch securityexception and warn
677    // if this is reenabled
678        long l = System.currentTimeMillis();
679        logln("user.timezone = " + System.getProperty("user.timezone", "?"));
680        logln("Time Zone :" +
681                           DateFormat.getDateInstance().getTimeZone().getID());
682        logln("Default format :" +
683                           DateFormat.getDateInstance().format(new Date(l)));
684        logln("Full format :" +
685                           DateFormat.getDateInstance(DateFormat.FULL).format(new
686                                                                              Date(l)));
687        logln("*** Set host TZ to CST ***");
688        logln("*** THE RESULTS OF THIS TEST MUST BE VERIFIED MANUALLY ***");
689        */
690    }
691
692    /**
693     * @bug 4134203
694     * SimpleDateFormat won't parse "GMT"
695     */
696    @Test
697    public void Test4134203() {
698        String dateFormat = "MM/dd/yy HH:mm:ss zzz";
699        SimpleDateFormat fmt = new SimpleDateFormat(dateFormat);
700
701        ParsePosition p0 = new ParsePosition(0);
702        Date d = fmt.parse("01/22/92 04:52:00 GMT", p0);
703        logln(d.toString());
704        if(p0.equals(new ParsePosition(0)))
705            errln("Fail: failed to parse 'GMT'");
706        // In the failure case an exception is thrown by parse();
707        // if no exception is thrown, the test passes.
708    }
709
710    /**
711     * @bug 4151631
712     * SimpleDateFormat incorrect handling of 2 single quotes in format()
713     */
714    @Test
715    public void Test4151631() {
716        String pattern =
717            "'TO_DATE('''dd'-'MM'-'yyyy HH:mm:ss''' , ''DD-MM-YYYY HH:MI:SS'')'";
718        logln("pattern=" + pattern);
719        SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.US);
720        StringBuffer result = new StringBuffer("");
721        FieldPosition pos = new FieldPosition(0);
722        Calendar cal = Calendar.getInstance();
723        cal.clear();
724        cal.set(1998, Calendar.JUNE, 30, 13, 30, 0);
725        Date d = cal.getTime();
726        result = format.format(d, result, pos);
727        if (!result.toString().equals("TO_DATE('30-06-1998 13:30:00' , 'DD-MM-YYYY HH:MI:SS')")) {
728            errln("Fail: result=" + result);
729        } else {
730            logln("Pass: result=" + result);
731        }
732    }
733
734    /**
735     * @bug 4151706
736     * 'z' at end of date format throws index exception in SimpleDateFormat
737     * CANNOT REPRODUCE THIS BUG ON 1.2FCS
738     */
739    @Test
740    public void Test4151706() {
741        String dateString = "Thursday, 31-Dec-98 23:00:00 GMT";
742        SimpleDateFormat fmt = new SimpleDateFormat("EEEE, dd-MMM-yy HH:mm:ss z", Locale.US);
743        Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.US);
744        cal.clear();
745        cal.set(1998, Calendar.DECEMBER, 31, 23, 0, 0);
746        Date d = new Date();
747        try {
748            d = fmt.parse(dateString);
749            // {sfb} what about next two lines?
750            if (d.getTime() != cal.getTime().getTime())
751                errln("Incorrect value: " + d);
752        } catch (Exception e) {
753            errln("Fail: " + e);
754        }
755        StringBuffer temp = new StringBuffer("");
756        FieldPosition pos = new FieldPosition(0);
757        logln(dateString + " . " + fmt.format(d, temp, pos));
758    }
759
760    /**
761     * @bug 4162071
762     * Cannot reproduce this bug under 1.2 FCS -- it may be a convoluted duplicate
763     * of some other bug that has been fixed.
764     */
765    @Test
766    public void Test4162071() {
767        String dateString = "Thu, 30-Jul-1999 11:51:14 GMT";
768        String format = "EEE', 'dd-MMM-yyyy HH:mm:ss z"; // RFC 822/1123
769        SimpleDateFormat df = new SimpleDateFormat(format, Locale.US);
770        try {
771            Date x = df.parse(dateString);
772            StringBuffer temp = new StringBuffer("");
773            FieldPosition pos = new FieldPosition(0);
774            logln(dateString + " -> " + df.format(x, temp, pos));
775        } catch (Exception e) {
776            errln("Parse format \"" + format + "\" failed.");
777        }
778    }
779
780    /**
781     * DateFormat shouldn't parse year "-1" as a two-digit year (e.g., "-1" . 1999).
782     */
783    @Test
784    public void Test4182066() {
785        SimpleDateFormat fmt = new SimpleDateFormat("MM/dd/yy", Locale.US);
786        SimpleDateFormat dispFmt = new SimpleDateFormat("MMM dd yyyy HH:mm:ss GG", Locale.US);
787        /* We expect 2-digit year formats to put 2-digit years in the right
788         * window.  Out of range years, that is, anything less than "00" or
789         * greater than "99", are treated as literal years.  So "1/2/3456"
790         * becomes 3456 AD.  Likewise, "1/2/-3" becomes -3 AD == 2 BC.
791         */
792        final String STRINGS[] =
793            {"02/29/00", "01/23/01", "04/05/-1", "01/23/-9", "11/12/1314", "10/31/1", "09/12/+1", "09/12/001",};
794        int STRINGS_COUNT = STRINGS.length;
795
796        Calendar cal = Calendar.getInstance();
797        Date FAIL_DATE = cal.getTime();
798        cal.clear();
799        cal.set(2000, Calendar.FEBRUARY, 29);
800        Date d0 = cal.getTime();
801        cal.clear();
802        cal.set(2001, Calendar.JANUARY, 23);
803        Date d1 = cal.getTime();
804        cal.clear();
805        cal.set(-1, Calendar.APRIL, 5);
806        Date d2 = cal.getTime();
807        cal.clear();
808        cal.set(-9, Calendar.JANUARY, 23);
809        Date d3 = cal.getTime();
810        cal.clear();
811        cal.set(1314, Calendar.NOVEMBER, 12);
812        Date d4 = cal.getTime();
813        cal.clear();
814        cal.set(1, Calendar.OCTOBER, 31);
815        Date d5 = cal.getTime();
816        cal.clear();
817        cal.set(1, Calendar.SEPTEMBER, 12);
818        Date d7 = cal.getTime();
819        Date DATES[] = {d0, d1, d2, d3, d4, d5, FAIL_DATE, d7};
820
821        String out = "";
822        boolean pass = true;
823        for (int i = 0; i < STRINGS_COUNT; ++i) {
824            String str = STRINGS[i];
825            Date expected = DATES[i];
826            Date actual = null;
827            try {
828                actual = fmt.parse(str);
829            } catch (ParseException e) {
830                actual = FAIL_DATE;
831            }
832            String actStr = "";
833            if ((actual.getTime()) == FAIL_DATE.getTime()) {
834                actStr += "null";
835            } else {
836                // Yuck: See j25
837                actStr = ((DateFormat) dispFmt).format(actual);
838            }
839
840            if (expected.getTime() == (actual.getTime())) {
841                out += str + " => " + actStr + "\n";
842            } else {
843                String expStr = "";
844                if (expected.getTime() == FAIL_DATE.getTime()) {
845                    expStr += "null";
846                } else {
847                    // Yuck: See j25
848                    expStr = ((DateFormat) dispFmt).format(expected);
849                }
850                out += "FAIL: " + str + " => " + actStr + ", expected " + expStr + "\n";
851                pass = false;
852            }
853        }
854        if (pass) {
855            log(out);
856        } else {
857            err(out);
858        }
859    }
860
861    /**
862     * j32 {JDK Bug 4210209 4209272}
863     * DateFormat cannot parse Feb 29 2000 when setLenient(false)
864     */
865    @Test
866    public void Test4210209() {
867
868        String pattern = "MMM d, yyyy";
869        DateFormat fmt = new SimpleDateFormat(pattern, Locale.US);
870        DateFormat disp = new SimpleDateFormat("MMM dd yyyy GG", Locale.US);
871
872        Calendar calx = fmt.getCalendar();
873        calx.setLenient(false);
874        Calendar calendar = Calendar.getInstance();
875        calendar.clear();
876        calendar.set(2000, Calendar.FEBRUARY, 29);
877        Date d = calendar.getTime();
878        String s = fmt.format(d);
879        logln(disp.format(d) + " f> " + pattern + " => \"" + s + "\"");
880        ParsePosition pos = new ParsePosition(0);
881        d = fmt.parse(s, pos);
882        logln("\"" + s + "\" p> " + pattern + " => " +
883              (d!=null?disp.format(d):"null"));
884        logln("Parse pos = " + pos.getIndex() + ", error pos = " + pos.getErrorIndex());
885        if (pos.getErrorIndex() != -1) {
886            errln("FAIL: Error index should be -1");
887        }
888
889        // The underlying bug is in GregorianCalendar.  If the following lines
890        // succeed, the bug is fixed.  If the bug isn't fixed, they will throw
891        // an exception.
892        GregorianCalendar cal = new GregorianCalendar();
893        cal.clear();
894        cal.setLenient(false);
895        cal.set(2000, Calendar.FEBRUARY, 29); // This should work!
896        d = cal.getTime();
897        logln("Attempt to set Calendar to Feb 29 2000: " + disp.format(d));
898    }
899
900    @Test
901    public void Test714() {
902        //TimeZone Offset
903        TimeZone defaultTZ = TimeZone.getDefault();
904        TimeZone PST = TimeZone.getTimeZone("PST");
905        int defaultOffset = defaultTZ.getRawOffset();
906        int PSTOffset = PST.getRawOffset();
907        Date d = new Date(978103543000l - (defaultOffset - PSTOffset));
908        d = new Date(d.getTime() - (defaultTZ.inDaylightTime(d) ? 3600000 : 0));
909        DateFormat fmt = DateFormat.getDateTimeInstance(-1, DateFormat.MEDIUM, Locale.US);
910        String tests = "7:25:43 AM";
911        String s = fmt.format(d);
912        if (!s.equals(tests)) {
913            errln("Fail: " + s + " != " + tests);
914        } else {
915            logln("OK: " + s + " == " + tests);
916        }
917    }
918
919    @Test
920    public void Test_GEec() {
921        class PatternAndResult {
922            private String pattern;
923            private String result;
924            PatternAndResult(String pat, String res) {
925                pattern = pat;
926                result = res;
927            }
928            public String getPattern()  { return pattern; }
929            public String getResult()  { return result; }
930        }
931        final PatternAndResult[] tests = {
932            new PatternAndResult( "dd MMM yyyy GGG",   "02 Jul 2008 AD" ),
933            new PatternAndResult( "dd MMM yyyy GGGGG", "02 Jul 2008 A" ),
934            new PatternAndResult( "e dd MMM yyyy",     "4 02 Jul 2008" ),
935            new PatternAndResult( "ee dd MMM yyyy",    "04 02 Jul 2008" ),
936            new PatternAndResult( "c dd MMM yyyy",     "4 02 Jul 2008" ),
937            new PatternAndResult( "cc dd MMM yyyy",    "4 02 Jul 2008" ),
938            new PatternAndResult( "eee dd MMM yyyy",   "Wed 02 Jul 2008" ),
939            new PatternAndResult( "EEE dd MMM yyyy",   "Wed 02 Jul 2008" ),
940            new PatternAndResult( "EE dd MMM yyyy",    "Wed 02 Jul 2008" ),
941            new PatternAndResult( "eeee dd MMM yyyy",  "Wednesday 02 Jul 2008" ),
942            new PatternAndResult( "eeeee dd MMM yyyy", "W 02 Jul 2008" ),
943            new PatternAndResult( "e ww YYYY",         "4 27 2008" ),
944            new PatternAndResult( "c ww YYYY",         "4 27 2008" ),
945        };
946        ULocale loc = ULocale.ENGLISH;
947        TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
948        Calendar cal = new GregorianCalendar(tz, loc);
949        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MMM-dd", loc);
950        for ( int i = 0; i < tests.length; i++ ) {
951            PatternAndResult item = tests[i];
952            dateFormat.applyPattern( item.getPattern() );
953            cal.set(2008, 6, 2, 5, 0); // 2008 July 02 5 AM PDT
954            StringBuffer buf = new StringBuffer(32);
955            FieldPosition fp = new FieldPosition(DateFormat.YEAR_FIELD);
956            dateFormat.format(cal, buf, fp);
957            if ( buf.toString().compareTo(item.getResult()) != 0 ) {
958                errln("for pattern " + item.getPattern() + ", expected " + item.getResult() + ", got " + buf );
959            }
960            ParsePosition pos = new ParsePosition(0);
961            dateFormat.parse( item.getResult(), cal, pos);
962            int year = cal.get(Calendar.YEAR);
963            int month = cal.get(Calendar.MONTH);
964            int day = cal.get(Calendar.DATE);
965            if ( year != 2008 || month != 6 || day != 2 ) {
966                errln("use pattern " + item.getPattern() + " to parse " + item.getResult() +
967                        ", expected y2008 m6 d2, got " + year + " " + month + " " + day );
968            }
969        }
970    }
971
972    static final char kArabicZero = 0x0660;
973    static final char kHindiZero  = 0x0966;
974    static final char kLatinZero  = 0x0030;
975
976    @Test
977    public void TestHindiArabicDigits()
978    {
979        String s;
980        char first;
981        String what;
982
983        {
984            DateFormat df = DateFormat.getInstance(new GregorianCalendar(), new ULocale("hi_IN@numbers=deva"));
985            what = "Gregorian Calendar, hindi";
986            s = df.format(new Date(0)); /* 31/12/1969 */
987            logln(what + "=" + s);
988            first = s.charAt(0);
989            if(first<kHindiZero || first>(kHindiZero+9)) {
990                errln(what + "- wrong digit,  got " + s + " (integer digit value " + new Integer((int)first).toString());
991            }
992        }
993
994        {
995            DateFormat df = DateFormat.getInstance(new IslamicCalendar(), new Locale("ar","IQ"));
996            s = df.format(new Date(0)); /* 21/10/1989 */
997            what = "Islamic Calendar, Arabic";
998            logln(what + ": " + s);
999            first = s.charAt(0);
1000            if(first<kArabicZero || first>(kArabicZero+9)) {
1001                errln(what + " wrong digit, got " + s + " (integer digit value " + new Integer((int)first).toString());
1002            }
1003        }
1004
1005        {
1006            DateFormat df = DateFormat.getInstance(new GregorianCalendar(), new Locale("ar","IQ"));
1007            s = df.format(new Date(0)); /* 31/12/1969 */
1008            what = "Gregorian,  ar_IQ, df.getInstance";
1009            logln(what + ": " + s);
1010            first = s.charAt(0);
1011            if(first<kArabicZero || first>(kArabicZero+9)) {
1012                errln(what + " wrong  digit but got " + s + " (integer digit value " + new Integer((int)first).toString());
1013            }
1014        }
1015        {
1016            DateFormat df = DateFormat.getInstance(new GregorianCalendar(), new Locale("mt","MT"));
1017            s = df.format(new Date(0)); /* 31/12/1969 */
1018            what = "Gregorian,  mt_MT, df.getInstance";
1019            logln(what + ": " + s);
1020            first = s.charAt(0);
1021            if(first<kLatinZero || first>(kLatinZero+9)) {
1022                errln(what + " wrong  digit but got " + s + " (integer digit value " + new Integer((int)first).toString());
1023            }
1024        }
1025
1026        {
1027            DateFormat df = DateFormat.getInstance(new IslamicCalendar(), new Locale("ar","IQ"));
1028            s = df.format(new Date(0)); /* 31/12/1969 */
1029            what = "Islamic calendar, ar_IQ, df.getInstance";
1030            logln(what+ ": " + s);
1031            first = s.charAt(0);
1032            if(first<kArabicZero || first>(kArabicZero+9)) {
1033                errln(what + " wrong  digit but got " + s + " (integer digit value " + new Integer((int)first).toString());
1034            }
1035        }
1036
1037        {
1038            DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, new Locale("ar","IQ"));
1039            s = df.format(new Date(0)); /* 31/12/1969 */
1040            what = "ar_IQ, getDateTimeInstance";
1041            logln(what+ ": " + s);
1042            first = s.charAt(0);
1043            if(first<kArabicZero || first>(kArabicZero+9)) {
1044                errln(what + " wrong  digit but got " + s + " (integer digit value " + new Integer((int)first).toString());
1045            }
1046        }
1047
1048        {
1049            DateFormat df = DateFormat.getInstance(new JapaneseCalendar(), new Locale("ar","IQ"));
1050            s = df.format(new Date(0)); /* 31/12/1969 */
1051            what = "ar_IQ, Japanese Calendar, getInstance";
1052            logln(what+ ": " + s);
1053            first = s.charAt(0);
1054            if(first<kArabicZero || first>(kArabicZero+9)) {
1055                errln(what + " wrong  digit but got " + s + " (integer digit value " + new Integer((int)first).toString());
1056            }
1057        }
1058    }
1059
1060    // Ticket#5683
1061    // Some ICU4J 3.6 data files contain garbage data which prevent the code to resolve another
1062    // bundle as an alias.  zh_TW should be equivalent to zh_Hant_TW
1063    @Test
1064    public void TestT5683() {
1065        Locale[] aliasLocales = {
1066            new Locale("zh", "CN"),
1067            new Locale("zh", "TW"),
1068            new Locale("zh", "HK"),
1069            new Locale("zh", "SG"),
1070            new Locale("zh", "MO")
1071        };
1072
1073        ULocale[] canonicalLocales = {
1074            new ULocale("zh_Hans_CN"),
1075            new ULocale("zh_Hant_TW"),
1076            new ULocale("zh_Hant_HK"),
1077            new ULocale("zh_Hans_SG"),
1078            new ULocale("zh_Hant_MO")
1079        };
1080
1081        Date d = new Date(0);
1082
1083        for (int i = 0; i < aliasLocales.length; i++) {
1084            DateFormat dfAlias = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, aliasLocales[i]);
1085            DateFormat dfCanonical = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, canonicalLocales[i]);
1086
1087            String sAlias = dfAlias.format(d);
1088            String sCanonical = dfCanonical.format(d);
1089
1090            if (!sAlias.equals(sCanonical)) {
1091                errln("Fail: The format result for locale " + aliasLocales[i] + " is different from the result for locale " + canonicalLocales[i]
1092                        + ": " + sAlias + "[" + aliasLocales[i] + "] / " + sCanonical + "[" + canonicalLocales[i] + "]");
1093            }
1094        }
1095    }
1096
1097    // Note: The purpose of this test case is a little bit questionable. This test
1098    // case expects Islamic month name is different from Gregorian month name.
1099    // However, some locales (in this code, zh_CN) may intentionally use the same
1100    // month name for both Gregorian and Islamic calendars. See #9645.
1101    @Test
1102    public void Test5006GetShortMonths() throws Exception {
1103        // Currently supported NLV locales
1104        Locale ENGLISH = new Locale("en", "US"); // We don't support 'en' alone
1105        Locale ARABIC = new Locale("ar", "");
1106        Locale CZECH = new Locale("cs", "");
1107        Locale GERMAN = new Locale("de", "");
1108        Locale GREEK = new Locale("el", "");
1109        Locale SPANISH = new Locale("es", "");
1110        Locale FRENCH = new Locale("fr", "");
1111        Locale HUNGARIAN = new Locale("hu", "");
1112        Locale ITALIAN = new Locale("it", "");
1113        Locale HEBREW = new Locale("iw", "");
1114        Locale JAPANESE = new Locale("ja", "");
1115        Locale KOREAN = new Locale("ko", "");
1116        Locale POLISH = new Locale("pl", "");
1117        Locale PORTUGUESE = new Locale("pt", "BR");
1118        Locale RUSSIAN = new Locale("ru", "");
1119        Locale TURKISH = new Locale("tr", "");
1120        Locale CHINESE_SIMPLIFIED = new Locale("zh", "CN");
1121        Locale CHINESE_TRADITIONAL = new Locale("zh", "TW");
1122
1123        Locale[] locales = new Locale[] { ENGLISH, ARABIC, CZECH, GERMAN, GREEK, SPANISH, FRENCH,
1124                HUNGARIAN, ITALIAN, HEBREW, JAPANESE, KOREAN, POLISH, PORTUGUESE, RUSSIAN, TURKISH,
1125                CHINESE_SIMPLIFIED, CHINESE_TRADITIONAL };
1126
1127        String[] islamicCivilTwelfthMonthLocalized = new String[locales.length];
1128        String[] islamicTwelfthMonthLocalized = new String[locales.length];
1129        String[] gregorianTwelfthMonthLocalized = new String[locales.length];
1130
1131        for (int i = 0; i < locales.length; i++) {
1132
1133            Locale locale = locales[i];
1134
1135            // Islamic
1136            android.icu.util.Calendar islamicCivilCalendar = new android.icu.util.IslamicCalendar(locale);
1137            android.icu.text.SimpleDateFormat islamicCivilDateFormat = (android.icu.text.SimpleDateFormat) islamicCivilCalendar
1138                    .getDateTimeFormat(android.icu.text.DateFormat.FULL, -1, locale);
1139            android.icu.text.DateFormatSymbols islamicCivilDateFormatSymbols = islamicCivilDateFormat
1140                    .getDateFormatSymbols();
1141
1142            String[] shortMonthsCivil = islamicCivilDateFormatSymbols.getShortMonths();
1143            String twelfthMonthLocalizedCivil = shortMonthsCivil[11];
1144
1145            islamicCivilTwelfthMonthLocalized[i] = twelfthMonthLocalizedCivil;
1146
1147            android.icu.util.IslamicCalendar islamicCalendar = new android.icu.util.IslamicCalendar(locale);
1148            islamicCalendar.setCivil(false);
1149            android.icu.text.SimpleDateFormat islamicDateFormat = (android.icu.text.SimpleDateFormat) islamicCalendar
1150                    .getDateTimeFormat(android.icu.text.DateFormat.FULL, -1, locale);
1151            android.icu.text.DateFormatSymbols islamicDateFormatSymbols = islamicDateFormat
1152                    .getDateFormatSymbols();
1153
1154            String[] shortMonths = islamicDateFormatSymbols.getShortMonths();
1155            String twelfthMonthLocalized = shortMonths[11];
1156
1157            islamicTwelfthMonthLocalized[i] = twelfthMonthLocalized;
1158
1159            // Gregorian
1160            android.icu.util.Calendar gregorianCalendar = new android.icu.util.GregorianCalendar(
1161                    locale);
1162            android.icu.text.SimpleDateFormat gregorianDateFormat = (android.icu.text.SimpleDateFormat) gregorianCalendar
1163                    .getDateTimeFormat(android.icu.text.DateFormat.FULL, -1, locale);
1164
1165            android.icu.text.DateFormatSymbols gregorianDateFormatSymbols = gregorianDateFormat
1166                    .getDateFormatSymbols();
1167            shortMonths = gregorianDateFormatSymbols.getShortMonths();
1168            twelfthMonthLocalized = shortMonths[11];
1169
1170            gregorianTwelfthMonthLocalized[i] = twelfthMonthLocalized;
1171
1172        }
1173
1174        // Compare
1175        for (int i = 0; i < locales.length; i++) {
1176
1177            String gregorianTwelfthMonth = gregorianTwelfthMonthLocalized[i];
1178            String islamicCivilTwelfthMonth = islamicCivilTwelfthMonthLocalized[i];
1179            String islamicTwelfthMonth = islamicTwelfthMonthLocalized[i];
1180
1181            logln(locales[i] + ": g:" + gregorianTwelfthMonth + ", ic:" + islamicCivilTwelfthMonth + ", i:"+islamicTwelfthMonth);
1182            if (gregorianTwelfthMonth.equalsIgnoreCase(islamicTwelfthMonth)) {
1183                // Simplified Chinese uses numeric month for both Gregorian/Islamic calendars
1184                if (locales[i] != CHINESE_SIMPLIFIED) {
1185                    errln(locales[i] + ": gregorian and islamic are same: " + gregorianTwelfthMonth
1186                          + ", " + islamicTwelfthMonth);
1187                }
1188            }
1189
1190            if (gregorianTwelfthMonth.equalsIgnoreCase(islamicCivilTwelfthMonth)) {
1191                // Simplified Chinese uses numeric month for both Gregorian/Islamic calendars
1192                if (locales[i] != CHINESE_SIMPLIFIED) {
1193                    errln(locales[i] + ": gregorian and islamic-civil are same: " + gregorianTwelfthMonth
1194                            + ", " + islamicCivilTwelfthMonth);
1195                }
1196            }
1197            if (!islamicTwelfthMonth.equalsIgnoreCase(islamicCivilTwelfthMonth)) {
1198                errln(locales[i] + ": islamic-civil and islamic are NOT same: " + islamicCivilTwelfthMonth
1199                        + ", " + islamicTwelfthMonth);
1200            }
1201        }
1202    }
1203
1204    @Test
1205    public void TestParsing() {
1206        String pattern = "EEE-WW-MMMM-yyyy";
1207        String text = "mon-02-march-2011";
1208        int expectedDay = 7;
1209
1210        SimpleDateFormat format = new SimpleDateFormat(pattern);
1211        Calendar cal = GregorianCalendar.getInstance(Locale.US);
1212        ParsePosition pos = new ParsePosition(0);
1213
1214        try {
1215            format.parse(text, cal, pos);
1216        } catch (Exception e) {
1217            errln("Fail parsing:  " + e);
1218        }
1219
1220        if (cal.get(Calendar.DAY_OF_MONTH) != expectedDay) {
1221            errln("Parsing failed: day of month should be '7' with pattern: \"" + pattern + "\" for text: \"" + text + "\"");
1222        }
1223    }
1224
1225    // Date formatting with Dangi calendar in en locale (#9987)
1226    @Test
1227    public void TestDangiFormat() {
1228        DateFormat fmt = DateFormat.getDateInstance(DateFormat.MEDIUM, new ULocale("en@calendar=dangi"));
1229        String calType = fmt.getCalendar().getType();
1230        assertEquals("Incorrect calendar type used by the date format instance", "dangi", calType);
1231
1232        GregorianCalendar gcal = new GregorianCalendar();
1233        gcal.set(2013, Calendar.MARCH, 1, 0, 0, 0);
1234        Date d = gcal.getTime();
1235
1236        String dangiDateStr = fmt.format(d);
1237        assertEquals("Bad date format", "Mo1 20, 2013", dangiDateStr);
1238    }
1239
1240    @Test
1241    public void TestT10110() {
1242        try {
1243            SimpleDateFormat formatter = new SimpleDateFormat("Gy年M月d日E", new Locale("zh_Hans"));
1244            /* Object parsed = */ formatter.parseObject("610000");
1245        }
1246        catch(ParseException pe) {
1247            return;
1248        }
1249        catch(Throwable t) {
1250            errln("ParseException not thrown for bad pattern! exception was: " + t.getLocalizedMessage());
1251            return;
1252        }
1253        errln("No exception thrown at all for bad pattern!");
1254    }
1255
1256    @Test
1257    public void TestT10239() {
1258
1259        class TestDateFormatItem {
1260            public String parseString;
1261            public String pattern;
1262            public String expectedResult;   // null indicates expected error
1263            // Simple constructor
1264            public TestDateFormatItem(String parString, String patt, String expResult) {
1265                pattern = patt;
1266                parseString = parString;
1267                expectedResult = expResult;
1268            }
1269        };
1270
1271        final TestDateFormatItem[] items = {
1272        //                     parse String                 pattern                 expected result
1273        new TestDateFormatItem("1 Oct 13 2013",             "e MMM dd yyyy",        "1 Oct 13 2013"),
1274        new TestDateFormatItem("02 Oct 14 2013",            "ee MMM dd yyyy",       "02 Oct 14 2013"),
1275        new TestDateFormatItem("Tue Oct 15 2013",           "eee MMM dd yyyy",      "Tue Oct 15 2013"),
1276        new TestDateFormatItem("Wednesday  Oct 16 2013",    "eeee MMM dd yyyy",     "Wednesday Oct 16 2013"),
1277        new TestDateFormatItem("Th Oct 17 2013",            "eeeeee MMM dd yyyy",   "Th Oct 17 2013"),
1278        new TestDateFormatItem("Fr Oct 18 2013",            "EEEEEE MMM dd yyyy",   "Fr Oct 18 2013"),
1279        new TestDateFormatItem("S Oct 19 2013",             "eeeee MMM dd yyyy",    "S Oct 19 2013"),
1280        new TestDateFormatItem("S Oct 20 2013",             "EEEEE MMM dd yyyy",    "S Oct 20 2013"),
1281        };
1282
1283        StringBuffer result = new StringBuffer();
1284        Date d = new Date();
1285        Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT"), Locale.US);
1286        SimpleDateFormat sdfmt = new SimpleDateFormat();
1287        ParsePosition p = new ParsePosition(0);
1288        for (TestDateFormatItem item: items) {
1289            cal.clear();
1290            sdfmt.setCalendar(cal);
1291            sdfmt.applyPattern(item.pattern);
1292            result.setLength(0);
1293            p.setIndex(0);
1294            p.setErrorIndex(-1);
1295            d = sdfmt.parse(item.parseString, p);
1296            if(item.expectedResult == null) {
1297                if(p.getErrorIndex() != -1)
1298                    continue;
1299                else
1300                    errln("error: unexpected parse success..."+item.parseString + " should have failed");
1301            }
1302            if(p.getErrorIndex() != -1) {
1303                errln("error: parse error for string " +item.parseString + " against pattern " + item.pattern + " -- idx["+p.getIndex()+"] errIdx["+p.getErrorIndex()+"]");
1304                continue;
1305            }
1306            cal.setTime(d);
1307            result = sdfmt.format(cal, result, new FieldPosition(0));
1308            if(!result.toString().equalsIgnoreCase(item.expectedResult)) {
1309                errln("error: unexpected format result. expected - " + item.expectedResult + "  but result was - " + result);
1310            } else {
1311                logln("formatted results match! - " + result.toString());
1312            }
1313        }
1314  }
1315
1316
1317    @Test
1318    public void TestT10334() {
1319        String pattern = new String("'--: 'EEE-WW-MMMM-yyyy");
1320        String text = new String("--mon-02-march-2011");
1321        SimpleDateFormat format = new SimpleDateFormat(pattern);
1322
1323        format.setBooleanAttribute(DateFormat.BooleanAttribute.PARSE_PARTIAL_LITERAL_MATCH, false);
1324        try {
1325            format.parse(text);
1326            errln("parse partial match did NOT fail in strict mode!");
1327        } catch (ParseException pe) {
1328            // expected
1329        }
1330
1331        format.setBooleanAttribute(DateFormat.BooleanAttribute.PARSE_PARTIAL_LITERAL_MATCH, true);
1332        try {
1333            format.parse(text);
1334        } catch (ParseException pe) {
1335            errln("parse partial match failure in lenient mode: " + pe.getLocalizedMessage());
1336        }
1337
1338        pattern = new String("YYYY MM dd");
1339        text =    new String("2013 12 10");
1340        format.applyPattern(pattern);
1341        Date referenceDate = null;
1342        try {
1343            referenceDate = format.parse(text);
1344        } catch (ParseException pe) {
1345            errln("unable to instantiate reference date: " + pe.getLocalizedMessage());
1346        }
1347
1348        FieldPosition fp = new FieldPosition(0);
1349        pattern = new String("YYYY LL dd ee cc qq QQ");
1350        format.applyPattern(pattern);
1351        StringBuffer formattedString = new StringBuffer();
1352        formattedString = format.format(referenceDate, formattedString, fp);
1353        logln("ref date: " + formattedString);
1354
1355
1356        pattern = new String("YYYY LLL dd eee ccc qqq QQQ");
1357        text = new String("2013 12 10 03 3 04 04");
1358        format.applyPattern(pattern);
1359        logln(format.format(referenceDate));
1360
1361        format.setBooleanAttribute(DateFormat.BooleanAttribute.PARSE_ALLOW_NUMERIC, true);
1362        ParsePosition pp = new ParsePosition(0);
1363        format.parse(text, pp);
1364        int errorIdx = pp.getErrorIndex();
1365        if (errorIdx != -1) {
1366
1367            errln("numeric parse error at["+errorIdx+"] on char["+pattern.substring(errorIdx, errorIdx+1)+"] in pattern["+pattern+"]");
1368        }
1369
1370        format.setBooleanAttribute(DateFormat.BooleanAttribute.PARSE_ALLOW_NUMERIC, false);
1371        try {
1372        format.parse(text);
1373        errln("numeric parse did NOT fail in strict mode!");
1374        } catch (ParseException pe) {
1375            // expected
1376        }
1377
1378        /*
1379         * test to verify new code (and improve code coverage) for normal quarter processing
1380         */
1381        text = new String("2013 Dec 10 Thu Thu Q4 Q4");
1382        try {
1383            format.parse(text);
1384        } catch (ParseException pe) {
1385            errln("normal quarter processing failed");
1386        }
1387
1388    }
1389
1390    @Test
1391    public void TestT10619() {
1392
1393        class TestDateFormatLeniencyItem {
1394            public boolean leniency;
1395            public String parseString;
1396            public String pattern;
1397            public String expectedResult;   // null indicates expected error
1398             // Simple constructor
1399            public TestDateFormatLeniencyItem(boolean len, String parString, String patt, String expResult) {
1400                leniency = len;
1401                pattern = patt;
1402                parseString = parString;
1403                expectedResult = expResult;
1404            }
1405        };
1406
1407        final TestDateFormatLeniencyItem[] items = {
1408            //                             leniency    parse String       pattern                 expected result
1409            new TestDateFormatLeniencyItem(true,       "2008-Jan 02",     "yyyy-LLL. dd",         "2008-Jan. 02"),
1410            new TestDateFormatLeniencyItem(false,      "2008-Jan 03",     "yyyy-LLL. dd",         null),
1411            new TestDateFormatLeniencyItem(true,       "2008-Jan--04",    "yyyy-MMM' -- 'dd",     "2008-Jan -- 04"),
1412            new TestDateFormatLeniencyItem(false,      "2008-Jan--05",    "yyyy-MMM' -- 'dd",     null),
1413            new TestDateFormatLeniencyItem(true,       "2008-12-31",      "yyyy-mm-dd",           "2008-12-31"),
1414            new TestDateFormatLeniencyItem(false,      "6 Jan 05 2008",   "eee MMM dd yyyy",      null),
1415            new TestDateFormatLeniencyItem(true,       "6 Jan 05 2008",   "eee MMM dd yyyy",      "Sat Jan 05 2008"),
1416        };
1417
1418        StringBuffer result = new StringBuffer();
1419        Date d = new Date();
1420        Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT"), Locale.US);
1421        SimpleDateFormat sdfmt = new SimpleDateFormat();
1422        ParsePosition p = new ParsePosition(0);
1423        for (TestDateFormatLeniencyItem item: items) {
1424            cal.clear();
1425            sdfmt.setCalendar(cal);
1426            sdfmt.applyPattern(item.pattern);
1427            sdfmt.setLenient(item.leniency);
1428            result.setLength(0);
1429            p.setIndex(0);
1430            p.setErrorIndex(-1);
1431            d = sdfmt.parse(item.parseString, p);
1432            if(item.expectedResult == null) {
1433                if(p.getErrorIndex() != -1)
1434                    continue;
1435                else
1436                    errln("error: unexpected parse success..."+item.parseString + " w/ lenient="+item.leniency+" should have failed");
1437            }
1438            if(p.getErrorIndex() != -1) {
1439                errln("error: parse error for string " +item.parseString + " -- idx["+p.getIndex()+"] errIdx["+p.getErrorIndex()+"]");
1440                continue;
1441            }
1442            cal.setTime(d);
1443            result = sdfmt.format(cal, result, new FieldPosition(0));
1444            if(!result.toString().equalsIgnoreCase(item.expectedResult)) {
1445                errln("error: unexpected format result. expected - " + item.expectedResult + "  but result was - " + result);
1446            } else {
1447                logln("formatted results match! - " + result.toString());
1448            }
1449        }
1450  }
1451
1452    @Test
1453  public void TestT10906()
1454  {
1455      String pattern = new String("MM-dd-yyyy");
1456      String text = new String("06-10-2014");
1457      SimpleDateFormat format = new SimpleDateFormat(pattern);
1458      ParsePosition pp = new ParsePosition(-1);
1459      try {
1460          format.parse(text, pp);
1461          int errorIdx = pp.getErrorIndex();
1462          if (errorIdx == -1) {
1463              errln("failed to report invalid (negative) starting parse position");
1464          }
1465      } catch(StringIndexOutOfBoundsException e) {
1466          errln("failed to fix invalid (negative) starting parse position");
1467      }
1468
1469  }
1470
1471    // Test case for numeric field format threading problem
1472    @Test
1473    public void TestT11363() {
1474
1475        class TestThread extends Thread {
1476            SimpleDateFormat fmt;
1477            Date d;
1478
1479            TestThread(SimpleDateFormat fmt, Date d) {
1480                this.fmt = fmt;
1481                this.d = d;
1482            }
1483
1484            public void run() {
1485                String s0 = fmt.format(d);
1486                for (int i = 0; i < 1000; i++) {
1487                    String s = fmt.format(d);
1488                    if (!s0.equals(s)) {
1489                        errln("Result: " + s + ", Expected: " + s0);
1490                    }
1491                }
1492            }
1493        }
1494
1495        SimpleDateFormat fmt0 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
1496
1497        Thread[] threads = new Thread[10];
1498
1499        GregorianCalendar cal = new GregorianCalendar(2014, Calendar.NOVEMBER, 5, 12, 34, 56);
1500        cal.set(Calendar.MILLISECOND, 777);
1501
1502        // calls format() once on the base object to trigger
1503        // lazy initialization stuffs.
1504        fmt0.format(cal.getTime());
1505
1506        for (int i = 0; i < threads.length; i++) {
1507            // Add 1 to all fields to use different numbers in each thread
1508            cal.add(Calendar.YEAR, 1);
1509            cal.add(Calendar.MONTH, 1);
1510            cal.add(Calendar.DAY_OF_MONTH, 1);
1511            cal.add(Calendar.HOUR_OF_DAY, 1);
1512            cal.add(Calendar.MINUTE, 1);
1513            cal.add(Calendar.SECOND, 1);
1514            cal.add(Calendar.MILLISECOND, 1);
1515            Date d = cal.getTime();
1516            SimpleDateFormat fmt = (SimpleDateFormat)fmt0.clone();
1517            threads[i] = new TestThread(fmt, d);
1518        }
1519
1520        for (Thread t : threads) {
1521            t.start();
1522        }
1523
1524        for (Thread t : threads) {
1525            try {
1526                t.join();
1527            } catch (InterruptedException e) {
1528                errln(e.toString());
1529            }
1530        }
1531    }
1532}
1533