1/*
2 *******************************************************************************
3 * Copyright (C) 2001-2015, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 *******************************************************************************
6 */
7
8/**
9 * Port From:   ICU4C v1.8.1 : format : DateFormatTest
10 * Source File: $ICU4CRoot/source/test/intltest/dtfmttst.cpp
11 **/
12
13package com.ibm.icu.dev.test.format;
14
15import java.io.ByteArrayInputStream;
16import java.io.ByteArrayOutputStream;
17import java.io.IOException;
18import java.io.ObjectInputStream;
19import java.io.ObjectOutputStream;
20import java.text.AttributedCharacterIterator;
21import java.text.CharacterIterator;
22import java.text.FieldPosition;
23import java.text.ParseException;
24import java.text.ParsePosition;
25import java.util.ArrayList;
26import java.util.Arrays;
27import java.util.Date;
28import java.util.EnumSet;
29import java.util.Iterator;
30import java.util.List;
31import java.util.Locale;
32import java.util.Map;
33import java.util.ResourceBundle;
34import java.util.Set;
35
36import com.ibm.icu.impl.ICUResourceBundle;
37import com.ibm.icu.text.ChineseDateFormat;
38import com.ibm.icu.text.ChineseDateFormat.Field;
39import com.ibm.icu.text.ChineseDateFormatSymbols;
40import com.ibm.icu.text.DateFormat;
41import com.ibm.icu.text.DateFormat.BooleanAttribute;
42import com.ibm.icu.text.DateFormatSymbols;
43import com.ibm.icu.text.DisplayContext;
44import com.ibm.icu.text.NumberFormat;
45import com.ibm.icu.text.SimpleDateFormat;
46import com.ibm.icu.text.TimeZoneFormat;
47import com.ibm.icu.text.TimeZoneFormat.ParseOption;
48import com.ibm.icu.util.BuddhistCalendar;
49import com.ibm.icu.util.Calendar;
50import com.ibm.icu.util.ChineseCalendar;
51import com.ibm.icu.util.GregorianCalendar;
52import com.ibm.icu.util.HebrewCalendar;
53import com.ibm.icu.util.IslamicCalendar;
54import com.ibm.icu.util.JapaneseCalendar;
55import com.ibm.icu.util.TimeZone;
56import com.ibm.icu.util.ULocale;
57import com.ibm.icu.util.UResourceBundle;
58import com.ibm.icu.util.VersionInfo;
59
60public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
61
62    public static void main(String[] args) throws Exception {
63        new DateFormatTest().run(args);
64    }
65
66    /**
67     * Verify that patterns have the correct values and could produce the
68     * the DateFormat instances that contain the correct localized patterns.
69     */
70    public void TestPatterns() {
71        final String[][] EXPECTED = {
72                {DateFormat.YEAR, "y","en","y"},
73
74                {DateFormat.QUARTER, "QQQQ", "en", "QQQQ"},
75                {DateFormat.ABBR_QUARTER, "QQQ", "en", "QQQ"},
76                {DateFormat.YEAR_QUARTER, "yQQQQ", "en", "QQQQ y"},
77                {DateFormat.YEAR_ABBR_QUARTER, "yQQQ", "en", "QQQ y"},
78
79                {DateFormat.NUM_MONTH, "M", "en", "L"},
80                {DateFormat.ABBR_MONTH, "MMM", "en", "LLL"},
81                {DateFormat.MONTH, "MMMM", "en", "LLLL"},
82                {DateFormat.YEAR_NUM_MONTH, "yM","en","M/y"},
83                {DateFormat.YEAR_ABBR_MONTH, "yMMM","en","MMM y"},
84                {DateFormat.YEAR_MONTH, "yMMMM","en","MMMM y"},
85
86                {DateFormat.DAY, "d","en","d"},
87                {DateFormat.YEAR_NUM_MONTH_DAY, "yMd", "en", "M/d/y"},
88                {DateFormat.YEAR_ABBR_MONTH_DAY, "yMMMd", "en", "MMM d, y"},
89                {DateFormat.YEAR_MONTH_DAY, "yMMMMd", "en", "MMMM d, y"},
90                {DateFormat.YEAR_NUM_MONTH_WEEKDAY_DAY, "yMEd", "en", "EEE, M/d/y"},
91                {DateFormat.YEAR_ABBR_MONTH_WEEKDAY_DAY, "yMMMEd", "en", "EEE, MMM d, y"},
92                {DateFormat.YEAR_MONTH_WEEKDAY_DAY, "yMMMMEEEEd", "en", "EEEE, MMMM d, y"},
93
94                {DateFormat.NUM_MONTH_DAY, "Md","en","M/d"},
95                {DateFormat.ABBR_MONTH_DAY, "MMMd","en","MMM d"},
96                {DateFormat.MONTH_DAY, "MMMMd","en","MMMM d"},
97                {DateFormat.NUM_MONTH_WEEKDAY_DAY, "MEd","en","EEE, M/d"},
98                {DateFormat.ABBR_MONTH_WEEKDAY_DAY, "MMMEd","en","EEE, MMM d"},
99                {DateFormat.MONTH_WEEKDAY_DAY, "MMMMEEEEd","en","EEEE, MMMM d"},
100
101                {DateFormat.HOUR, "j", "en", "h a"}, // (fixed expected result per ticket 6872<-6626)
102                {DateFormat.HOUR24, "H", "en", "HH"}, // (fixed expected result per ticket 6872<-6626
103
104                {DateFormat.MINUTE, "m", "en", "m"},
105                {DateFormat.HOUR_MINUTE, "jm","en","h:mm a"}, // (fixed expected result per ticket 6872<-7180)
106                {DateFormat.HOUR24_MINUTE, "Hm", "en", "HH:mm"}, // (fixed expected result per ticket 6872<-6626)
107
108                {DateFormat.SECOND, "s", "en", "s"},
109                {DateFormat.HOUR_MINUTE_SECOND, "jms","en","h:mm:ss a"}, // (fixed expected result per ticket 6872<-7180)
110                {DateFormat.HOUR24_MINUTE_SECOND, "Hms","en","HH:mm:ss"}, // (fixed expected result per ticket 6872<-6626)
111                {DateFormat.MINUTE_SECOND, "ms", "en", "mm:ss"}, // (fixed expected result per ticket 6872<-6626)
112
113                {DateFormat.LOCATION_TZ, "VVVV", "en", "VVVV"},
114                {DateFormat.GENERIC_TZ, "vvvv", "en", "vvvv"},
115                {DateFormat.ABBR_GENERIC_TZ, "v", "en", "v"},
116                {DateFormat.SPECIFIC_TZ, "zzzz", "en", "zzzz"},
117                {DateFormat.ABBR_SPECIFIC_TZ, "z", "en", "z"},
118                {DateFormat.ABBR_UTC_TZ, "ZZZZ", "en", "ZZZZ"},
119
120                {DateFormat.YEAR_NUM_MONTH_DAY + DateFormat.ABBR_UTC_TZ, "yMdZZZZ", "en", "M/d/y, ZZZZ"},
121                {DateFormat.MONTH_DAY + DateFormat.LOCATION_TZ, "MMMMdVVVV", "en", "MMMM d, VVVV"},
122        };
123        Date testDate = new Date(2012-1900, 6, 1, 14, 58, 59); // just for verbose log
124
125        for (int i = 0; i < EXPECTED.length; i++) {
126            boolean ok = true;
127            // Verify that patterns have the correct values
128            String actualPattern = EXPECTED[i][0];
129            String expectedPattern = EXPECTED[i][1];
130            ULocale locale = new ULocale(EXPECTED[i][2], "", "");
131            if (!actualPattern.equals(expectedPattern)) {
132                errln("FAILURE! Expected pattern: " + expectedPattern +
133                        " but was: " + actualPattern);
134                ok=false;
135            }
136
137            // Verify that DataFormat instances produced contain the correct
138            // localized patterns
139            DateFormat date1 = DateFormat.getPatternInstance(actualPattern,
140                    locale);
141            DateFormat date2 = DateFormat.getPatternInstance(Calendar.getInstance(locale),
142                    actualPattern, locale);
143
144            String expectedLocalPattern = EXPECTED[i][3];
145            String actualLocalPattern1 = ((SimpleDateFormat)date1).toLocalizedPattern();
146            String actualLocalPattern2 = ((SimpleDateFormat)date2).toLocalizedPattern();
147            if (!actualLocalPattern1.equals(expectedLocalPattern)) {
148                errln("FAILURE! Expected local pattern: " + expectedLocalPattern
149                        + " but was: " + actualLocalPattern1);
150                ok=false;
151            }
152            if (!actualLocalPattern2.equals(expectedLocalPattern)) {
153                errln("FAILURE! Expected local pattern: " + expectedLocalPattern
154                        + " but was: " + actualLocalPattern2);
155                ok=false;
156            }
157            if (ok && isVerbose()) {
158                logln(date1.format(testDate) + "\t\t" + Arrays.asList(EXPECTED[i]));
159            }
160        }
161    }
162
163    // Test written by Wally Wedel and emailed to me.
164    public void TestWallyWedel() {
165        /*
166         * Instantiate a TimeZone so we can get the ids.
167         */
168        //TimeZone tz = new SimpleTimeZone(7, ""); //The variable is never used
169        /*
170         * Computational variables.
171         */
172        int offset, hours, minutes, seconds;
173        /*
174         * Instantiate a SimpleDateFormat set up to produce a full time
175         zone name.
176         */
177        SimpleDateFormat sdf = new SimpleDateFormat("zzzz");
178        /*
179         * A String array for the time zone ids.
180         */
181
182        final String[] ids = TimeZone.getAvailableIDs();
183        int ids_length = ids.length; //when fixed the bug should comment it out
184
185        /*
186         * How many ids do we have?
187         */
188        logln("Time Zone IDs size:" + ids_length);
189        /*
190         * Column headings (sort of)
191         */
192        logln("Ordinal ID offset(h:m) name");
193        /*
194         * Loop through the tzs.
195         */
196        Date today = new Date();
197        Calendar cal = Calendar.getInstance();
198        for (int i = 0; i < ids_length; i++) {
199            logln(i + " " + ids[i]);
200            TimeZone ttz = TimeZone.getTimeZone(ids[i]);
201            // offset = ttz.getRawOffset();
202            cal.setTimeZone(ttz);
203            cal.setTime(today);
204            offset = cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET);
205            // logln(i + " " + ids[i] + " offset " + offset);
206            String sign = "+";
207            if (offset < 0) {
208                sign = "-";
209                offset = -offset;
210            }
211            hours = offset / 3600000;
212            minutes = (offset % 3600000) / 60000;
213            seconds = (offset % 60000) / 1000;
214            String dstOffset = sign + (hours < 10 ? "0" : "") + hours
215                    + ":" + (minutes < 10 ? "0" : "") + minutes;
216            if (seconds != 0) {
217                dstOffset += ":" + (seconds < 10 ? "0" : "") + seconds;
218            }
219            /*
220             * Instantiate a date so we can display the time zone name.
221             */
222            sdf.setTimeZone(ttz);
223            /*
224             * Format the output.
225             */
226            StringBuffer fmtOffset = new StringBuffer("");
227            FieldPosition pos = new FieldPosition(0);
228
229            try {
230                fmtOffset = sdf.format(today, fmtOffset, pos);
231            } catch (Exception e) {
232                logln("Exception:" + e);
233                continue;
234            }
235            // UnicodeString fmtOffset = tzS.toString();
236            String fmtDstOffset = null;
237            if (fmtOffset.toString().startsWith("GMT")) {
238                //fmtDstOffset = fmtOffset.substring(3);
239                fmtDstOffset = fmtOffset.substring(3, fmtOffset.length());
240            }
241            /*
242             * Show our result.
243             */
244
245            boolean ok = fmtDstOffset == null || fmtDstOffset.equals("") || fmtDstOffset.equals(dstOffset);
246            if (ok) {
247                logln(i + " " + ids[i] + " " + dstOffset + " "
248                      + fmtOffset + (fmtDstOffset != null ? " ok" : " ?"));
249            } else {
250                errln(i + " " + ids[i] + " " + dstOffset + " " + fmtOffset + " *** FAIL ***");
251            }
252
253        }
254    }
255
256    public void TestEquals() {
257        DateFormat fmtA = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.FULL);
258        DateFormat fmtB = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.FULL);
259        if (!fmtA.equals(fmtB))
260            errln("FAIL");
261    }
262
263    /**
264     * Test the parsing of 2-digit years.
265     */
266    public void TestTwoDigitYearDSTParse() {
267
268        SimpleDateFormat fullFmt = new SimpleDateFormat("EEE MMM dd HH:mm:ss.SSS zzz yyyy G");
269        SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM-yy h:mm:ss 'o''clock' a z", Locale.ENGLISH);
270        String s = "03-Apr-04 2:20:47 o'clock AM PST";
271
272        /*
273         * SimpleDateFormat(pattern, locale) Construct a SimpleDateDateFormat using
274         * the given pattern, the locale and using the TimeZone.getDefault();
275         * So it need to add the timezone offset on hour field.
276         * ps. the Method Calendar.getTime() used by SimpleDateFormat.parse() always
277         * return Date value with TimeZone.getDefault() [Richard/GCL]
278         */
279
280        TimeZone defaultTZ = TimeZone.getDefault();
281        TimeZone PST = TimeZone.getTimeZone("PST");
282        int defaultOffset = defaultTZ.getRawOffset();
283        int PSTOffset = PST.getRawOffset();
284        int hour = 2 + (defaultOffset - PSTOffset) / (60*60*1000);
285        // hour is the expected hour of day, in units of seconds
286        hour = ((hour < 0) ? hour + 24 : hour) * 60*60;
287        try {
288            Date d = fmt.parse(s);
289            Calendar cal = Calendar.getInstance();
290            cal.setTime(d);
291            //DSTOffset
292            hour += defaultTZ.inDaylightTime(d) ? 1 : 0;
293
294            logln(s + " P> " + ((DateFormat) fullFmt).format(d));
295            // hr is the actual hour of day, in units of seconds
296            // adjust for DST
297            int hr = cal.get(Calendar.HOUR_OF_DAY) * 60*60 -
298                cal.get(Calendar.DST_OFFSET) / 1000;
299            if (hr != hour)
300                errln("FAIL: Hour (-DST) = " + hr / (60*60.0)+
301                      "; expected " + hour / (60*60.0));
302        } catch (ParseException e) {
303            errln("Parse Error:" + e.getMessage());
304        }
305
306    }
307
308    /**
309     * Verify that returned field position indices are correct.
310     */
311    public void TestFieldPosition() {
312        int i, j, exp;
313        StringBuffer buf = new StringBuffer();
314
315        // Verify data
316        if (VersionInfo.ICU_VERSION.compareTo(VersionInfo.getInstance(3, 7)) >= 0) {
317            DateFormatSymbols rootSyms = new DateFormatSymbols(new Locale("", "", ""));
318            assertEquals("patternChars", PATTERN_CHARS, rootSyms.getLocalPatternChars());
319        }
320
321        assertTrue("DATEFORMAT_FIELD_NAMES", DATEFORMAT_FIELD_NAMES.length == DateFormat.FIELD_COUNT);
322        if(DateFormat.FIELD_COUNT != PATTERN_CHARS.length()){
323            errln("Did not get the correct value for DateFormat.FIELD_COUNT. Expected:  "+ PATTERN_CHARS.length());
324        }
325
326        // Create test formatters
327        final int COUNT = 4;
328        DateFormat[] dateFormats = new DateFormat[COUNT];
329        dateFormats[0] = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, Locale.US);
330        dateFormats[1] = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, Locale.FRANCE);
331        // Make the pattern "G y M d..."
332        buf.append(PATTERN_CHARS);
333        for (j=buf.length()-1; j>=0; --j) buf.insert(j, ' ');
334        dateFormats[2] = new SimpleDateFormat(buf.toString(), Locale.US);
335        // Make the pattern "GGGG yyyy MMMM dddd..."
336        for (j=buf.length()-1; j>=0; j-=2) {
337            for (i=0; i<3; ++i) {
338                buf.insert(j, buf.charAt(j));
339            }
340        }
341        dateFormats[3] = new SimpleDateFormat(buf.toString(), Locale.US);
342
343        Date aug13 = new Date((long) 871508052513.0);
344
345        // Expected output field values for above DateFormats on aug13
346        // Fields are given in order of DateFormat field number
347        final String EXPECTED[] = {
348             "", "1997", "August", "13", "", "", "34", "12", "", "Wednesday",
349             "", "", "", "", "PM", "2", "", "Pacific Daylight Time", "", "",
350             "", "", "", "", "", "", "", "", "", "",
351             "", "", "", "", "", ":",
352
353             "", "1997", "ao\u00FBt", "13", "", "14", "34", "12", "", "mercredi",
354             "", "", "", "", "", "", "", "heure d\u2019\u00E9t\u00E9 du Pacifique", "", "",
355             "", "", "", "", "", "", "", "", "", "",
356             "", "", "", "", "", ":",
357
358            "AD", "1997", "8", "13", "14", "14", "34", "12", "5", "Wed",
359            "225", "2", "33", "3", "PM", "2", "2", "PDT", "1997", "4",
360            "1997", "2450674", "52452513", "-0700", "PT", "4", "8", "3", "3", "uslax",
361            "1997", "GMT-7", "-07", "-07", "1997", ":",
362
363            "Anno Domini", "1997", "August", "0013", "0014", "0014", "0034", "0012", "5130", "Wednesday",
364            "0225", "0002", "0033", "0003", "PM", "0002", "0002", "Pacific Daylight Time", "1997", "Wednesday",
365            "1997", "2450674", "52452513", "GMT-07:00", "Pacific Time", "Wednesday", "August", "3rd quarter", "3rd quarter", "Los Angeles Time",
366            "1997", "GMT-07:00", "-0700", "-0700", "1997", ":",
367        };
368
369        assertTrue("data size", EXPECTED.length == COUNT * DateFormat.FIELD_COUNT);
370
371        final DateFormat.Field[] DTFMT_FIELDS = {
372            DateFormat.Field.AM_PM,
373            DateFormat.Field.DAY_OF_MONTH,
374            DateFormat.Field.DAY_OF_WEEK,
375            DateFormat.Field.DAY_OF_WEEK_IN_MONTH,
376            DateFormat.Field.DAY_OF_YEAR,
377
378            DateFormat.Field.DOW_LOCAL,
379            DateFormat.Field.ERA,
380            DateFormat.Field.EXTENDED_YEAR,
381            DateFormat.Field.HOUR_OF_DAY0,
382            DateFormat.Field.HOUR_OF_DAY1,
383
384            DateFormat.Field.HOUR0,
385            DateFormat.Field.HOUR1,
386            DateFormat.Field.JULIAN_DAY,
387            DateFormat.Field.MILLISECOND,
388            DateFormat.Field.MILLISECONDS_IN_DAY,
389
390            DateFormat.Field.MINUTE,
391            DateFormat.Field.MONTH,
392            DateFormat.Field.QUARTER,
393            DateFormat.Field.SECOND,
394            DateFormat.Field.TIME_ZONE,
395
396            DateFormat.Field.WEEK_OF_MONTH,
397            DateFormat.Field.WEEK_OF_YEAR,
398            DateFormat.Field.YEAR,
399            DateFormat.Field.YEAR_WOY,
400        };
401
402        final String[][] EXPECTED_BY_FIELD = {
403            {"PM", "13", "Wednesday", "", "",
404             "", "", "", "", "",
405             "", "2", "", "", "",
406             "34", "August", "", "12", "Pacific Daylight Time",
407             "", "", "1997", ""},
408
409            {"", "13", "mercredi", "", "",
410             "", "", "", "14", "",
411             "", "", "", "", "",
412             "34", "ao\u00FBt", "", "12", "heure d\u2019\u00E9t\u00E9 du Pacifique",
413             "", "", "1997", ""},
414
415            {"PM", "13", "Wed", "2", "225",
416             "4", "AD", "1997", "14", "14",
417             "2", "2", "2450674", "5", "52452513",
418             "34", "8", "3", "12", "PDT",
419             "3", "33", "1997", "1997"},
420
421            {"PM", "0013", "Wednesday", "0002", "0225",
422             "Wednesday", "Anno Domini", "1997", "0014", "0014",
423             "0002", "0002", "2450674", "5130", "52452513",
424             "0034", "August", "3rd quarter", "0012", "Pacific Daylight Time",
425             "0003", "0033", "1997", "1997"},
426        };
427
428        TimeZone PT = TimeZone.getTimeZone("America/Los_Angeles");
429        for (j = 0, exp = 0; j < COUNT; ++j) {
430            //  String str;
431            DateFormat df = dateFormats[j];
432            df.setTimeZone(PT);
433            logln(" Pattern = " + ((SimpleDateFormat) df).toPattern());
434            try {
435                logln("  Result = " + df.format(aug13));
436            } catch (Exception e) {
437                errln("FAIL: " + e);
438                e.printStackTrace();
439                continue;
440            }
441
442            FieldPosition pos;
443            String field;
444
445            for (i = 0; i < DateFormat.FIELD_COUNT; ++i, ++exp) {
446                pos = new FieldPosition(i);
447                buf.setLength(0);
448                df.format(aug13, buf, pos);
449                field = buf.substring(pos.getBeginIndex(), pos.getEndIndex());
450                assertEquals("pattern#" + j + " field #" + i + " " + DATEFORMAT_FIELD_NAMES[i],
451                             EXPECTED[exp], field);
452            }
453
454            // FieldPostion initialized by DateFormat.Field trac#6089
455            for(i = 0; i < DTFMT_FIELDS.length; i++) {
456                // The format method only set position for the first occurrence of
457                // the specified field.
458                pos = new FieldPosition(DTFMT_FIELDS[i]);
459                buf.setLength(0);
460                df.format(aug13, buf, pos);
461                field = buf.substring(pos.getBeginIndex(), pos.getEndIndex());
462                assertEquals("pattern#" + j + " " + DTFMT_FIELDS[i].toString(), EXPECTED_BY_FIELD[j][i], field);
463            }
464        }
465    }
466    /**
467     * This MUST be kept in sync with DateFormatSymbols.patternChars.
468     */
469    static final String PATTERN_CHARS = "GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxr:";
470
471    /**
472     * A list of the DateFormat.Field.
473     * This MUST be kept in sync with PATTERN_CHARS above.
474     */
475    static final DateFormat.Field[] DATEFORMAT_FIELDS = {
476        DateFormat.Field.ERA,           // G
477        DateFormat.Field.YEAR,          // y
478        DateFormat.Field.MONTH,         // M
479        DateFormat.Field.DAY_OF_MONTH,  // d
480        DateFormat.Field.HOUR_OF_DAY1,  // k
481        DateFormat.Field.HOUR_OF_DAY0,  // H
482        DateFormat.Field.MINUTE,        // m
483        DateFormat.Field.SECOND,        // s
484        DateFormat.Field.MILLISECOND,   // S
485        DateFormat.Field.DAY_OF_WEEK,   // E
486        DateFormat.Field.DAY_OF_YEAR,   // D
487        DateFormat.Field.DAY_OF_WEEK_IN_MONTH,  // F
488        DateFormat.Field.WEEK_OF_YEAR,  // w
489        DateFormat.Field.WEEK_OF_MONTH, // W
490        DateFormat.Field.AM_PM,         // a
491        DateFormat.Field.HOUR1,         // h
492        DateFormat.Field.HOUR0,         // K
493        DateFormat.Field.TIME_ZONE,     // z
494        DateFormat.Field.YEAR_WOY,      // Y
495        DateFormat.Field.DOW_LOCAL,     // e
496        DateFormat.Field.EXTENDED_YEAR, // u
497        DateFormat.Field.JULIAN_DAY,    // g
498        DateFormat.Field.MILLISECONDS_IN_DAY,   // A
499        DateFormat.Field.TIME_ZONE,     // Z
500        DateFormat.Field.TIME_ZONE,     // v
501        DateFormat.Field.DAY_OF_WEEK,   // c
502        DateFormat.Field.MONTH,         // L
503        DateFormat.Field.QUARTER,       // Q
504        DateFormat.Field.QUARTER,       // q
505        DateFormat.Field.TIME_ZONE,     // V
506        DateFormat.Field.YEAR,          // U
507        DateFormat.Field.TIME_ZONE,     // O
508        DateFormat.Field.TIME_ZONE,     // X
509        DateFormat.Field.TIME_ZONE,     // x
510        DateFormat.Field.RELATED_YEAR,  // r
511        DateFormat.Field.TIME_SEPARATOR,// :
512    };
513
514    /**
515     * A list of the names of all the fields in DateFormat.
516     * This MUST be kept in sync with DateFormat.
517     */
518    static final String DATEFORMAT_FIELD_NAMES[] = {
519        "ERA_FIELD",
520        "YEAR_FIELD",
521        "MONTH_FIELD",
522        "DATE_FIELD",
523        "HOUR_OF_DAY1_FIELD",
524        "HOUR_OF_DAY0_FIELD",
525        "MINUTE_FIELD",
526        "SECOND_FIELD",
527        "MILLISECOND_FIELD",
528        "DAY_OF_WEEK_FIELD",
529        "DAY_OF_YEAR_FIELD",
530        "DAY_OF_WEEK_IN_MONTH_FIELD",
531        "WEEK_OF_YEAR_FIELD",
532        "WEEK_OF_MONTH_FIELD",
533        "AM_PM_FIELD",
534        "HOUR1_FIELD",
535        "HOUR0_FIELD",
536        "TIMEZONE_FIELD",
537        "YEAR_WOY_FIELD",
538        "DOW_LOCAL_FIELD",
539        "EXTENDED_YEAR_FIELD",
540        "JULIAN_DAY_FIELD",
541        "MILLISECONDS_IN_DAY_FIELD",
542        "TIMEZONE_RFC_FIELD",
543        "GENERIC_TIMEZONE_FIELD",
544        "STAND_ALONE_DAY_FIELD",
545        "STAND_ALONE_MONTH_FIELD",
546        "QUARTER_FIELD",
547        "STAND_ALONE_QUARTER_FIELD",
548        "TIMEZONE_SPECIAL_FIELD",
549        "YEAR_NAME_FIELD",
550        "TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD",
551        "TIMEZONE_ISO_FIELD",
552        "TIMEZONE_ISO_LOCAL_FIELD",
553        "RELATED_YEAR",
554        "TIME_SEPARATOR",
555    };
556
557    /**
558     * General parse/format tests.  Add test cases as needed.
559     */
560    public void TestGeneral() {
561
562        String DATA[] = {
563            "yyyy MM dd HH:mm:ss.SSS",
564
565            // Milliseconds are left-justified, since they format as fractions of a second
566            // Both format and parse should round HALF_UP
567            "y/M/d H:mm:ss.S", "fp", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.5", "2004 03 10 16:36:31.500",
568            "y/M/d H:mm:ss.SS", "fp", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.56", "2004 03 10 16:36:31.560",
569            "y/M/d H:mm:ss.SSS", "F", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.567",
570            "y/M/d H:mm:ss.SSSS", "pf", "2004/3/10 16:36:31.5679", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.5670",
571        };
572        expect(DATA, new Locale("en", "", ""));
573    }
574
575    public void TestGenericTime() {
576
577
578        // any zone pattern should parse any zone
579        Locale en = new Locale("en", "", "");
580        String ZDATA[] = {
581            "yyyy MM dd HH:mm zzz",
582            // round trip
583            "y/M/d H:mm zzzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Standard Time",
584            "y/M/d H:mm zzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
585            "y/M/d H:mm vvvv", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
586            "y/M/d H:mm v", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PT",
587            // non-generic timezone string influences dst offset even if wrong for date/time
588            "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PDT", "2004 01 01 01:00 PDT", "2004/1/1 0:00 PST",
589            "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 PDT", "2004 01 01 01:00 PDT", "2004/1/1 0:00 Pacific Time",
590            "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PST", "2004 07 01 02:00 PDT", "2004/7/1 2:00 PDT",
591            "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 PST", "2004 07 01 02:00 PDT", "2004/7/1 2:00 Pacific Time",
592            // generic timezone generates dst offset appropriate for local time
593            "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
594            "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
595            "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PDT",
596            "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 Pacific Time",
597            // daylight savings time transition edge cases.
598            // time to parse does not really exist, PT interpreted as earlier time
599            "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PT", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PDT",
600            "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PST", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PDT",
601            "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PDT", "2005 04 03 01:30 PST", "2005/4/3 1:30 PST",
602            "y/M/d H:mm v", "pf", "2005/4/3 2:30 PT", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PT",
603            "y/M/d H:mm v", "pf", "2005/4/3 2:30 PST", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PT",
604            "y/M/d H:mm v", "pf", "2005/4/3 2:30 PDT", "2005 04 03 01:30 PST", "2005/4/3 1:30 PT",
605            "y/M/d H:mm", "pf", "2005/4/3 2:30", "2005 04 03 03:30 PDT", "2005/4/3 3:30",
606            // time to parse is ambiguous, PT interpreted as later time
607            "y/M/d H:mm zzz", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30 PST",
608            "y/M/d H:mm v", "pf", "2005/10/30 1:30 PT", "2005 10 30  01:30 PST", "2005/10/30 1:30 PT",
609            "y/M/d H:mm", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30",
610
611            "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PT", "2004 10 31 01:30 PST", "2004/10/31 1:30 PST",
612             "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PST", "2004 10 31 01:30 PST", "2004/10/31 1:30 PST",
613             "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PDT", "2004 10 31 01:30 PDT", "2004/10/31 1:30 PDT",
614             "y/M/d H:mm v", "pf", "2004/10/31 1:30 PT", "2004 10 31 01:30 PST", "2004/10/31 1:30 PT",
615             "y/M/d H:mm v", "pf", "2004/10/31 1:30 PST", "2004 10 31 01:30 PST", "2004/10/31 1:30 PT",
616             "y/M/d H:mm v", "pf", "2004/10/31 1:30 PDT", "2004 10 31 01:30 PDT", "2004/10/31 1:30 PT",
617             "y/M/d H:mm", "pf", "2004/10/31 1:30", "2004 10 31 01:30 PST", "2004/10/31 1:30",
618            // Below is actually an invalid test case.  See the note in #5910.  Disable the case for now.
619            // TODO: Revisit after 3.8
620            //"y/M/d H:mm vvvv", "pf", "2004/10/31 1:30 Argentina Time", "2004 10 30 21:30 PDT", "2004/10/31 1:30 Argentina Time",
621        };
622        expect(ZDATA, en, true);
623
624        logln("cross format/parse tests");
625        final String basepat = "yy/MM/dd H:mm ";
626        final SimpleDateFormat[] formats = {
627            new SimpleDateFormat(basepat + "v", en),
628            new SimpleDateFormat(basepat + "vvvv", en),
629            new SimpleDateFormat(basepat + "zzz", en),
630            new SimpleDateFormat(basepat + "zzzz", en)
631        };
632
633        final SimpleDateFormat univ = new SimpleDateFormat("yyyy MM dd HH:mm zzz", en);
634
635     // To allow cross pattern parsing, we need to set ParseOption.ALL_STYLES
636        TimeZoneFormat tzfmt = univ.getTimeZoneFormat().cloneAsThawed();
637        tzfmt.setDefaultParseOptions(EnumSet.of(ParseOption.ALL_STYLES));
638        tzfmt.freeze();
639        univ.setTimeZoneFormat(tzfmt);
640        for (SimpleDateFormat sdf : formats) {
641            sdf.setTimeZoneFormat(tzfmt);
642        }
643
644        final String[] times = { "2004 01 02 03:04 PST", "2004 07 08 09:10 PDT" };
645        for (int i = 0; i < times.length; ++i) {
646            try {
647                Date d = univ.parse(times[i]);
648                logln("time: " + d);
649                for (int j = 0; j < formats.length; ++j) {
650                    String test = formats[j].format(d);
651                    logln("test: '" + test + "'");
652                    for (int k = 0; k < formats.length; ++k) {
653                        try {
654                            Date t = formats[k].parse(test);
655                            if (!d.equals(t)) {
656                                errln("format " + k +
657                                      " incorrectly parsed output of format " + j +
658                                      " (" + test + "), returned " +
659                                      t + " instead of " + d);
660                            } else {
661                                logln("format " + k + " parsed ok");
662                            }
663                        }
664                        catch (ParseException e) {
665                            errln("format " + k +
666                                  " could not parse output of format " + j +
667                                  " (" + test + ")");
668                        }
669                    }
670                }
671            }
672            catch (ParseException e) {
673                errln("univ could not parse: " + times[i]);
674            }
675        }
676
677    }
678
679    public void TestGenericTimeZoneOrder() {
680        // generic times should parse the same no matter what the placement of the time zone string
681        // should work for standard and daylight times
682
683        String XDATA[] = {
684            "yyyy MM dd HH:mm zzz",
685            // standard time, explicit daylight/standard
686            "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
687            "y/M/d zzz H:mm", "pf", "2004/1/1 PT 1:00", "2004 01 01 01:00 PST", "2004/1/1 PST 1:00",
688            "zzz y/M/d H:mm", "pf", "PT 2004/1/1 1:00", "2004 01 01 01:00 PST", "PST 2004/1/1 1:00",
689
690            // standard time, generic
691            "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
692            "y/M/d vvvv H:mm", "pf", "2004/1/1 PT 1:00", "2004 01 01 01:00 PST", "2004/1/1 Pacific Time 1:00",
693            "vvvv y/M/d H:mm", "pf", "PT 2004/1/1 1:00", "2004 01 01 01:00 PST", "Pacific Time 2004/1/1 1:00",
694
695            // daylight time, explicit daylight/standard
696            "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PDT",
697            "y/M/d zzz H:mm", "pf", "2004/7/1 PT 1:00", "2004 07 01 01:00 PDT", "2004/7/1 PDT 1:00",
698            "zzz y/M/d H:mm", "pf", "PT 2004/7/1 1:00", "2004 07 01 01:00 PDT", "PDT 2004/7/1 1:00",
699
700            // daylight time, generic
701            "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 Pacific Time",
702            "y/M/d vvvv H:mm", "pf", "2004/7/1 PT 1:00", "2004 07 01 01:00 PDT", "2004/7/1 Pacific Time 1:00",
703            "vvvv y/M/d H:mm", "pf", "PT 2004/7/1 1:00", "2004 07 01 01:00 PDT", "Pacific Time 2004/7/1 1:00",
704        };
705        Locale en = new Locale("en", "", "");
706        expect(XDATA, en, true);
707    }
708
709    public void TestTimeZoneDisplayName() {
710        Calendar cal = new GregorianCalendar();
711        SimpleDateFormat testfmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
712        testfmt.setTimeZone(TimeZone.getTimeZone("Etc/GMT"));
713
714        for (int i = 0; i < fallbackTests.length; ++i) {
715            String[] info = fallbackTests[i];
716            logln(info[0] + ";" + info[1] + ";" + info[2] + ";" + info[3]);
717
718            long time = 0;
719            try {
720                Date testd = testfmt.parse(info[2]);
721                time = testd.getTime();
722            } catch (ParseException pe) {
723                errln("Failed to parse test date data");
724                continue;
725            }
726            ULocale l = new ULocale(info[0]);
727            TimeZone tz = TimeZone.getTimeZone(info[1]);
728            SimpleDateFormat fmt = new SimpleDateFormat(info[3], l);
729            cal.setTimeInMillis(time);
730            cal.setTimeZone(tz);
731            String result = fmt.format(cal);
732            if (!result.equals(info[4])) {
733                errln(info[0] + ";" + info[1] + ";" + info[2] + ";" + info[3] + " expected: '" +
734                      info[4] + "' but got: '" + result + "'");
735            }
736        }
737    }
738
739    private static final String GMT_BG = "\u0413\u0440\u0438\u043D\u0443\u0438\u0447";
740    private static final String GMT_ZH = "GMT";
741    //private static final String GMT_ZH = "\u683C\u6797\u5C3C\u6CBB\u6807\u51C6\u65F6\u95F4";
742    //private static final String GMT_BG = "GMT";
743
744    private static final String[][] fallbackTests  = {
745        { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
746        { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
747        { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZZ", "-08:00", "-8:00" },
748        { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "PST", "America/Los_Angeles" },
749        { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "Pacific Standard Time", "America/Los_Angeles" },
750        { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
751        { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
752        { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "PDT", "America/Los_Angeles" },
753        { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "Pacific Daylight Time", "America/Los_Angeles" },
754        { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "PT", "America/Los_Angeles" },
755        { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Pacific Time", "America/Los_Angeles" },
756        { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "VVVV", "Los Angeles Time", "America/Los_Angeles" },
757        { "en_GB", "America/Los_Angeles", "2004-01-15T12:00:00Z", "z", "GMT-8", "America/Los_Angeles" },
758        { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "Z", "-0700", "-7:00" },
759        { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
760        { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "z", "MST", "America/Phoenix" },
761        { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "zzzz", "Mountain Standard Time", "America/Phoenix" },
762        { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
763        { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
764        { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "z", "MST", "America/Phoenix" },
765        { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "zzzz", "Mountain Standard Time", "America/Phoenix" },
766        { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "v", "MST", "America/Phoenix" },
767        { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "vvvv", "Mountain Standard Time", "America/Phoenix" },
768        { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "VVVV", "Phoenix Time", "America/Phoenix" },
769
770        { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
771        { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
772        { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
773        { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
774        { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
775        { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
776        { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
777        { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
778        { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Time", "America/Buenos_Aires" },
779        { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentina Standard Time", "America/Buenos_Aires" },
780        { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "VVVV", "Buenos Aires Time", "America/Buenos_Aires" },
781
782        { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
783        { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
784        { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
785        { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
786        { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
787        { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
788        { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
789        { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
790        { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Time", "America/Buenos_Aires" },
791        { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentina Standard Time", "America/Buenos_Aires" },
792        { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "VVVV", "Buenos Aires Time", "America/Buenos_Aires" },
793
794        { "en", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
795        { "en", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
796        { "en", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
797        { "en", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "Cuba Standard Time", "-5:00" },
798        { "en", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
799        { "en", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
800        { "en", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
801        { "en", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "Cuba Daylight Time", "-4:00" },
802        { "en", "America/Havana", "2004-07-15T00:00:00Z", "v", "Cuba Time", "America/Havana" },
803        { "en", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "Cuba Time", "America/Havana" },
804        { "en", "America/Havana", "2004-07-15T00:00:00Z", "VVVV", "Cuba Time", "America/Havana" },
805
806        { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
807        { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
808        { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
809        { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "Australian Eastern Daylight Time", "+11:00" },
810        { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
811        { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
812        { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
813        { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "Australian Eastern Standard Time", "+10:00" },
814        { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney Time", "Australia/Sydney" },
815        { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Eastern Australia Time", "Australia/Sydney" },
816        { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "VVVV", "Sydney Time", "Australia/Sydney" },
817
818        { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
819        { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
820        { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
821        { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "Australian Eastern Daylight Time", "+11:00" },
822        { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
823        { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
824        { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
825        { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "Australian Eastern Standard Time", "+10:00" },
826        { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney Time", "Australia/Sydney" },
827        { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Eastern Australia Time", "Australia/Sydney" },
828        { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "VVVV", "Sydney Time", "Australia/Sydney" },
829
830        { "en", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
831        { "en", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
832        { "en", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
833        { "en", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "Greenwich Mean Time", "+0:00" },
834        { "en", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
835        { "en", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
836        { "en", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "Europe/London" },
837        { "en", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "British Summer Time", "Europe/London" },
838    // icu en.txt has exemplar city for this time zone
839        { "en", "Europe/London", "2004-07-15T00:00:00Z", "v", "United Kingdom Time", "Europe/London" },
840        { "en", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "United Kingdom Time", "Europe/London" },
841        { "en", "Europe/London", "2004-07-15T00:00:00Z", "VVVV", "United Kingdom Time", "Europe/London" },
842
843        { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
844        { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
845        { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
846        { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
847        { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
848        { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
849        { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
850        { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
851        { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
852        { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
853
854        // JB#5150
855        { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
856        { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
857        { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
858        { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "India Standard Time", "+5:30" },
859        { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
860        { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
861        { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
862        { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "India Standard Time", "+5:30" },
863        { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "India Time", "Asia/Calcutta" },
864        { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "India Standard Time", "Asia/Calcutta" },
865
866        // Proper CLDR primary zone support #9733
867        { "en", "America/Santiago", "2013-01-01T00:00:00Z", "VVVV", "Chile Time", "America/Santiago" },
868        { "en", "Pacific/Easter", "2013-01-01T00:00:00Z", "VVVV", "Easter Time", "Pacific/Easter" },
869
870        // ==========
871
872        { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
873        { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
874        { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "-8:00" },
875        { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "Nordamerikanische Westk\u00fcsten-Normalzeit", "-8:00" },
876        { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
877        { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
878        { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "-7:00" },
879        { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "Nordamerikanische Westk\u00fcsten-Sommerzeit", "-7:00" },
880        { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "Los Angeles Zeit", "America/Los_Angeles" },
881        { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Nordamerikanische Westk\u00fcstenzeit", "America/Los_Angeles" },
882
883        { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
884        { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
885        { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
886        { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
887        { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
888        { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
889        { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
890        { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
891        { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Zeit", "America/Buenos_Aires" },
892        { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentinische Normalzeit", "America/Buenos_Aires" },
893
894        { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
895        { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
896        { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
897        { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
898        { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
899        { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
900        { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
901        { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
902        { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Zeit", "America/Buenos_Aires" },
903        { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentinische Normalzeit", "America/Buenos_Aires" },
904
905        { "de", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
906        { "de", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
907        { "de", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
908        { "de", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "Kubanische Normalzeit", "-5:00" },
909        { "de", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
910        { "de", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
911        { "de", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
912        { "de", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "Kubanische Sommerzeit", "-4:00" },
913        { "de", "America/Havana", "2004-07-15T00:00:00Z", "v", "Kuba Zeit", "America/Havana" },
914        { "de", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "Kubanische Zeit", "America/Havana" },
915        // added to test proper fallback of country name
916        { "de_CH", "America/Havana", "2004-07-15T00:00:00Z", "v", "Kuba Zeit", "America/Havana" },
917        { "de_CH", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "Kubanische Zeit", "America/Havana" },
918
919        { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
920        { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
921        { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
922        { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "Ostaustralische Sommerzeit", "+11:00" },
923        { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
924        { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
925        { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
926        { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "Ostaustralische Normalzeit", "+10:00" },
927        { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney Zeit", "Australia/Sydney" },
928        { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Ostaustralische Zeit", "Australia/Sydney" },
929
930        { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
931        { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
932        { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
933        { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "Ostaustralische Sommerzeit", "+11:00" },
934        { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
935        { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
936        { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
937        { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "Ostaustralische Normalzeit", "+10:00" },
938        { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney Zeit", "Australia/Sydney" },
939        { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Ostaustralische Zeit", "Australia/Sydney" },
940
941        { "de", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
942        { "de", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
943        { "de", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
944        { "de", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "Mittlere Greenwich-Zeit", "+0:00" },
945        { "de", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
946        { "de", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
947        { "de", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
948        { "de", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "Britische Sommerzeit", "+1:00" },
949        { "de", "Europe/London", "2004-07-15T00:00:00Z", "v", "Vereinigtes K\u00f6nigreich Zeit", "Europe/London" },
950        { "de", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "Vereinigtes K\u00f6nigreich Zeit", "Europe/London" },
951
952        { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
953        { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
954        { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
955        { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
956        { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
957        { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
958        { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
959        { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
960        { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
961        { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
962
963        // JB#5150
964        { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
965        { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
966        { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
967        { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "Indische Zeit", "+5:30" },
968        { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
969        { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
970        { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
971        { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "Indische Zeit", "+5:30" },
972        { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "Indien Zeit", "Asia/Calcutta" },
973        { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "Indische Zeit", "Asia/Calcutta" },
974
975        // ==========
976
977        { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
978        { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", GMT_ZH+"-08:00", "-8:00" },
979        { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", GMT_ZH+"-8", "America/Los_Angeles" },
980        { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\u5317\u7f8e\u592a\u5e73\u6d0b\u6807\u51c6\u65f6\u95f4", "America/Los_Angeles" },
981        { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
982        { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", GMT_ZH+"-07:00", "-7:00" },
983        { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", GMT_ZH+"-7", "America/Los_Angeles" },
984        { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\u5317\u7f8e\u592a\u5e73\u6d0b\u590f\u4ee4\u65f6\u95f4", "America/Los_Angeles" },
985    // icu zh.txt has exemplar city for this time zone
986        { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\u6D1B\u6749\u77F6\u65F6\u95F4", "America/Los_Angeles" },
987        { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\u5317\u7f8e\u592a\u5e73\u6d0b\u65f6\u95f4", "America/Los_Angeles" },
988
989        { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
990        { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", GMT_ZH+"-03:00", "-3:00" },
991        { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", GMT_ZH+"-3", "-3:00" },
992        { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\u963f\u6839\u5ef7\u6807\u51c6\u65f6\u95f4", "-3:00" },
993        { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
994        { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", GMT_ZH+"-03:00", "-3:00" },
995        { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", GMT_ZH+"-3", "-3:00" },
996        { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\u963f\u6839\u5ef7\u6807\u51c6\u65f6\u95f4", "-3:00" },
997    // icu zh.txt does not have info for this time zone
998        { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\u5E03\u5B9C\u8BFA\u65AF\u827E\u5229\u65AF\u65F6\u95F4", "America/Buenos_Aires" },
999        { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\u963f\u6839\u5ef7\u6807\u51c6\u65f6\u95f4", "America/Buenos_Aires" },
1000
1001        { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
1002        { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", GMT_ZH+"-03:00", "-3:00" },
1003        { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", GMT_ZH+"-3", "-3:00" },
1004        { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\u963f\u6839\u5ef7\u6807\u51c6\u65f6\u95f4", "-3:00" },
1005        { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
1006        { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", GMT_ZH+"-03:00", "-3:00" },
1007        { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", GMT_ZH+"-3", "-3:00" },
1008        { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\u963f\u6839\u5ef7\u6807\u51c6\u65f6\u95f4", "-3:00" },
1009        { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\u5E03\u5B9C\u8BFA\u65AF\u827E\u5229\u65AF\u65F6\u95F4", "America/Buenos_Aires" },
1010        { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\u963f\u6839\u5ef7\u6807\u51c6\u65f6\u95f4", "America/Buenos_Aires" },
1011
1012        { "zh", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
1013        { "zh", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", GMT_ZH+"-05:00", "-5:00" },
1014        { "zh", "America/Havana", "2004-01-15T00:00:00Z", "z", GMT_ZH+"-5", "-5:00" },
1015        { "zh", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\u53e4\u5df4\u6807\u51c6\u65f6\u95f4", "-5:00" },
1016        { "zh", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
1017        { "zh", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", GMT_ZH+"-04:00", "-4:00" },
1018        { "zh", "America/Havana", "2004-07-15T00:00:00Z", "z", GMT_ZH+"-4", "-4:00" },
1019        { "zh", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\u53e4\u5df4\u590f\u4ee4\u65f6\u95f4", "-4:00" },
1020        { "zh", "America/Havana", "2004-07-15T00:00:00Z", "v", "\u53e4\u5df4\u65f6\u95f4", "America/Havana" },
1021        { "zh", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\u53e4\u5df4\u65f6\u95f4", "America/Havana" },
1022
1023        { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
1024        { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", GMT_ZH+"+11:00", "+11:00" },
1025        { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "z", GMT_ZH+"+11", "+11:00" },
1026        { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\u6fb3\u5927\u5229\u4e9a\u4e1c\u90e8\u590f\u4ee4\u65f6\u95f4", "+11:00" },
1027        { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
1028        { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", GMT_ZH+"+10:00", "+10:00" },
1029        { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "z", GMT_ZH+"+10", "+10:00" },
1030        { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\u6fb3\u5927\u5229\u4e9a\u4e1c\u90e8\u6807\u51c6\u65f6\u95f4", "+10:00" },
1031        { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\u6089\u5C3C\u65F6\u95F4", "Australia/Sydney" },
1032        { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\u6fb3\u5927\u5229\u4e9a\u4e1c\u90e8\u65f6\u95f4", "Australia/Sydney" },
1033
1034        { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
1035        { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", GMT_ZH+"+11:00", "+11:00" },
1036        { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", GMT_ZH+"+11", "+11:00" },
1037        { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\u6fb3\u5927\u5229\u4e9a\u4e1c\u90e8\u590f\u4ee4\u65f6\u95f4", "+11:00" },
1038        { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
1039        { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", GMT_ZH+"+10:00", "+10:00" },
1040        { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", GMT_ZH+"+10", "+10:00" },
1041        { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\u6fb3\u5927\u5229\u4e9a\u4e1c\u90e8\u6807\u51c6\u65f6\u95f4",  "+10:00" },
1042        { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\u6089\u5C3C\u65F6\u95F4", "Australia/Sydney" },
1043        { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\u6fb3\u5927\u5229\u4e9a\u4e1c\u90e8\u65f6\u95f4", "Australia/Sydney" },
1044
1045        { "zh", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
1046        { "zh", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", GMT_ZH, "+0:00" },
1047        { "zh", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
1048        { "zh", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\u683C\u6797\u5C3C\u6CBB\u6807\u51C6\u65F6\u95F4", "+0:00" },
1049        { "zh", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
1050        { "zh", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", GMT_ZH+"+01:00", "+1:00" },
1051        { "zh", "Europe/London", "2004-07-15T00:00:00Z", "z", GMT_ZH+"+1", "+1:00" },
1052        { "zh", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\u82f1\u56fd\u590f\u4ee4\u65f6\u95f4", "+1:00" },
1053        { "zh", "Europe/London", "2004-07-15T00:00:00Z", "v", "\u82f1\u56fd\u65f6\u95f4", "Europe/London" },
1054        { "zh", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\u82f1\u56fd\u65f6\u95f4", "Europe/London" },
1055        { "zh", "Europe/London", "2004-07-15T00:00:00Z", "VVVV", "\u82f1\u56fd\u65f6\u95f4", "Europe/London" },
1056
1057        { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
1058        { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", GMT_ZH+"-03:00", "-3:00" },
1059        { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", GMT_ZH+"-3", "-3:00" },
1060        { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", GMT_ZH+"-03:00", "-3:00" },
1061        { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
1062        { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", GMT_ZH+"-03:00", "-3:00" },
1063        { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", GMT_ZH+"-3", "-3:00" },
1064        { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", GMT_ZH+"-03:00", "-3:00" },
1065        { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", GMT_ZH+"-3", "-3:00" },
1066        { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", GMT_ZH+"-03:00", "-3:00" },
1067
1068        // JB#5150
1069        { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
1070        { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", GMT_ZH+"+05:30", "+5:30" },
1071        { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", GMT_ZH+"+5:30", "+5:30" },
1072        { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\u5370\u5ea6\u65f6\u95f4", "+5:30" },
1073        { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
1074        { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", GMT_ZH+"+05:30", "+5:30" },
1075        { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", GMT_ZH+"+5:30", "+05:30" },
1076        { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\u5370\u5ea6\u65f6\u95f4", "+5:30" },
1077        { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\u5370\u5ea6\u65f6\u95f4", "Asia/Calcutta" },
1078        { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\u5370\u5EA6\u65f6\u95f4", "Asia/Calcutta" },
1079
1080        // ==========
1081
1082        { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
1083        { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
1084        { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "-8:00" },
1085        { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\u0909\u0924\u094d\u0924\u0930\u0940 \u0905\u092e\u0947\u0930\u093f\u0915\u0940 \u092a\u094d\u0930\u0936\u093e\u0902\u0924 \u092e\u093e\u0928\u0915 \u0938\u092e\u092f", "-8:00" },
1086        { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
1087        { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
1088        { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "-7:00" },
1089        { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\u0909\u0924\u094d\u0924\u0930\u0940 \u0905\u092e\u0947\u0930\u093f\u0915\u0940 \u092a\u094d\u0930\u0936\u093e\u0902\u0924 \u0921\u0947\u0932\u093e\u0907\u091f \u0938\u092e\u092f", "-7:00" },
1090        { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\u0932\u0949\u0938 \u090f\u0902\u091c\u093f\u0932\u094d\u0938 \u0938\u092e\u092f", "America/Los_Angeles" },
1091        { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\u0909\u0924\u094d\u0924\u0930\u0940 \u0905\u092e\u0947\u0930\u093f\u0915\u0940 \u092a\u094d\u0930\u0936\u093e\u0902\u0924 \u0938\u092e\u092f", "America/Los_Angeles" },
1092
1093        { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
1094        { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
1095        { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
1096        { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\u0905\u0930\u094D\u091C\u0947\u0902\u091F\u0940\u0928\u093E \u092E\u093E\u0928\u0915 \u0938\u092E\u092F", "-3:00" },
1097        { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
1098        { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
1099        { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
1100        { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\u0905\u0930\u094D\u091C\u0947\u0902\u091F\u0940\u0928\u093E \u092E\u093E\u0928\u0915 \u0938\u092E\u092F", "-3:00" },
1101        { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\u092C\u094D\u092F\u0942\u0928\u0938 \u0906\u092F\u0930\u0938 \u0938\u092E\u092F", "America/Buenos_Aires" },
1102        { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\u0905\u0930\u094D\u091C\u0947\u0902\u091F\u0940\u0928\u093E \u092E\u093E\u0928\u0915 \u0938\u092E\u092F", "America/Buenos_Aires" },
1103
1104        { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
1105        { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
1106        { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
1107        { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\u0905\u0930\u094D\u091C\u0947\u0902\u091F\u0940\u0928\u093E \u092E\u093E\u0928\u0915 \u0938\u092E\u092F", "-3:00" },
1108        { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
1109        { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
1110        { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
1111        { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\u0905\u0930\u094D\u091C\u0947\u0902\u091F\u0940\u0928\u093E \u092E\u093E\u0928\u0915 \u0938\u092E\u092F", "-3:00" },
1112        { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\u092C\u094D\u092F\u0942\u0928\u0938 \u0906\u092F\u0930\u0938 \u0938\u092E\u092F", "America/Buenos_Aires" },
1113        { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\u0905\u0930\u094D\u091C\u0947\u0902\u091F\u0940\u0928\u093E \u092E\u093E\u0928\u0915 \u0938\u092E\u092F", "America/Buenos_Aires" },
1114
1115        { "hi", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
1116        { "hi", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
1117        { "hi", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
1118        { "hi", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\u0915\u094d\u092f\u0942\u092c\u093e \u092e\u093e\u0928\u0915 \u0938\u092e\u092f", "-5:00" },
1119        { "hi", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
1120        { "hi", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
1121        { "hi", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
1122        { "hi", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\u0915\u094d\u092f\u0942\u092c\u093e \u0921\u0947\u0932\u093e\u0907\u091f \u0938\u092e\u092f", "-4:00" },
1123        { "hi", "America/Havana", "2004-07-15T00:00:00Z", "v", "\u0915\u094d\u092f\u0942\u092c\u093e \u0938\u092E\u092F", "America/Havana" },
1124        { "hi", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\u0915\u094d\u092f\u0942\u092c\u093e \u0938\u092e\u092f", "America/Havana" },
1125
1126        { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
1127        { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
1128        { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
1129        { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\u0911\u0938\u094d\u200d\u091f\u094d\u0930\u0947\u0932\u093f\u092f\u093e\u0908 \u092a\u0942\u0930\u094d\u0935\u0940 \u0921\u0947\u0932\u093e\u0907\u091f \u0938\u092e\u092f", "+11:00" },
1130        { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
1131        { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
1132        { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
1133        { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\u0911\u0938\u094D\u200D\u091F\u094D\u0930\u0947\u0932\u093F\u092F\u093E\u0908 \u092A\u0942\u0930\u094D\u0935\u0940 \u092E\u093E\u0928\u0915 \u0938\u092E\u092F", "+10:00" },
1134        { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\u0938\u093F\u0921\u0928\u0940 \u0938\u092E\u092F", "Australia/Sydney" },
1135        { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\u092a\u0942\u0930\u094d\u0935\u0940 \u0911\u0938\u094d\u091f\u094d\u0930\u0947\u0932\u093f\u092f\u093e \u0938\u092e\u092f", "Australia/Sydney" },
1136
1137        { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
1138        { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
1139        { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
1140        { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\u0911\u0938\u094d\u200d\u091f\u094d\u0930\u0947\u0932\u093f\u092f\u093e\u0908 \u092a\u0942\u0930\u094d\u0935\u0940 \u0921\u0947\u0932\u093e\u0907\u091f \u0938\u092e\u092f", "+11:00" },
1141        { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
1142        { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
1143        { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
1144        { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\u0911\u0938\u094D\u200D\u091F\u094D\u0930\u0947\u0932\u093F\u092F\u093E\u0908 \u092A\u0942\u0930\u094D\u0935\u0940 \u092E\u093E\u0928\u0915 \u0938\u092E\u092F", "+10:00" },
1145        { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\u0938\u093F\u0921\u0928\u0940 \u0938\u092E\u092F", "Australia/Sydney" },
1146        { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\u092a\u0942\u0930\u094d\u0935\u0940 \u0911\u0938\u094d\u091f\u094d\u0930\u0947\u0932\u093f\u092f\u093e \u0938\u092e\u092f", "Australia/Sydney" },
1147
1148        { "hi", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
1149        { "hi", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
1150        { "hi", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
1151        { "hi", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\u0917\u094d\u0930\u0940\u0928\u0935\u093f\u091a \u092e\u0940\u0928 \u091f\u093e\u0907\u092e", "+0:00" },
1152        { "hi", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
1153        { "hi", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
1154        { "hi", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
1155        { "hi", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\u092c\u094d\u0930\u093f\u091f\u093f\u0936 \u0917\u094d\u0930\u0940\u0937\u094d\u092e\u0915\u093e\u0932\u0940\u0928 \u0938\u092e\u092f", "+1:00" },
1156        { "hi", "Europe/London", "2004-07-15T00:00:00Z", "v", "\u092f\u0942\u0928\u093e\u0907\u091f\u0947\u0921 \u0915\u093f\u0902\u0917\u0921\u092e \u0938\u092e\u092f", "Europe/London" },
1157        { "hi", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\u092f\u0942\u0928\u093e\u0907\u091f\u0947\u0921 \u0915\u093f\u0902\u0917\u0921\u092e \u0938\u092e\u092f", "Europe/London" },
1158
1159        { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
1160        { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
1161        { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
1162        { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
1163        { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
1164        { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
1165        { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
1166        { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
1167        { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
1168        { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
1169
1170        { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
1171        { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
1172        { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "IST", "+5:30" },
1173        { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\u092D\u093E\u0930\u0924\u0940\u092F \u092E\u093E\u0928\u0915 \u0938\u092E\u092F", "+5:30" },
1174        { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
1175        { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30"," +5:30" },
1176        { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "IST", "+05:30" },
1177        { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\u092D\u093E\u0930\u0924\u0940\u092F \u092E\u093E\u0928\u0915 \u0938\u092E\u092F", "+5:30" },
1178        { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "IST", "Asia/Calcutta" },
1179        { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\u092D\u093E\u0930\u0924\u0940\u092F \u092E\u093E\u0928\u0915 \u0938\u092E\u092F", "Asia/Calcutta" },
1180
1181        // ==========
1182
1183        { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
1184        { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", GMT_BG+"-08:00", "-8:00" },
1185        { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", GMT_BG+"-8", "America/Los_Angeles" },
1186        { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\u0421\u0435\u0432\u0435\u0440\u043d\u043e\u0430\u043c\u0435\u0440\u0438\u043a\u0430\u043d\u0441\u043a\u043e \u0442\u0438\u0445\u043e\u043e\u043a\u0435\u0430\u043d\u0441\u043a\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e \u0432\u0440\u0435\u043c\u0435", "America/Los_Angeles" },
1187        { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
1188        { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", GMT_BG+"-07:00", "-7:00" },
1189        { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", GMT_BG+"-7", "America/Los_Angeles" },
1190        { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\u0421\u0435\u0432\u0435\u0440\u043d\u043e\u0430\u043c\u0435\u0440\u0438\u043a\u0430\u043d\u0441\u043a\u043e \u0442\u0438\u0445\u043e\u043e\u043a\u0435\u0430\u043d\u0441\u043a\u043e \u043b\u044f\u0442\u043d\u043e \u0447\u0430\u0441\u043e\u0432\u043e \u0432\u0440\u0435\u043c\u0435", "America/Los_Angeles" },
1191    // icu bg.txt has exemplar city for this time zone
1192        { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\u041B\u043E\u0441 \u0410\u043D\u0434\u0436\u0435\u043B\u0438\u0441", "America/Los_Angeles" },
1193        { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\u0421\u0435\u0432\u0435\u0440\u043d\u043e\u0430\u043c\u0435\u0440\u0438\u043a\u0430\u043d\u0441\u043a\u043e \u0442\u0438\u0445\u043e\u043e\u043a\u0435\u0430\u043d\u0441\u043a\u043e \u0432\u0440\u0435\u043c\u0435", "America/Los_Angeles" },
1194        { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "VVVV", "\u041B\u043E\u0441 \u0410\u043D\u0434\u0436\u0435\u043B\u0438\u0441", "America/Los_Angeles" },
1195
1196        { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
1197        { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", GMT_BG+"-03:00", "-3:00" },
1198        { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", GMT_BG+"-3", "-3:00" },
1199        { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\u0410\u0440\u0436\u0435\u043D\u0442\u0438\u043D\u0441\u043a\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e \u0432\u0440\u0435\u043c\u0435", "-3:00" },
1200        { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
1201        { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", GMT_BG+"-03:00", "-3:00" },
1202        { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", GMT_BG+"-3", "-3:00" },
1203        { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\u0410\u0440\u0436\u0435\u043D\u0442\u0438\u043D\u0441\u043a\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e \u0432\u0440\u0435\u043c\u0435", "-3:00" },
1204        { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\u0411\u0443\u0435\u043D\u043E\u0441 \u0410\u0439\u0440\u0435\u0441", "America/Buenos_Aires" },
1205        { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\u0410\u0440\u0436\u0435\u043D\u0442\u0438\u043D\u0441\u043a\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e \u0432\u0440\u0435\u043c\u0435", "America/Buenos_Aires" },
1206
1207        { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
1208        { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", GMT_BG+"-03:00", "-3:00" },
1209        { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", GMT_BG+"-3", "-3:00" },
1210        { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\u0410\u0440\u0436\u0435\u043D\u0442\u0438\u043D\u0441\u043a\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e \u0432\u0440\u0435\u043c\u0435", "-3:00" },
1211        { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
1212        { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", GMT_BG+"-03:00", "-3:00" },
1213        { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", GMT_BG+"-3", "-3:00" },
1214        { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\u0410\u0440\u0436\u0435\u043D\u0442\u0438\u043D\u0441\u043a\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e \u0432\u0440\u0435\u043c\u0435", "-3:00" },
1215    // icu bg.txt does not have info for this time zone
1216        { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\u0411\u0443\u0435\u043D\u043E\u0441 \u0410\u0439\u0440\u0435\u0441", "America/Buenos_Aires" },
1217        { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\u0410\u0440\u0436\u0435\u043D\u0442\u0438\u043D\u0441\u043a\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e \u0432\u0440\u0435\u043c\u0435", "America/Buenos_Aires" },
1218
1219        { "bg", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
1220        { "bg", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", GMT_BG+"-05:00", "-5:00" },
1221        { "bg", "America/Havana", "2004-01-15T00:00:00Z", "z", GMT_BG+"-5", "-5:00" },
1222        { "bg", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\u041a\u0443\u0431\u0438\u043d\u0441\u043a\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e \u0432\u0440\u0435\u043c\u0435", "-5:00" },
1223        { "bg", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
1224        { "bg", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", GMT_BG+"-04:00", "-4:00" },
1225        { "bg", "America/Havana", "2004-07-15T00:00:00Z", "z", GMT_BG+"-4", "-4:00" },
1226        { "bg", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\u041a\u0443\u0431\u0438\u043d\u0441\u043a\u043e \u043b\u044f\u0442\u043d\u043e \u0447\u0430\u0441\u043e\u0432\u043e \u0432\u0440\u0435\u043c\u0435", "-4:00" },
1227        { "bg", "America/Havana", "2004-07-15T00:00:00Z", "v", "\u041a\u0443\u0431\u0430", "America/Havana" },
1228        { "bg", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\u041a\u0443\u0431\u0438\u043d\u0441\u043a\u043e \u0432\u0440\u0435\u043C\u0435", "America/Havana" },
1229
1230        { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
1231        { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", GMT_BG+"+11:00", "+11:00" },
1232        { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "z", GMT_BG+"+11", "+11:00" },
1233        { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\u0410\u0432\u0441\u0442\u0440\u0430\u043B\u0438\u044F \u2013 \u0438\u0437\u0442\u043E\u0447\u043D\u043E \u043B\u044F\u0442\u043D\u043E \u0447\u0430\u0441\u043E\u0432\u043E \u0432\u0440\u0435\u043C\u0435", "+11:00" },
1234        { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
1235        { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", GMT_BG+"+10:00", "+10:00" },
1236        { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "z", GMT_BG+"+10", "+10:00" },
1237        { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\u0410\u0432\u0441\u0442\u0440\u0430\u043B\u0438\u044F \u2013 \u0438\u0437\u0442\u043E\u0447\u043D\u043E \u0441\u0442\u0430\u043D\u0434\u0430\u0440\u0442\u043D\u043E \u0432\u0440\u0435\u043C\u0435", "+10:00" },
1238        { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\u0421\u0438\u0434\u043D\u0438", "Australia/Sydney" },
1239        { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\u0410\u0432\u0441\u0442\u0440\u0430\u043B\u0438\u044F \u2013 \u0438\u0437\u0442\u043E\u0447\u043D\u043E \u0432\u0440\u0435\u043C\u0435", "Australia/Sydney" },
1240
1241        { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
1242        { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", GMT_BG+"+11:00", "+11:00" },
1243        { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", GMT_BG+"+11", "+11:00" },
1244        { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\u0410\u0432\u0441\u0442\u0440\u0430\u043B\u0438\u044F \u2013 \u0438\u0437\u0442\u043E\u0447\u043D\u043E \u043B\u044F\u0442\u043D\u043E \u0447\u0430\u0441\u043E\u0432\u043E \u0432\u0440\u0435\u043C\u0435", "+11:00" },
1245        { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
1246        { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", GMT_BG+"+10:00", "+10:00" },
1247        { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", GMT_BG+"+10", "+10:00" },
1248        { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\u0410\u0432\u0441\u0442\u0440\u0430\u043B\u0438\u044F \u2013 \u0438\u0437\u0442\u043E\u0447\u043D\u043E \u0441\u0442\u0430\u043D\u0434\u0430\u0440\u0442\u043D\u043E \u0432\u0440\u0435\u043C\u0435", "+10:00" },
1249        { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\u0421\u0438\u0434\u043D\u0438", "Australia/Sydney" },
1250        { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\u0410\u0432\u0441\u0442\u0440\u0430\u043B\u0438\u044F \u2013 \u0438\u0437\u0442\u043E\u0447\u043D\u043E \u0432\u0440\u0435\u043C\u0435", "Australia/Sydney" },
1251
1252        { "bg", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
1253        { "bg", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", GMT_BG, "+0:00" },
1254        { "bg", "Europe/London", "2004-01-15T00:00:00Z", "z", GMT_BG, "+0:00" },
1255        { "bg", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\u0421\u0440\u0435\u0434\u043d\u043e \u0433\u0440\u0438\u043d\u0443\u0438\u0447\u043a\u043e \u0432\u0440\u0435\u043c\u0435", "+0:00" },
1256        { "bg", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
1257        { "bg", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", GMT_BG+"+01:00", "+1:00" },
1258        { "bg", "Europe/London", "2004-07-15T00:00:00Z", "z", GMT_BG+"+1", "+1:00" },
1259        { "bg", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\u0411\u0440\u0438\u0442\u0430\u043d\u0441\u043a\u043e \u043b\u044f\u0442\u043d\u043e \u0447\u0430\u0441\u043e\u0432\u043e \u0432\u0440\u0435\u043c\u0435", "+1:00" },
1260        { "bg", "Europe/London", "2004-07-15T00:00:00Z", "v", "\u0412\u0435\u043b\u0438\u043a\u043e\u0431\u0440\u0438\u0442\u0430\u043d\u0438\u044f", "Europe/London" },
1261        { "bg", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\u0412\u0435\u043b\u0438\u043a\u043e\u0431\u0440\u0438\u0442\u0430\u043d\u0438\u044f", "Europe/London" },
1262
1263        { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
1264        { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", GMT_BG+"-03:00", "-3:00" },
1265        { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", GMT_BG+"-3", "-3:00" },
1266        { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", GMT_BG+"-03:00", "-3:00" },
1267        { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
1268        { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", GMT_BG+"-03:00", "-3:00" },
1269        { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", GMT_BG+"-3", "-3:00" },
1270        { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", GMT_BG+"-03:00", "-3:00" },
1271        { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", GMT_BG+"-3", "-3:00" },
1272        { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", GMT_BG+"-03:00", "-3:00" },
1273
1274        // JB#5150
1275        { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
1276        { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", GMT_BG+"+05:30", "+5:30" },
1277        { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", GMT_BG+"+5:30", "+5:30" },
1278        { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\u0418\u043D\u0434\u0438\u0439\u0441\u043A\u043E \u0441\u0442\u0430\u043D\u0434\u0430\u0440\u0442\u043D\u043E \u0432\u0440\u0435\u043C\u0435", "+5:30" },
1279        { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
1280        { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", GMT_BG+"+05:30", "+5:30" },
1281        { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", GMT_BG+"+5:30", "+05:30" },
1282        { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\u0418\u043D\u0434\u0438\u0439\u0441\u043A\u043E \u0441\u0442\u0430\u043D\u0434\u0430\u0440\u0442\u043D\u043E \u0432\u0440\u0435\u043C\u0435", "+5:30" },
1283        { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\u0418\u043D\u0434\u0438\u044F", "Asia/Calcutta" },
1284        { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\u0418\u043D\u0434\u0438\u0439\u0441\u043A\u043E \u0441\u0442\u0430\u043D\u0434\u0430\u0440\u0442\u043D\u043E \u0432\u0440\u0435\u043C\u0435", "Asia/Calcutta" },
1285
1286    // ==========
1287
1288        { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
1289        { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
1290        { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "America/Los_Angeles" },
1291        { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\u30a2\u30e1\u30ea\u30ab\u592a\u5e73\u6d0b\u6a19\u6e96\u6642", "America/Los_Angeles" },
1292        { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
1293        { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
1294        { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "America/Los_Angeles" },
1295        { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\u30a2\u30e1\u30ea\u30ab\u592a\u5e73\u6d0b\u590f\u6642\u9593", "America/Los_Angeles" },
1296    // icu ja.txt has exemplar city for this time zone
1297        { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\u30ED\u30B5\u30F3\u30BC\u30EB\u30B9\u6642\u9593", "America/Los_Angeles" },
1298        { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\u30A2\u30E1\u30EA\u30AB\u592A\u5E73\u6D0B\u6642\u9593", "America/Los_Angeles" },
1299        { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "VVVV", "\u30ED\u30B5\u30F3\u30BC\u30EB\u30B9\u6642\u9593", "America/Los_Angeles" },
1300
1301        { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
1302        { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
1303        { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
1304        { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\u30A2\u30EB\u30BC\u30F3\u30C1\u30F3\u6A19\u6E96\u6642", "-3:00" },
1305        { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
1306        { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
1307        { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
1308        { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\u30A2\u30EB\u30BC\u30F3\u30C1\u30F3\u6A19\u6E96\u6642", "-3:00" },
1309    // icu ja.txt does not have info for this time zone
1310        { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\u30D6\u30A8\u30CE\u30B9\u30A2\u30A4\u30EC\u30B9\u6642\u9593", "America/Buenos_Aires" },
1311        { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\u30A2\u30EB\u30BC\u30F3\u30C1\u30F3\u6A19\u6E96\u6642", "America/Buenos_Aires" },
1312
1313        { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
1314        { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
1315        { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
1316        { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\u30A2\u30EB\u30BC\u30F3\u30C1\u30F3\u6A19\u6E96\u6642", "-3:00" },
1317        { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
1318        { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
1319        { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
1320        { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\u30A2\u30EB\u30BC\u30F3\u30C1\u30F3\u6A19\u6E96\u6642", "-3:00" },
1321    // icu ja.txt does not have info for this time zone
1322        { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\u30D6\u30A8\u30CE\u30B9\u30A2\u30A4\u30EC\u30B9\u6642\u9593", "America/Buenos_Aires" },
1323        { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\u30A2\u30EB\u30BC\u30F3\u30C1\u30F3\u6A19\u6E96\u6642", "America/Buenos_Aires" },
1324
1325        { "ja", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
1326        { "ja", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
1327        { "ja", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
1328        { "ja", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\u30AD\u30E5\u30FC\u30D0\u6A19\u6E96\u6642", "-5:00" },
1329        { "ja", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
1330        { "ja", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
1331        { "ja", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
1332        { "ja", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\u30AD\u30E5\u30FC\u30D0\u590F\u6642\u9593", "-4:00" },
1333        { "ja", "America/Havana", "2004-07-15T00:00:00Z", "v", "\u30ad\u30e5\u30fc\u30d0\u6642\u9593", "America/Havana" },
1334        { "ja", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\u30ad\u30e5\u30fc\u30d0\u6642\u9593", "America/Havana" },
1335
1336        { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
1337        { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
1338        { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
1339        { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2\u6771\u90E8\u590F\u6642\u9593", "+11:00" },
1340        { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
1341        { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
1342        { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
1343        { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2\u6771\u90E8\u6A19\u6E96\u6642", "+10:00" },
1344    // icu ja.txt does not have info for this time zone
1345        { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\u30B7\u30C9\u30CB\u30FC\u6642\u9593", "Australia/Sydney" },
1346        { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2\u6771\u90E8\u6642\u9593", "Australia/Sydney" },
1347
1348        { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
1349        { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
1350        { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
1351        { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2\u6771\u90E8\u590F\u6642\u9593", "+11:00" },
1352        { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
1353        { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
1354        { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
1355        { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2\u6771\u90E8\u6A19\u6E96\u6642", "+10:00" },
1356        { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\u30B7\u30C9\u30CB\u30FC\u6642\u9593", "Australia/Sydney" },
1357        { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\u30AA\u30FC\u30B9\u30C8\u30E9\u30EA\u30A2\u6771\u90E8\u6642\u9593", "Australia/Sydney" },
1358
1359        { "ja", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
1360        { "ja", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
1361        { "ja", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
1362        { "ja", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\u30B0\u30EA\u30CB\u30C3\u30B8\u6A19\u6E96\u6642", "+0:00" },
1363        { "ja", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
1364        { "ja", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
1365        { "ja", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
1366        { "ja", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\u82f1\u56fd\u590f\u6642\u9593", "+1:00" },
1367        { "ja", "Europe/London", "2004-07-15T00:00:00Z", "v", "\u30a4\u30ae\u30ea\u30b9\u6642\u9593", "Europe/London" },
1368        { "ja", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\u30a4\u30ae\u30ea\u30b9\u6642\u9593", "Europe/London" },
1369        { "ja", "Europe/London", "2004-07-15T00:00:00Z", "VVVV", "\u30a4\u30ae\u30ea\u30b9\u6642\u9593", "Europe/London" },
1370
1371        { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
1372        { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
1373        { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
1374        { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
1375        { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
1376        { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
1377        { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
1378        { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
1379        { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
1380        { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
1381
1382        // JB#5150
1383        { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
1384        { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
1385        { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
1386        { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\u30A4\u30F3\u30C9\u6A19\u6E96\u6642", "+5:30" },
1387        { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
1388        { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
1389        { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
1390        { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\u30A4\u30F3\u30C9\u6A19\u6E96\u6642", "+5:30" },
1391        { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\u30A4\u30F3\u30C9\u6642\u9593", "Asia/Calcutta" },
1392        { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\u30A4\u30F3\u30C9\u6A19\u6E96\u6642", "Asia/Calcutta" },
1393
1394    // ==========
1395    // - We want a locale here that doesn't have anything in the way of translations
1396    // - so we can test the fallback behavior.  If "ti" translates some stuff we will
1397    // - need to choose a different locale.
1398
1399        { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
1400        { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
1401        { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "-8:00" },
1402        { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "GMT-08:00", "-8:00" },
1403        { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
1404        { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
1405        { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "-7:00" },
1406        { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "GMT-07:00", "-7:00" },
1407        { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "Los Angeles", "America/Los_Angeles" },
1408        { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Los Angeles", "America/Los_Angeles" },
1409
1410        { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
1411        { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
1412        { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
1413        { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
1414        { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
1415        { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
1416        { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
1417        { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
1418        { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires", "America/Buenos_Aires" },
1419        { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Buenos Aires", "America/Buenos_Aires" },
1420
1421        { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
1422        { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
1423        { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
1424        { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
1425        { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
1426        { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
1427        { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
1428        { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
1429        { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires", "America/Buenos_Aires" },
1430        { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Buenos Aires", "America/Buenos_Aires" },
1431
1432        { "ti", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
1433        { "ti", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
1434        { "ti", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
1435        { "ti", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "GMT-05:00", "-5:00" },
1436        { "ti", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
1437        { "ti", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
1438        { "ti", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
1439        { "ti", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "GMT-04:00", "-4:00" },
1440        { "ti", "America/Havana", "2004-07-15T00:00:00Z", "v", "CU", "America/Havana" },
1441        { "ti", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "CU", "America/Havana" },
1442
1443        { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
1444        { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
1445        { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
1446        { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "GMT+11:00", "+11:00" },
1447        { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
1448        { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
1449        { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
1450        { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "GMT+10:00", "+10:00" },
1451        { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney", "Australia/Sydney" },
1452        { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Sydney", "Australia/Sydney" },
1453
1454        { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
1455        { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
1456        { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
1457        { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "GMT+11:00", "+11:00" },
1458        { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
1459        { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
1460        { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
1461        { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "GMT+10:00", "+10:00" },
1462        { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney", "Australia/Sydney" },
1463        { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Sydney", "Australia/Sydney" },
1464
1465        { "ti", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
1466        { "ti", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
1467        { "ti", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
1468        { "ti", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "GMT", "+0:00" },
1469        { "ti", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
1470        { "ti", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
1471        { "ti", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
1472        { "ti", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "GMT+01:00", "+1:00" },
1473        { "ti", "Europe/London", "2004-07-15T00:00:00Z", "v", "GB", "Europe/London" },
1474        { "ti", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "GB", "Europe/London" },
1475
1476        { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
1477        { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
1478        { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
1479        { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
1480        { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
1481        { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
1482        { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
1483        { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
1484        { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
1485        { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
1486
1487        // JB#5150
1488        { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
1489        { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
1490        { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
1491        { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "GMT+05:30", "+5:30" },
1492        { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
1493        { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
1494        { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
1495        { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "GMT+05:30", "+5:30" },
1496        { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "IN", "Asia/Calcutta" },
1497        { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "IN", "Asia/Calcutta" },
1498
1499        // Ticket#8589 Partial location name to use country name if the zone is the golden
1500        // zone for the time zone's country.
1501        { "en_MX", "America/Chicago", "1995-07-15T00:00:00Z", "vvvv", "Central Time (United States)", "America/Chicago"},
1502
1503        // Tests proper handling of time zones that should have empty sets when inherited from the parent.
1504        // For example, en_GB understands CET as Central European Time, but en_HK, which inherits from en_GB
1505        // does not
1506        { "en_GB", "Europe/Paris", "2004-01-15T00:00:00Z", "zzzz", "Central European Standard Time", "+1:00"},
1507        { "en_GB", "Europe/Paris", "2004-07-15T00:00:00Z", "zzzz", "Central European Summer Time", "+2:00"},
1508        { "en_GB", "Europe/Paris", "2004-01-15T00:00:00Z", "z", "CET", "+1:00"},
1509        { "en_GB", "Europe/Paris", "2004-07-15T00:00:00Z", "z", "CEST", "+2:00"},
1510        { "en_HK", "Europe/Paris", "2004-01-15T00:00:00Z", "zzzz", "Central European Standard Time", "+1:00"},
1511        { "en_HK", "Europe/Paris", "2004-07-15T00:00:00Z", "zzzz", "Central European Summer Time", "+2:00"},
1512        { "en_HK", "Europe/Paris", "2004-01-15T00:00:00Z", "z", "GMT+1", "+1:00"},
1513        { "en_HK", "Europe/Paris", "2004-07-15T00:00:00Z", "z", "GMT+2", "+2:00"},
1514    };
1515    /**
1516     * Verify that strings which contain incomplete specifications are parsed
1517     * correctly.  In some instances, this means not being parsed at all, and
1518     * returning an appropriate error.
1519     */
1520    public void TestPartialParse994() {
1521
1522        SimpleDateFormat f = new SimpleDateFormat();
1523        Calendar cal = Calendar.getInstance();
1524        cal.clear();
1525        cal.set(1997, 1 - 1, 17, 10, 11, 42);
1526        Date date = null;
1527        tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:11:42", cal.getTime());
1528        tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:", date);
1529        tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10", date);
1530        tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 ", date);
1531        tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17", date);
1532    }
1533
1534    // internal test subroutine, used by TestPartialParse994
1535    public void tryPat994(SimpleDateFormat format, String pat, String str, Date expected) {
1536        Date Null = null;
1537        logln("Pattern \"" + pat + "\"   String \"" + str + "\"");
1538        try {
1539            format.applyPattern(pat);
1540            Date date = format.parse(str);
1541            String f = ((DateFormat) format).format(date);
1542            logln(" parse(" + str + ") -> " + date);
1543            logln(" format -> " + f);
1544            if (expected.equals(Null) || !date.equals(expected))
1545                errln("FAIL: Expected null"); //" + expected);
1546            if (!f.equals(str))
1547                errln("FAIL: Expected " + str);
1548        } catch (ParseException e) {
1549            logln("ParseException: " + e.getMessage());
1550            if (!(expected ==Null))
1551                errln("FAIL: Expected " + expected);
1552        } catch (Exception e) {
1553            errln("*** Exception:");
1554            e.printStackTrace();
1555        }
1556    }
1557
1558    /**
1559     * Verify the behavior of patterns in which digits for different fields run together
1560     * without intervening separators.
1561     */
1562    public void TestRunTogetherPattern985() {
1563        String format = "yyyyMMddHHmmssSSS";
1564        String now, then;
1565        //UBool flag;
1566        SimpleDateFormat formatter = new SimpleDateFormat(format);
1567        Date date1 = new Date();
1568        now = ((DateFormat) formatter).format(date1);
1569        logln(now);
1570        ParsePosition pos = new ParsePosition(0);
1571        Date date2 = formatter.parse(now, pos);
1572        if (date2 == null)
1573            then = "Parse stopped at " + pos.getIndex();
1574        else
1575            then = ((DateFormat) formatter).format(date2);
1576        logln(then);
1577        if (date2 == null || !date2.equals(date1))
1578            errln("FAIL");
1579    }
1580
1581    /**
1582     * Verify the behavior of patterns in which digits for different fields run together
1583     * without intervening separators.
1584     */
1585    public void TestRunTogetherPattern917() {
1586        SimpleDateFormat fmt;
1587        String myDate;
1588        fmt = new SimpleDateFormat("yyyy/MM/dd");
1589        myDate = "1997/02/03";
1590        Calendar cal = Calendar.getInstance();
1591        cal.clear();
1592        cal.set(1997, 2 - 1, 3);
1593        _testIt917(fmt, myDate, cal.getTime());
1594        fmt = new SimpleDateFormat("yyyyMMdd");
1595        myDate = "19970304";
1596        cal.clear();
1597        cal.set(1997, 3 - 1, 4);
1598        _testIt917(fmt, myDate, cal.getTime());
1599
1600    }
1601
1602    // internal test subroutine, used by TestRunTogetherPattern917
1603    public void _testIt917(SimpleDateFormat fmt, String str, Date expected) {
1604        logln("pattern=" + fmt.toPattern() + "   string=" + str);
1605        Date o = new Date();
1606        o = (Date) ((DateFormat) fmt).parseObject(str, new ParsePosition(0));
1607        logln("Parsed object: " + o);
1608        if (o == null || !o.equals(expected))
1609            errln("FAIL: Expected " + expected);
1610        String formatted = o==null? "null" : ((DateFormat) fmt).format(o);
1611        logln( "Formatted string: " + formatted);
1612        if (!formatted.equals(str))
1613            errln( "FAIL: Expected " + str);
1614    }
1615
1616    /**
1617     * Verify the handling of Czech June and July, which have the unique attribute that
1618     * one is a proper prefix substring of the other.
1619     */
1620    public void TestCzechMonths459() {
1621        DateFormat fmt = DateFormat.getDateInstance(DateFormat.FULL, new Locale("cs", "", ""));
1622        logln("Pattern " + ((SimpleDateFormat) fmt).toPattern());
1623        Calendar cal = Calendar.getInstance();
1624        cal.clear();
1625        cal.set(1997, Calendar.JUNE, 15);
1626        Date june = cal.getTime();
1627        cal.clear();
1628        cal.set(1997, Calendar.JULY, 15);
1629        Date july = cal.getTime();
1630        String juneStr = fmt.format(june);
1631        String julyStr = fmt.format(july);
1632        try {
1633            logln("format(June 15 1997) = " + juneStr);
1634            Date d = fmt.parse(juneStr);
1635            String s = fmt.format(d);
1636            int month, yr, day;
1637            cal.setTime(d);
1638            yr = cal.get(Calendar.YEAR);
1639            month = cal.get(Calendar.MONTH);
1640            day = cal.get(Calendar.DAY_OF_MONTH);
1641            logln("  . parse . " + s + " (month = " + month + ")");
1642            if (month != Calendar.JUNE)
1643                errln("FAIL: Month should be June");
1644            if (yr != 1997)
1645                errln("FAIL: Year should be 1997");
1646            if (day != 15)
1647                errln("FAIL: day should be 15");
1648            logln("format(July 15 1997) = " + julyStr);
1649            d = fmt.parse(julyStr);
1650            s = fmt.format(d);
1651            cal.setTime(d);
1652            yr = cal.get(Calendar.YEAR) - 1900;
1653            month = cal.get(Calendar.MONTH);
1654            day = cal.get(Calendar.DAY_OF_WEEK);
1655            logln("  . parse . " + s + " (month = " + month + ")");
1656            if (month != Calendar.JULY)
1657                errln("FAIL: Month should be July");
1658        } catch (ParseException e) {
1659            errln(e.getMessage());
1660        }
1661    }
1662
1663    /**
1664     * Test the handling of 'D' in patterns.
1665     */
1666    public void TestLetterDPattern212() {
1667        String dateString = "1995-040.05:01:29";
1668        String bigD = "yyyy-DDD.hh:mm:ss";
1669        String littleD = "yyyy-ddd.hh:mm:ss";
1670        Calendar cal = Calendar.getInstance();
1671        cal.clear();
1672        cal.set(1995, 0, 1, 5, 1, 29);
1673        Date expLittleD = cal.getTime();
1674        Date expBigD = new Date((long) (expLittleD.getTime() + 39 * 24 * 3600000.0));
1675        expLittleD = expBigD; // Expect the same, with default lenient parsing
1676        logln("dateString= " + dateString);
1677        SimpleDateFormat formatter = new SimpleDateFormat(bigD);
1678        ParsePosition pos = new ParsePosition(0);
1679        Date myDate = formatter.parse(dateString, pos);
1680        logln("Using " + bigD + " . " + myDate);
1681        if (!myDate.equals(expBigD))
1682            errln("FAIL: Expected " + expBigD);
1683        formatter = new SimpleDateFormat(littleD);
1684        pos = new ParsePosition(0);
1685        myDate = formatter.parse(dateString, pos);
1686        logln("Using " + littleD + " . " + myDate);
1687        if (!myDate.equals(expLittleD))
1688            errln("FAIL: Expected " + expLittleD);
1689    }
1690
1691    /**
1692     * Test the day of year pattern.
1693     */
1694    public void TestDayOfYearPattern195() {
1695        Calendar cal = Calendar.getInstance();
1696        Date today = cal.getTime();
1697        int year,month,day;
1698        year = cal.get(Calendar.YEAR);
1699        month = cal.get(Calendar.MONTH);
1700        day = cal.get(Calendar.DAY_OF_MONTH);
1701        cal.clear();
1702        cal.set(year, month, day);
1703        Date expected = cal.getTime();
1704        logln("Test Date: " + today);
1705        SimpleDateFormat sdf = (SimpleDateFormat)DateFormat.getDateInstance();
1706        tryPattern(sdf, today, null, expected);
1707        tryPattern(sdf, today, "G yyyy DDD", expected);
1708    }
1709
1710    // interl test subroutine, used by TestDayOfYearPattern195
1711    public void tryPattern(SimpleDateFormat sdf, Date d, String pattern, Date expected) {
1712        if (pattern != null)
1713            sdf.applyPattern(pattern);
1714        logln("pattern: " + sdf.toPattern());
1715        String formatResult = ((DateFormat) sdf).format(d);
1716        logln(" format -> " + formatResult);
1717        try {
1718            Date d2 = sdf.parse(formatResult);
1719            logln(" parse(" + formatResult + ") -> " + d2);
1720            if (!d2.equals(expected))
1721                errln("FAIL: Expected " + expected);
1722            String format2 = ((DateFormat) sdf).format(d2);
1723            logln(" format -> " + format2);
1724            if (!formatResult.equals(format2))
1725                errln("FAIL: Round trip drift");
1726        } catch (Exception e) {
1727            errln(e.getMessage());
1728        }
1729    }
1730
1731    /**
1732     * Test the handling of single quotes in patterns.
1733     */
1734    public void TestQuotePattern161() {
1735        SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy 'at' hh:mm:ss a zzz", Locale.US);
1736        Calendar cal = Calendar.getInstance();
1737        cal.clear();
1738        cal.set(1997, Calendar.AUGUST, 13, 10, 42, 28);
1739        Date currentTime_1 = cal.getTime();
1740        String dateString = ((DateFormat) formatter).format(currentTime_1);
1741        String exp = "08/13/1997 at 10:42:28 AM ";
1742        logln("format(" + currentTime_1 + ") = " + dateString);
1743        if (!dateString.substring(0, exp.length()).equals(exp))
1744            errln("FAIL: Expected " + exp);
1745
1746    }
1747
1748    /**
1749     * Verify the correct behavior when handling invalid input strings.
1750     */
1751    public void TestBadInput135() {
1752        int looks[] = {DateFormat.SHORT, DateFormat.MEDIUM, DateFormat.LONG, DateFormat.FULL};
1753        int looks_length = looks.length;
1754        final String[] strings = {"Mar 15", "Mar 15 1997", "asdf", "3/1/97 1:23:", "3/1/00 1:23:45 AM"};
1755        int strings_length = strings.length;
1756        DateFormat full = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, Locale.US);
1757        String expected = "March 1, 2000 at 1:23:45 AM ";
1758        for (int i = 0; i < strings_length; ++i) {
1759            final String text = strings[i];
1760            for (int j = 0; j < looks_length; ++j) {
1761                int dateLook = looks[j];
1762                for (int k = 0; k < looks_length; ++k) {
1763                    int timeLook = looks[k];
1764                    DateFormat df = DateFormat.getDateTimeInstance(dateLook, timeLook, Locale.US);
1765                    String prefix = text + ", " + dateLook + "/" + timeLook + ": ";
1766                    try {
1767                        Date when = df.parse(text);
1768                        if (when == null) {
1769                            errln(prefix + "SHOULD NOT HAPPEN: parse returned null.");
1770                            continue;
1771                        }
1772                        if (when != null) {
1773                            String format;
1774                            format = full.format(when);
1775                            logln(prefix + "OK: " + format);
1776                            if (!format.substring(0, expected.length()).equals(expected)) {
1777                                errln("FAIL: Expected <" + expected + ">, but got <"
1778                                        + format.substring(0, expected.length()) + ">");
1779                            }
1780                        }
1781                    } catch(java.text.ParseException e) {
1782                        logln(e.getMessage());
1783                    }
1784                }
1785            }
1786        }
1787    }
1788
1789    /**
1790     * Verify the correct behavior when parsing an array of inputs against an
1791     * array of patterns, with known results.  The results are encoded after
1792     * the input strings in each row.
1793     */
1794    public void TestBadInput135a() {
1795
1796        SimpleDateFormat dateParse = new SimpleDateFormat("", Locale.US);
1797        final String ss;
1798        Date date;
1799        String[] parseFormats ={"MMMM d, yyyy", "MMMM d yyyy", "M/d/yy",
1800                                "d MMMM, yyyy", "d MMMM yyyy",  "d MMMM",
1801                                "MMMM d", "yyyy", "h:mm a MMMM d, yyyy" };
1802        String[] inputStrings = {
1803            "bogus string", null, null, null, null, null, null, null, null, null,
1804                "April 1, 1997", "April 1, 1997", null, null, null, null, null, "April 1", null, null,
1805                "Jan 1, 1970", "January 1, 1970", null, null, null, null, null, "January 1", null, null,
1806                "Jan 1 2037", null, "January 1 2037", null, null, null, null, "January 1", null, null,
1807                "1/1/70", null, null, "1/1/70", null, null, null, null, "0001", null,
1808                "5 May 1997", null, null, null, null, "5 May 1997", "5 May", null, "0005", null,
1809                "16 May", null, null, null, null, null, "16 May", null, "0016", null,
1810                "April 30", null, null, null, null, null, null, "April 30", null, null,
1811                "1998", null, null, null, null, null, null, null, "1998", null,
1812                "1", null, null, null, null, null, null, null, "0001", null,
1813                "3:00 pm Jan 1, 1997", null, null, null, null, null, null, null, "0003", "3:00 PM January 1, 1997",
1814                };
1815        final int PF_LENGTH = parseFormats.length;
1816        final int INPUT_LENGTH = inputStrings.length;
1817
1818        dateParse.applyPattern("d MMMM, yyyy");
1819        dateParse.setTimeZone(TimeZone.getDefault());
1820        ss = "not parseable";
1821        //    String thePat;
1822        logln("Trying to parse \"" + ss + "\" with " + dateParse.toPattern());
1823        try {
1824            date = dateParse.parse(ss);
1825        } catch (Exception ex) {
1826            logln("FAIL:" + ex);
1827        }
1828        for (int i = 0; i < INPUT_LENGTH; i += (PF_LENGTH + 1)) {
1829            ParsePosition parsePosition = new ParsePosition(0);
1830            String s = inputStrings[i];
1831            for (int index = 0; index < PF_LENGTH; ++index) {
1832                final String expected = inputStrings[i + 1 + index];
1833                dateParse.applyPattern(parseFormats[index]);
1834                dateParse.setTimeZone(TimeZone.getDefault());
1835                try {
1836                    parsePosition.setIndex(0);
1837                    date = dateParse.parse(s, parsePosition);
1838                    if (parsePosition.getIndex() != 0) {
1839                        String s1, s2;
1840                        s1 = s.substring(0, parsePosition.getIndex());
1841                        s2 = s.substring(parsePosition.getIndex(), s.length());
1842                        if (date == null) {
1843                            errln("ERROR: null result fmt=\"" + parseFormats[index]
1844                                    + "\" pos=" + parsePosition.getIndex()
1845                                    + " " + s1 + "|" + s2);
1846                        } else {
1847                            String result = ((DateFormat) dateParse).format(date);
1848                            logln("Parsed \"" + s + "\" using \"" + dateParse.toPattern() + "\" to: " + result);
1849                            if (expected == null)
1850                                errln("FAIL: Expected parse failure for <" + result + ">");
1851                            else
1852                                if (!result.equals(expected))
1853                                    errln("FAIL: Expected " + expected);
1854                        }
1855                    } else
1856                        if (expected != null) {
1857                            errln("FAIL: Expected " + expected + " from \"" + s
1858                                    + "\" with \"" + dateParse.toPattern()+ "\"");
1859                        }
1860                } catch (Exception ex) {
1861                    logln("FAIL:" + ex);
1862                }
1863            }
1864        }
1865
1866    }
1867
1868    /**
1869     * Test the parsing of two-digit years.
1870     */
1871    public void TestTwoDigitYear() {
1872        DateFormat fmt = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US);
1873        Calendar cal = Calendar.getInstance();
1874        cal.clear();
1875        cal.set(130 + 1900, Calendar.JUNE, 5);
1876        parse2DigitYear(fmt, "6/5/30", cal.getTime());
1877        cal.clear();
1878        cal.set(50 + 1900, Calendar.JUNE, 4);
1879        parse2DigitYear(fmt, "6/4/50", cal.getTime());
1880    }
1881
1882    // internal test subroutine, used by TestTwoDigitYear
1883    public void parse2DigitYear(DateFormat fmt, String str, Date expected) {
1884        try {
1885            Date d = fmt.parse(str);
1886            logln("Parsing \""+ str+ "\" with "+ ((SimpleDateFormat) fmt).toPattern()
1887                    + "  => "+ d);
1888            if (!d.equals(expected))
1889                errln( "FAIL: Expected " + expected);
1890        } catch (ParseException e) {
1891            errln(e.getMessage());
1892        }
1893    }
1894
1895    /**
1896     * Test the formatting of time zones.
1897     */
1898    public void TestDateFormatZone061() {
1899        Date date;
1900        DateFormat formatter;
1901        date = new Date(859248000000L);
1902        logln("Date 1997/3/25 00:00 GMT: " + date);
1903        formatter = new SimpleDateFormat("dd-MMM-yyyyy HH:mm", Locale.UK);
1904        formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
1905        String temp = formatter.format(date);
1906        logln("Formatted in GMT to: " + temp);
1907        try {
1908            Date tempDate = formatter.parse(temp);
1909            logln("Parsed to: " + tempDate);
1910            if (!tempDate.equals(date))
1911                errln("FAIL: Expected " + date + " Got: " + tempDate);
1912        } catch (Throwable t) {
1913            System.out.println(t);
1914        }
1915
1916    }
1917
1918    /**
1919     * Test the formatting of time zones.
1920     */
1921    public void TestDateFormatZone146() {
1922        TimeZone saveDefault = TimeZone.getDefault();
1923
1924        //try {
1925        TimeZone thedefault = TimeZone.getTimeZone("GMT");
1926        TimeZone.setDefault(thedefault);
1927        // java.util.Locale.setDefault(new java.util.Locale("ar", "", ""));
1928
1929        // check to be sure... its GMT all right
1930        TimeZone testdefault = TimeZone.getDefault();
1931        String testtimezone = testdefault.getID();
1932        if (testtimezone.equals("GMT"))
1933            logln("Test timezone = " + testtimezone);
1934        else
1935            errln("Test timezone should be GMT, not " + testtimezone);
1936
1937        // now try to use the default GMT time zone
1938        GregorianCalendar greenwichcalendar = new GregorianCalendar(1997, 3, 4, 23, 0);
1939        //*****************************greenwichcalendar.setTimeZone(TimeZone.getDefault());
1940        //greenwichcalendar.set(1997, 3, 4, 23, 0);
1941        // try anything to set hour to 23:00 !!!
1942        greenwichcalendar.set(Calendar.HOUR_OF_DAY, 23);
1943        // get time
1944        Date greenwichdate = greenwichcalendar.getTime();
1945        // format every way
1946        String DATA[] = {
1947                "simple format:  ", "04/04/97 23:00 GMT",
1948                "MM/dd/yy HH:mm zzz", "full format:    ",
1949                "Friday, April 4, 1997 11:00:00 o'clock PM GMT",
1950                "EEEE, MMMM d, yyyy h:mm:ss 'o''clock' a zzz",
1951                "long format:    ", "April 4, 1997 11:00:00 PM GMT",
1952                "MMMM d, yyyy h:mm:ss a z", "default format: ",
1953                "04-Apr-97 11:00:00 PM", "dd-MMM-yy h:mm:ss a",
1954                "short format:   ", "4/4/97 11:00 PM",
1955                "M/d/yy h:mm a"};
1956        int DATA_length = DATA.length;
1957
1958        for (int i = 0; i < DATA_length; i += 3) {
1959            DateFormat fmt = new SimpleDateFormat(DATA[i + 2], Locale.ENGLISH);
1960            fmt.setCalendar(greenwichcalendar);
1961            String result = fmt.format(greenwichdate);
1962            logln(DATA[i] + result);
1963            if (!result.equals(DATA[i + 1]))
1964                errln("FAIL: Expected " + DATA[i + 1] + ", got " + result);
1965        }
1966        //}
1967        //finally {
1968        TimeZone.setDefault(saveDefault);
1969        //}
1970
1971    }
1972
1973    /**
1974     * Test the formatting of dates in different locales.
1975     */
1976    public void TestLocaleDateFormat() {
1977        Date testDate = new Date(874306800000L); //Mon Sep 15 00:00:00 PDT 1997
1978        DateFormat dfFrench = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, Locale.FRENCH);
1979        DateFormat dfUS = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, Locale.US);
1980        //Set TimeZone = PDT
1981        TimeZone tz = TimeZone.getTimeZone("PST");
1982        dfFrench.setTimeZone(tz);
1983        dfUS.setTimeZone(tz);
1984        String expectedFRENCH_JDK12 = "lundi 15 septembre 1997 00:00:00 heure d\u2019\u00E9t\u00E9 du Pacifique";
1985        //String expectedFRENCH = "lundi 15 septembre 1997 00 h 00 PDT";
1986        String expectedUS = "Monday, September 15, 1997 at 12:00:00 AM Pacific Daylight Time";
1987        logln("Date set to : " + testDate);
1988        String out = dfFrench.format(testDate);
1989        logln("Date Formated with French Locale " + out);
1990        //fix the jdk resources differences between jdk 1.2 and jdk 1.3
1991        /* our own data only has GMT-xxxx information here
1992        String javaVersion = System.getProperty("java.version");
1993        if (javaVersion.startsWith("1.2")) {
1994            if (!out.equals(expectedFRENCH_JDK12))
1995                errln("FAIL: Expected " + expectedFRENCH_JDK12+" Got "+out);
1996        } else {
1997            if (!out.equals(expectedFRENCH))
1998                errln("FAIL: Expected " + expectedFRENCH);
1999        }
2000        */
2001        if (!out.equals(expectedFRENCH_JDK12))
2002            errln("FAIL: Expected " + expectedFRENCH_JDK12+" Got "+out);
2003        out = dfUS.format(testDate);
2004        logln("Date Formated with US Locale " + out);
2005        if (!out.equals(expectedUS))
2006            errln("FAIL: Expected " + expectedUS+" Got "+out);
2007    }
2008
2009    public void TestFormattingLocaleTimeSeparator() {
2010        Date date = new Date(874266720000L);  // Sun Sep 14 21:52:00 CET 1997
2011        TimeZone tz = TimeZone.getTimeZone("CET");
2012
2013        DateFormat dfArab = DateFormat.getTimeInstance(DateFormat.SHORT, new ULocale("ar"));
2014        DateFormat dfLatn = DateFormat.getTimeInstance(DateFormat.SHORT, new ULocale("ar-u-nu-latn"));
2015
2016        dfArab.setTimeZone(tz);
2017        dfLatn.setTimeZone(tz);
2018
2019        String expectedArab = "\u0669\u060C\u0665\u0662 \u0645";
2020        String expectedLatn = "9:52 \u0645";
2021
2022        String actualArab = dfArab.format(date);
2023        String actualLatn = dfLatn.format(date);
2024
2025        if (!actualArab.equals(expectedArab)) {
2026            errln("FAIL: Expected " + expectedArab + " Got " + actualArab);
2027        }
2028        if (!actualLatn.equals(expectedLatn)) {
2029            errln("FAIL: Expected " + expectedLatn + " Got " + actualLatn);
2030        }
2031    }
2032
2033    /**
2034     * Test the formatting of dates with the 'NONE' keyword.
2035     */
2036    public void TestDateFormatNone() {
2037        Date testDate = new Date(874306800000L); //Mon Sep 15 00:00:00 PDT 1997
2038        DateFormat dfFrench = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.NONE, Locale.FRENCH);
2039        //Set TimeZone = PDT
2040        TimeZone tz = TimeZone.getTimeZone("PST");
2041        dfFrench.setTimeZone(tz);
2042        String expectedFRENCH_JDK12 = "lundi 15 septembre 1997";
2043        //String expectedFRENCH = "lundi 15 septembre 1997 00 h 00 PDT";
2044        logln("Date set to : " + testDate);
2045        String out = dfFrench.format(testDate);
2046        logln("Date Formated with French Locale " + out);
2047        if (!out.equals(expectedFRENCH_JDK12))
2048            errln("FAIL: Expected " + expectedFRENCH_JDK12+" Got "+out);
2049    }
2050
2051
2052    /**
2053     * Test DateFormat(Calendar) API
2054     */
2055    public void TestDateFormatCalendar() {
2056        DateFormat date=null, time=null, full=null;
2057        Calendar cal=null;
2058        ParsePosition pos = new ParsePosition(0);
2059        String str;
2060        Date when;
2061
2062        /* Create a formatter for date fields. */
2063        date = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US);
2064        if (date == null) {
2065            errln("FAIL: getDateInstance failed");
2066            return;
2067        }
2068
2069        /* Create a formatter for time fields. */
2070        time = DateFormat.getTimeInstance(DateFormat.SHORT, Locale.US);
2071        if (time == null) {
2072            errln("FAIL: getTimeInstance failed");
2073            return;
2074        }
2075
2076        /* Create a full format for output */
2077        full = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL,
2078                                              Locale.US);
2079        if (full == null) {
2080            errln("FAIL: getInstance failed");
2081            return;
2082        }
2083
2084        /* Create a calendar */
2085        cal = Calendar.getInstance(Locale.US);
2086        if (cal == null) {
2087            errln("FAIL: Calendar.getInstance failed");
2088            return;
2089        }
2090
2091        /* Parse the date */
2092        cal.clear();
2093        str = "4/5/2001";
2094        pos.setIndex(0);
2095        date.parse(str, cal, pos);
2096        if (pos.getIndex() != str.length()) {
2097            errln("FAIL: DateFormat.parse(4/5/2001) failed at " +
2098                  pos.getIndex());
2099            return;
2100        }
2101
2102        /* Parse the time */
2103        str = "5:45 PM";
2104        pos.setIndex(0);
2105        time.parse(str, cal, pos);
2106        if (pos.getIndex() != str.length()) {
2107            errln("FAIL: DateFormat.parse(17:45) failed at " +
2108                  pos.getIndex());
2109            return;
2110        }
2111
2112        /* Check result */
2113        when = cal.getTime();
2114        str = full.format(when);
2115        // Thursday, April 5, 2001 5:45:00 PM PDT 986517900000
2116        if (when.getTime() == 986517900000.0) {
2117            logln("Ok: Parsed result: " + str);
2118        } else {
2119            errln("FAIL: Parsed result: " + str + ", exp 4/5/2001 5:45 PM");
2120        }
2121    }
2122
2123    /**
2124     * Test DateFormat's parsing of space characters.  See jitterbug 1916.
2125     */
2126    public void TestSpaceParsing() {
2127
2128        String DATA[] = {
2129            "yyyy MM dd HH:mm:ss",
2130
2131            // pattern, input, expected output (in quotes)
2132            "MMMM d yy", " 04 05 06",  null, // MMMM wants Apr/April
2133            null,        "04 05 06",   null,
2134            "MM d yy",   " 04 05 06",  "2006 04 05 00:00:00",
2135            null,        "04 05 06",   "2006 04 05 00:00:00",
2136            "MMMM d yy", " Apr 05 06", "2006 04 05 00:00:00",
2137            null,        "Apr 05 06",  "2006 04 05 00:00:00",
2138
2139            "hh:mm:ss a", "12:34:56 PM", "1970 01 01 12:34:56",
2140            null,         "12:34:56PM",  "1970 01 01 12:34:56",
2141            null,         "12.34.56PM",  "1970 01 01 12:34:56",
2142            null,         "12 : 34 : 56  PM", "1970 01 01 12:34:56",
2143        };
2144
2145        expectParse(DATA, new Locale("en", "", ""));
2146    }
2147
2148    /**
2149     * Test handling of "HHmmss" pattern.
2150     */
2151    public void TestExactCountFormat() {
2152        String DATA[] = {
2153            "yyyy MM dd HH:mm:ss",
2154
2155            // pattern, input, expected parse or null if expect parse failure
2156            "HHmmss", "123456", "1970 01 01 12:34:56",
2157            null,     "12345",  "1970 01 01 01:23:45",
2158            null,     "1234",   null,
2159            null,     "00-05",  null,
2160            null,     "12-34",  null,
2161            null,     "00+05",  null,
2162            "ahhmm",  "PM730",  "1970 01 01 19:30:00",
2163        };
2164
2165        expectParse(DATA, new Locale("en", "", ""));
2166    }
2167
2168    /**
2169     * Test handling of white space.
2170     */
2171    public void TestWhiteSpaceParsing() {
2172        String DATA[] = {
2173            "yyyy MM dd",
2174
2175            // pattern, input, expected parse or null if expect parse failure
2176
2177            // Pattern space run should parse input text space run
2178            "MM   d yy",   " 04 01 03",    "2003 04 01",
2179            null,          " 04  01   03 ", "2003 04 01",
2180        };
2181
2182        expectParse(DATA, new Locale("en", "", ""));
2183    }
2184
2185    public void TestInvalidPattern() {
2186        Exception e = null;
2187        SimpleDateFormat f = null;
2188        String out = null;
2189        try {
2190            f = new SimpleDateFormat("Yesterday");
2191            out = f.format(new Date(0));
2192        } catch (IllegalArgumentException e1) {
2193            e = e1;
2194        }
2195        if (e != null) {
2196            logln("Ok: Received " + e.getMessage());
2197        } else {
2198            errln("FAIL: Expected exception, got " + f.toPattern() +
2199                  "; " + out);
2200        }
2201    }
2202
2203    public void TestGreekMay() {
2204        Date date = new Date(-9896080848000L);
2205        SimpleDateFormat fmt = new SimpleDateFormat("EEEE, dd MMMM yyyy h:mm:ss a",
2206                             new Locale("el", "", ""));
2207        String str = fmt.format(date);
2208        ParsePosition pos = new ParsePosition(0);
2209        Date d2 = fmt.parse(str, pos);
2210        if (!date.equals(d2)) {
2211            errln("FAIL: unable to parse strings where case-folding changes length");
2212        }
2213    }
2214
2215    public void TestErrorChecking() {
2216        try {
2217            DateFormat.getDateTimeInstance(-1, -1, Locale.US);
2218            errln("Expected exception for getDateTimeInstance(-1, -1, Locale)");
2219        }
2220        catch(IllegalArgumentException e) {
2221            logln("one ok");
2222        }
2223        catch(Exception e) {
2224            warnln("Expected IllegalArgumentException, got: " + e);
2225        }
2226
2227        try {
2228            DateFormat df = new SimpleDateFormat("aabbccc");
2229            df.format(new Date());
2230            errln("Expected exception for format with bad pattern");
2231        }
2232        catch(IllegalArgumentException ex) {
2233            logln("two ok");
2234        }
2235        catch(Exception e) {
2236            warnln("Expected IllegalArgumentException, got: " + e);
2237        }
2238
2239        {
2240            SimpleDateFormat fmt = new SimpleDateFormat("dd/MM/yy"); // opposite of text
2241            fmt.set2DigitYearStart(getDate(2003, Calendar.DECEMBER, 25));
2242            String text = "12/25/03";
2243            Calendar xcal = new GregorianCalendar();
2244            xcal.setLenient(false);
2245            ParsePosition pp = new ParsePosition(0);
2246            fmt.parse(text, xcal, pp); // should get parse error on second field, not lenient
2247            if (pp.getErrorIndex() == -1) {
2248                errln("Expected parse error");
2249            } else {
2250                logln("three ok");
2251            }
2252        }
2253    }
2254
2255    public void TestChineseDateFormatLocalizedPatternChars() {
2256        // jb 4904
2257        // make sure we can display localized versions of the chars used in the default
2258        // chinese date format patterns
2259        Calendar chineseCalendar = new ChineseCalendar();
2260        chineseCalendar.setTimeInMillis((new Date()).getTime());
2261        SimpleDateFormat longChineseDateFormat =
2262            (SimpleDateFormat)chineseCalendar.getDateTimeFormat(DateFormat.LONG, DateFormat.LONG, Locale.CHINA );
2263        DateFormatSymbols dfs = new ChineseDateFormatSymbols( chineseCalendar, Locale.CHINA );
2264        longChineseDateFormat.setDateFormatSymbols( dfs );
2265        // This next line throws the exception
2266        try {
2267            longChineseDateFormat.toLocalizedPattern();
2268        }
2269        catch (Exception e) {
2270            errln("could not localized pattern: " + e.getMessage());
2271        }
2272    }
2273
2274    public void TestCoverage() {
2275        Date now = new Date();
2276        Calendar cal = new GregorianCalendar();
2277        DateFormat f = DateFormat.getTimeInstance();
2278        logln("time: " + f.format(now));
2279
2280        int hash = f.hashCode(); // sigh, everyone overrides this
2281
2282        f = DateFormat.getInstance(cal);
2283        if(hash == f.hashCode()){
2284            errln("FAIL: hashCode equal for inequal objects");
2285        }
2286        logln("time again: " + f.format(now));
2287
2288        f = DateFormat.getTimeInstance(cal, DateFormat.FULL);
2289        logln("time yet again: " + f.format(now));
2290
2291        f = DateFormat.getDateInstance();
2292        logln("time yet again: " + f.format(now));
2293
2294        ICUResourceBundle rb = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME,"de_DE");
2295        DateFormatSymbols sym = new DateFormatSymbols(rb, Locale.GERMANY);
2296        DateFormatSymbols sym2 = (DateFormatSymbols)sym.clone();
2297        if (sym.hashCode() != sym2.hashCode()) {
2298            errln("fail, date format symbols hashcode not equal");
2299        }
2300        if (!sym.equals(sym2)) {
2301            errln("fail, date format symbols not equal");
2302        }
2303
2304        Locale foo = new Locale("fu", "FU", "BAR");
2305        rb = null;
2306        sym = new DateFormatSymbols(GregorianCalendar.class, foo);
2307        sym.equals(null);
2308
2309        sym = new ChineseDateFormatSymbols();
2310        sym = new ChineseDateFormatSymbols(new Locale("en_US"));
2311        try{
2312            sym = new ChineseDateFormatSymbols(null, new Locale("en_US"));
2313            errln("ChineseDateFormatSymbols(Calender, Locale) was suppose to return a null " +
2314                    "pointer exception for a null paramater.");
2315        } catch(Exception e){}
2316        sym = new ChineseDateFormatSymbols(new ChineseCalendar(), new Locale("en_US"));
2317        try{
2318            sym = new ChineseDateFormatSymbols(null, new ULocale("en_US"));
2319            errln("ChineseDateFormatSymbols(Calender, ULocale) was suppose to return a null " +
2320                    "pointer exception for a null paramater.");
2321        } catch(Exception e){}
2322        sym = new ChineseDateFormatSymbols(new ChineseCalendar(), foo);
2323        // cover new ChineseDateFormatSymbols(Calendar, ULocale)
2324        ChineseCalendar ccal = new ChineseCalendar();
2325        sym = new ChineseDateFormatSymbols(ccal, ULocale.CHINA); //gclsh1 add
2326
2327        StringBuffer buf = new StringBuffer();
2328        FieldPosition pos = new FieldPosition(0);
2329
2330        f.format((Object)cal, buf, pos);
2331        f.format((Object)now, buf, pos);
2332        f.format((Object)new Long(now.getTime()), buf, pos);
2333        try {
2334            f.format((Object)"Howdy", buf, pos);
2335        }
2336        catch (Exception e) {
2337        }
2338
2339        NumberFormat nf = f.getNumberFormat();
2340        f.setNumberFormat(nf);
2341
2342        boolean lenient = f.isLenient();
2343        f.setLenient(lenient);
2344
2345        ULocale uloc = f.getLocale(ULocale.ACTUAL_LOCALE);
2346
2347        DateFormat sdfmt = new SimpleDateFormat();
2348
2349        if (f.hashCode() != f.hashCode()) {
2350            errln("hashCode is not stable");
2351        }
2352        if (!f.equals(f)) {
2353            errln("f != f");
2354        }
2355        if (f.equals(null)) {
2356            errln("f should not equal null");
2357        }
2358        if (f.equals(sdfmt)) {
2359            errln("A time instance shouldn't equal a default date format");
2360        }
2361
2362        Date d;
2363        {
2364            ChineseDateFormat fmt = new ChineseDateFormat("yymm", Locale.US);
2365            try {
2366                fmt.parse("2"); // fewer symbols than required 2
2367                errln("whoops");
2368            }
2369            catch (ParseException e) {
2370                logln("ok");
2371            }
2372
2373            try {
2374                fmt.parse("2255"); // should succeed with obeycount
2375                logln("ok");
2376            }
2377            catch (ParseException e) {
2378                errln("whoops");
2379            }
2380
2381            try {
2382                fmt.parse("ni hao"); // not a number, should fail
2383                errln("whoops ni hao");
2384            }
2385            catch (ParseException e) {
2386                logln("ok ni hao");
2387            }
2388        }
2389        {
2390            Calendar xcal = new GregorianCalendar();
2391            xcal.set(Calendar.HOUR_OF_DAY, 0);
2392            DateFormat fmt = new SimpleDateFormat("k");
2393            StringBuffer xbuf = new StringBuffer();
2394            FieldPosition fpos = new FieldPosition(Calendar.HOUR_OF_DAY);
2395            fmt.format(xcal, xbuf, fpos);
2396            try {
2397                fmt.parse(xbuf.toString());
2398                logln("ok");
2399
2400                xbuf.setLength(0);
2401                xcal.set(Calendar.HOUR_OF_DAY, 25);
2402                fmt.format(xcal, xbuf, fpos);
2403                Date d2 = fmt.parse(xbuf.toString());
2404                logln("ok again - d2=" + d2);
2405            }
2406            catch (ParseException e) {
2407                errln("whoops");
2408            }
2409        }
2410
2411        {
2412            // cover gmt+hh:mm
2413            DateFormat fmt = new SimpleDateFormat("MM/dd/yy z");
2414            try {
2415                d = fmt.parse("07/10/53 GMT+10:00");
2416                logln("ok : d = " + d);
2417            }
2418            catch (ParseException e) {
2419                errln("Parse of 07/10/53 GMT+10:00 for pattern MM/dd/yy z");
2420            }
2421
2422            // cover invalid separator after GMT
2423            {
2424                ParsePosition pp = new ParsePosition(0);
2425                String text = "07/10/53 GMT=10:00";
2426                d = fmt.parse(text, pp);
2427                if(pp.getIndex()!=12){
2428                    errln("Parse of 07/10/53 GMT=10:00 for pattern MM/dd/yy z");
2429                }
2430                logln("Parsing of the text stopped at pos: " + pp.getIndex() + " as expected and length is "+text.length());
2431            }
2432
2433            // cover bad text after GMT+.
2434            try {
2435                fmt.parse("07/10/53 GMT+blecch");
2436                logln("ok GMT+blecch");
2437            }
2438            catch (ParseException e) {
2439                errln("whoops GMT+blecch");
2440            }
2441
2442            // cover bad text after GMT+hh:.
2443            try {
2444                fmt.parse("07/10/53 GMT+07:blecch");
2445                logln("ok GMT+xx:blecch");
2446            }
2447            catch (ParseException e) {
2448                errln("whoops GMT+xx:blecch");
2449            }
2450
2451            // cover no ':' GMT+#, # < 24 (hh)
2452            try {
2453                d = fmt.parse("07/10/53 GMT+07");
2454                logln("ok GMT+07");
2455            }
2456            catch (ParseException e) {
2457                errln("Parse of 07/10/53 GMT+07 for pattern MM/dd/yy z");
2458            }
2459
2460            // cover no ':' GMT+#, # > 24 (hhmm)
2461            try {
2462                d = fmt.parse("07/10/53 GMT+0730");
2463                logln("ok");
2464            }
2465            catch (ParseException e) {
2466                errln("Parse of 07/10/53 GMT+0730 for pattern MM/dd/yy z");
2467            }
2468
2469            // cover GMT+#, # with second field
2470            try {
2471                d = fmt.parse("07/10/53 GMT+07:30:15");
2472                logln("ok GMT+07:30:15");
2473            }
2474            catch (ParseException e) {
2475                errln("Parse of 07/10/53 GMT+07:30:15 for pattern MM/dd/yy z");
2476            }
2477
2478            // cover no ':' GMT+#, # with second field, no leading zero
2479            try {
2480                d = fmt.parse("07/10/53 GMT+73015");
2481                logln("ok GMT+73015");
2482            }
2483            catch (ParseException e) {
2484                errln("Parse of 07/10/53 GMT+73015 for pattern MM/dd/yy z");
2485            }
2486
2487            // cover no ':' GMT+#, # with 1 digit second field
2488            try {
2489                d = fmt.parse("07/10/53 GMT+07300");
2490                logln("ok GMT+07300");
2491            }
2492            catch (ParseException e) {
2493                errln("Parse of 07/10/53 GMT+07300 for pattern MM/dd/yy z");
2494            }
2495
2496            // cover raw digits with no leading sign (bad RFC822)
2497            try {
2498                d = fmt.parse("07/10/53 07");
2499                errln("Parse of 07/10/53 07 for pattern MM/dd/yy z passed!");
2500            }
2501            catch (ParseException e) {
2502                logln("ok");
2503            }
2504
2505            // cover raw digits (RFC822)
2506            try {
2507                d = fmt.parse("07/10/53 +07");
2508                logln("ok");
2509            }
2510            catch (ParseException e) {
2511                errln("Parse of 07/10/53 +07 for pattern MM/dd/yy z failed");
2512            }
2513
2514            // cover raw digits (RFC822)
2515            try {
2516                d = fmt.parse("07/10/53 -0730");
2517                logln("ok");
2518            }
2519            catch (ParseException e) {
2520                errln("Parse of 07/10/53 -00730 for pattern MM/dd/yy z failed");
2521            }
2522
2523            // cover raw digits (RFC822) in DST
2524            try {
2525                fmt.setTimeZone(TimeZone.getTimeZone("PDT"));
2526                d = fmt.parse("07/10/53 -0730");
2527                logln("ok");
2528            }
2529            catch (ParseException e) {
2530                errln("Parse of 07/10/53 -0730 for pattern MM/dd/yy z failed");
2531            }
2532        }
2533
2534        // TODO: revisit toLocalizedPattern
2535        if (false) {
2536            SimpleDateFormat fmt = new SimpleDateFormat("aabbcc");
2537            try {
2538                String pat = fmt.toLocalizedPattern();
2539                errln("whoops, shouldn't have been able to localize aabbcc");
2540            }
2541            catch (IllegalArgumentException e) {
2542                logln("aabbcc localize ok");
2543            }
2544        }
2545
2546        {
2547            SimpleDateFormat fmt = new SimpleDateFormat("'aabbcc");
2548            try {
2549                fmt.toLocalizedPattern();
2550                errln("whoops, localize unclosed quote");
2551            }
2552            catch (IllegalArgumentException e) {
2553                logln("localize unclosed quote ok");
2554            }
2555        }
2556        {
2557            SimpleDateFormat fmt = new SimpleDateFormat("MM/dd/yy z");
2558            String text = "08/15/58 DBDY"; // bogus time zone
2559            try {
2560                fmt.parse(text);
2561                errln("recognized bogus time zone DBDY");
2562            }
2563            catch (ParseException e) {
2564                logln("time zone ex ok");
2565            }
2566        }
2567
2568        {
2569            // force fallback to default timezone when fmt timezone
2570            // is not named
2571            SimpleDateFormat fmt = new SimpleDateFormat("MM/dd/yy z");
2572            // force fallback to default time zone, still fails
2573            fmt.setTimeZone(TimeZone.getTimeZone("GMT+0147")); // not in equivalency group
2574            String text = "08/15/58 DBDY";
2575            try {
2576                fmt.parse(text);
2577                errln("Parse of 07/10/53 DBDY for pattern MM/dd/yy z passed");
2578            }
2579            catch (ParseException e) {
2580                logln("time zone ex2 ok");
2581            }
2582
2583            // force success on fallback
2584            text = "08/15/58 " + TimeZone.getDefault().getDisplayName(true, TimeZone.SHORT);
2585            try {
2586                fmt.parse(text);
2587                logln("found default tz");
2588            }
2589            catch (ParseException e) {
2590                errln("whoops, got parse exception");
2591            }
2592        }
2593
2594        {
2595            // force fallback to symbols list of timezones when neither
2596            // fmt and default timezone is named
2597            SimpleDateFormat fmt = new SimpleDateFormat("MM/dd/yy z");
2598            TimeZone oldtz = TimeZone.getDefault();
2599            TimeZone newtz = TimeZone.getTimeZone("GMT+0137"); // nonstandard tz
2600            fmt.setTimeZone(newtz);
2601            TimeZone.setDefault(newtz); // todo: fix security issue
2602
2603            // fallback to symbol list, but fail
2604            String text = "08/15/58 DBDY"; // try to parse the bogus time zone
2605            try {
2606                fmt.parse(text);
2607                errln("Parse of 07/10/53 DBDY for pattern MM/dd/yy z passed");
2608            }
2609            catch (ParseException e) {
2610                logln("time zone ex3 ok");
2611            }
2612            catch (Exception e) {
2613                // hmmm... this shouldn't happen.  don't want to exit this
2614                // fn with timezone improperly set, so just in case
2615                TimeZone.setDefault(oldtz);
2616                throw new IllegalStateException(e.getMessage());
2617            }
2618        }
2619
2620        {
2621            //cover getAvailableULocales
2622            final ULocale[] locales = DateFormat.getAvailableULocales();
2623            long count = locales.length;
2624            if (count==0) {
2625                errln(" got a empty list for getAvailableULocales");
2626            }else{
2627                logln("" + count + " available ulocales");
2628            }
2629        }
2630
2631        {
2632            //cover DateFormatSymbols.getDateFormatBundle
2633            cal = new GregorianCalendar();
2634            Locale loc = Locale.getDefault();
2635            DateFormatSymbols mysym = new DateFormatSymbols(cal, loc);
2636            if (mysym == null)
2637                errln("FAIL: constructs DateFormatSymbols with calendar and locale failed");
2638
2639            uloc = ULocale.getDefault();
2640            // These APIs are obsolete and return null
2641            ResourceBundle resb = DateFormatSymbols.getDateFormatBundle(cal, loc);
2642            ResourceBundle resb2 = DateFormatSymbols.getDateFormatBundle(cal, uloc);
2643            ResourceBundle resb3 = DateFormatSymbols.getDateFormatBundle(cal.getClass(), loc);
2644            ResourceBundle resb4 = DateFormatSymbols.getDateFormatBundle(cal.getClass(), uloc);
2645
2646            if (resb != null) {
2647                logln("resb is not null");
2648            }
2649            if (resb2 != null) {
2650                logln("resb2 is not null");
2651            }
2652            if (resb3 != null) {
2653                logln("resb3 is not null");
2654            }
2655            if (resb4 != null) {
2656                logln("resb4 is not null");
2657            }
2658        }
2659
2660        {
2661            //cover DateFormatSymbols.getInstance
2662            DateFormatSymbols datsym1 = DateFormatSymbols.getInstance();
2663            DateFormatSymbols datsym2 = new DateFormatSymbols();
2664            if (!datsym1.equals(datsym2)) {
2665                errln("FAIL: DateFormatSymbols returned by getInstance()" +
2666                        "does not match new DateFormatSymbols().");
2667            }
2668            datsym1 = DateFormatSymbols.getInstance(Locale.JAPAN);
2669            datsym2 = DateFormatSymbols.getInstance(ULocale.JAPAN);
2670            if (!datsym1.equals(datsym2)) {
2671                errln("FAIL: DateFormatSymbols returned by getInstance(Locale.JAPAN)" +
2672                        "does not match the one returned by getInstance(ULocale.JAPAN).");
2673            }
2674        }
2675        {
2676            //cover DateFormatSymbols.getAvailableLocales/getAvailableULocales
2677            Locale[] allLocales = DateFormatSymbols.getAvailableLocales();
2678            if (allLocales.length == 0) {
2679                errln("FAIL: Got a empty list for DateFormatSymbols.getAvailableLocales");
2680            } else {
2681                logln("PASS: " + allLocales.length +
2682                        " available locales returned by DateFormatSymbols.getAvailableLocales");
2683            }
2684
2685            ULocale[] allULocales = DateFormatSymbols.getAvailableULocales();
2686            if (allULocales.length == 0) {
2687                errln("FAIL: Got a empty list for DateFormatSymbols.getAvailableLocales");
2688            } else {
2689                logln("PASS: " + allULocales.length +
2690                        " available locales returned by DateFormatSymbols.getAvailableULocales");
2691            }
2692        }
2693    }
2694
2695    public void TestStandAloneMonths()
2696    {
2697        String EN_DATA[] = {
2698            "yyyy MM dd HH:mm:ss",
2699
2700            "yyyy LLLL dd H:mm:ss", "fp", "2004 03 10 16:36:31", "2004 March 10 16:36:31", "2004 03 10 16:36:31",
2701            "yyyy LLL dd H:mm:ss",  "fp", "2004 03 10 16:36:31", "2004 Mar 10 16:36:31",   "2004 03 10 16:36:31",
2702            "yyyy LLLL dd H:mm:ss", "F",  "2004 03 10 16:36:31", "2004 March 10 16:36:31",
2703            "yyyy LLL dd H:mm:ss",  "pf", "2004 Mar 10 16:36:31", "2004 03 10 16:36:31", "2004 Mar 10 16:36:31",
2704
2705            "LLLL", "fp", "1970 01 01 0:00:00", "January",   "1970 01 01 0:00:00",
2706            "LLLL", "fp", "1970 02 01 0:00:00", "February",  "1970 02 01 0:00:00",
2707            "LLLL", "fp", "1970 03 01 0:00:00", "March",     "1970 03 01 0:00:00",
2708            "LLLL", "fp", "1970 04 01 0:00:00", "April",     "1970 04 01 0:00:00",
2709            "LLLL", "fp", "1970 05 01 0:00:00", "May",       "1970 05 01 0:00:00",
2710            "LLLL", "fp", "1970 06 01 0:00:00", "June",      "1970 06 01 0:00:00",
2711            "LLLL", "fp", "1970 07 01 0:00:00", "July",      "1970 07 01 0:00:00",
2712            "LLLL", "fp", "1970 08 01 0:00:00", "August",    "1970 08 01 0:00:00",
2713            "LLLL", "fp", "1970 09 01 0:00:00", "September", "1970 09 01 0:00:00",
2714            "LLLL", "fp", "1970 10 01 0:00:00", "October",   "1970 10 01 0:00:00",
2715            "LLLL", "fp", "1970 11 01 0:00:00", "November",  "1970 11 01 0:00:00",
2716            "LLLL", "fp", "1970 12 01 0:00:00", "December",  "1970 12 01 0:00:00",
2717
2718            "LLL", "fp", "1970 01 01 0:00:00", "Jan", "1970 01 01 0:00:00",
2719            "LLL", "fp", "1970 02 01 0:00:00", "Feb", "1970 02 01 0:00:00",
2720            "LLL", "fp", "1970 03 01 0:00:00", "Mar", "1970 03 01 0:00:00",
2721            "LLL", "fp", "1970 04 01 0:00:00", "Apr", "1970 04 01 0:00:00",
2722            "LLL", "fp", "1970 05 01 0:00:00", "May", "1970 05 01 0:00:00",
2723            "LLL", "fp", "1970 06 01 0:00:00", "Jun", "1970 06 01 0:00:00",
2724            "LLL", "fp", "1970 07 01 0:00:00", "Jul", "1970 07 01 0:00:00",
2725            "LLL", "fp", "1970 08 01 0:00:00", "Aug", "1970 08 01 0:00:00",
2726            "LLL", "fp", "1970 09 01 0:00:00", "Sep", "1970 09 01 0:00:00",
2727            "LLL", "fp", "1970 10 01 0:00:00", "Oct", "1970 10 01 0:00:00",
2728            "LLL", "fp", "1970 11 01 0:00:00", "Nov", "1970 11 01 0:00:00",
2729            "LLL", "fp", "1970 12 01 0:00:00", "Dec", "1970 12 01 0:00:00",
2730        };
2731
2732        String CS_DATA[] = {
2733            "yyyy MM dd HH:mm:ss",
2734
2735            "yyyy LLLL dd H:mm:ss", "fp", "2004 04 10 16:36:31", "2004 duben 10 16:36:31", "2004 04 10 16:36:31",
2736            "yyyy MMMM dd H:mm:ss", "fp", "2004 04 10 16:36:31", "2004 dubna 10 16:36:31", "2004 04 10 16:36:31",
2737            "yyyy LLL dd H:mm:ss",  "fp", "2004 04 10 16:36:31", "2004 dub 10 16:36:31",   "2004 04 10 16:36:31",
2738            "yyyy LLLL dd H:mm:ss", "F",  "2004 04 10 16:36:31", "2004 duben 10 16:36:31",
2739            "yyyy MMMM dd H:mm:ss", "F",  "2004 04 10 16:36:31", "2004 dubna 10 16:36:31",
2740            "yyyy LLLL dd H:mm:ss", "pf", "2004 duben 10 16:36:31", "2004 04 10 16:36:31", "2004 duben 10 16:36:31",
2741            "yyyy MMMM dd H:mm:ss", "pf", "2004 dubna 10 16:36:31", "2004 04 10 16:36:31", "2004 dubna 10 16:36:31",
2742
2743            "LLLL", "fp", "1970 01 01 0:00:00", "leden",               "1970 01 01 0:00:00",
2744            "LLLL", "fp", "1970 02 01 0:00:00", "\u00FAnor",           "1970 02 01 0:00:00",
2745            "LLLL", "fp", "1970 03 01 0:00:00", "b\u0159ezen",         "1970 03 01 0:00:00",
2746            "LLLL", "fp", "1970 04 01 0:00:00", "duben",               "1970 04 01 0:00:00",
2747            "LLLL", "fp", "1970 05 01 0:00:00", "kv\u011Bten",         "1970 05 01 0:00:00",
2748            "LLLL", "fp", "1970 06 01 0:00:00", "\u010Derven",         "1970 06 01 0:00:00",
2749            "LLLL", "fp", "1970 07 01 0:00:00", "\u010Dervenec",       "1970 07 01 0:00:00",
2750            "LLLL", "fp", "1970 08 01 0:00:00", "srpen",               "1970 08 01 0:00:00",
2751            "LLLL", "fp", "1970 09 01 0:00:00", "z\u00E1\u0159\u00ED", "1970 09 01 0:00:00",
2752            "LLLL", "fp", "1970 10 01 0:00:00", "\u0159\u00EDjen",     "1970 10 01 0:00:00",
2753            "LLLL", "fp", "1970 11 01 0:00:00", "listopad",            "1970 11 01 0:00:00",
2754            "LLLL", "fp", "1970 12 01 0:00:00", "prosinec",            "1970 12 01 0:00:00",
2755
2756            "LLL", "fp", "1970 01 01 0:00:00", "led",                  "1970 01 01 0:00:00",
2757            "LLL", "fp", "1970 02 01 0:00:00", "\u00FAno",             "1970 02 01 0:00:00",
2758            "LLL", "fp", "1970 03 01 0:00:00", "b\u0159e",             "1970 03 01 0:00:00",
2759            "LLL", "fp", "1970 04 01 0:00:00", "dub",                  "1970 04 01 0:00:00",
2760            "LLL", "fp", "1970 05 01 0:00:00", "kv\u011B",             "1970 05 01 0:00:00",
2761            "LLL", "fp", "1970 06 01 0:00:00", "\u010Dvn",             "1970 06 01 0:00:00",
2762            "LLL", "fp", "1970 07 01 0:00:00", "\u010Dvc",             "1970 07 01 0:00:00",
2763            "LLL", "fp", "1970 08 01 0:00:00", "srp",                  "1970 08 01 0:00:00",
2764            "LLL", "fp", "1970 09 01 0:00:00", "z\u00E1\u0159",        "1970 09 01 0:00:00",
2765            "LLL", "fp", "1970 10 01 0:00:00", "\u0159\u00EDj",        "1970 10 01 0:00:00",
2766            "LLL", "fp", "1970 11 01 0:00:00", "lis",                  "1970 11 01 0:00:00",
2767            "LLL", "fp", "1970 12 01 0:00:00", "pro",                  "1970 12 01 0:00:00",
2768        };
2769
2770        expect(EN_DATA, new Locale("en", "", ""));
2771        expect(CS_DATA, new Locale("cs", "", ""));
2772    }
2773
2774    public void TestStandAloneDays()
2775    {
2776        String EN_DATA[] = {
2777            "yyyy MM dd HH:mm:ss",
2778
2779            "cccc", "fp", "1970 01 04 0:00:00", "Sunday",    "1970 01 04 0:00:00",
2780            "cccc", "fp", "1970 01 05 0:00:00", "Monday",    "1970 01 05 0:00:00",
2781            "cccc", "fp", "1970 01 06 0:00:00", "Tuesday",   "1970 01 06 0:00:00",
2782            "cccc", "fp", "1970 01 07 0:00:00", "Wednesday", "1970 01 07 0:00:00",
2783            "cccc", "fp", "1970 01 01 0:00:00", "Thursday",  "1970 01 01 0:00:00",
2784            "cccc", "fp", "1970 01 02 0:00:00", "Friday",    "1970 01 02 0:00:00",
2785            "cccc", "fp", "1970 01 03 0:00:00", "Saturday",  "1970 01 03 0:00:00",
2786
2787            "ccc", "fp", "1970 01 04 0:00:00", "Sun", "1970 01 04 0:00:00",
2788            "ccc", "fp", "1970 01 05 0:00:00", "Mon", "1970 01 05 0:00:00",
2789            "ccc", "fp", "1970 01 06 0:00:00", "Tue", "1970 01 06 0:00:00",
2790            "ccc", "fp", "1970 01 07 0:00:00", "Wed", "1970 01 07 0:00:00",
2791            "ccc", "fp", "1970 01 01 0:00:00", "Thu", "1970 01 01 0:00:00",
2792            "ccc", "fp", "1970 01 02 0:00:00", "Fri", "1970 01 02 0:00:00",
2793            "ccc", "fp", "1970 01 03 0:00:00", "Sat", "1970 01 03 0:00:00",
2794        };
2795
2796        String CS_DATA[] = {
2797            "yyyy MM dd HH:mm:ss",
2798
2799            "cccc", "fp", "1970 01 04 0:00:00", "ned\u011Ble",       "1970 01 04 0:00:00",
2800            "cccc", "fp", "1970 01 05 0:00:00", "pond\u011Bl\u00ED", "1970 01 05 0:00:00",
2801            "cccc", "fp", "1970 01 06 0:00:00", "\u00FAter\u00FD",   "1970 01 06 0:00:00",
2802            "cccc", "fp", "1970 01 07 0:00:00", "st\u0159eda",       "1970 01 07 0:00:00",
2803            "cccc", "fp", "1970 01 01 0:00:00", "\u010Dtvrtek",      "1970 01 01 0:00:00",
2804            "cccc", "fp", "1970 01 02 0:00:00", "p\u00E1tek",        "1970 01 02 0:00:00",
2805            "cccc", "fp", "1970 01 03 0:00:00", "sobota",            "1970 01 03 0:00:00",
2806
2807            "ccc", "fp", "1970 01 04 0:00:00", "ne",      "1970 01 04 0:00:00",
2808            "ccc", "fp", "1970 01 05 0:00:00", "po",      "1970 01 05 0:00:00",
2809            "ccc", "fp", "1970 01 06 0:00:00", "\u00FAt", "1970 01 06 0:00:00",
2810            "ccc", "fp", "1970 01 07 0:00:00", "st",      "1970 01 07 0:00:00",
2811            "ccc", "fp", "1970 01 01 0:00:00", "\u010Dt", "1970 01 01 0:00:00",
2812            "ccc", "fp", "1970 01 02 0:00:00", "p\u00E1", "1970 01 02 0:00:00",
2813            "ccc", "fp", "1970 01 03 0:00:00", "so",      "1970 01 03 0:00:00",
2814        };
2815
2816        expect(EN_DATA, new Locale("en", "", ""));
2817        expect(CS_DATA, new Locale("cs", "", ""));
2818    }
2819
2820    public void TestShortDays()
2821    {
2822        String EN_DATA[] = {
2823            "yyyy MM dd HH:mm:ss",
2824
2825            "EEEEEE, MMM d y", "fp", "2013 01 13 0:00:00", "Su, Jan 13 2013", "2013 01 13 0:00:00",
2826            "EEEEEE, MMM d y", "fp", "2013 01 16 0:00:00", "We, Jan 16 2013", "2013 01 16 0:00:00",
2827            "EEEEEE d",        "fp", "1970 01 17 0:00:00", "Sa 17",           "1970 01 17 0:00:00",
2828            "cccccc d",        "fp", "1970 01 17 0:00:00", "Sa 17",           "1970 01 17 0:00:00",
2829            "cccccc",          "fp", "1970 01 03 0:00:00", "Sa",              "1970 01 03 0:00:00",
2830        };
2831
2832        String SV_DATA[] = {
2833            "yyyy MM dd HH:mm:ss",
2834
2835            "EEEEEE d MMM y",  "fp", "2013 01 13 0:00:00", "s\u00F6 13 jan. 2013", "2013 01 13 0:00:00",
2836            "EEEEEE d MMM y",  "fp", "2013 01 16 0:00:00", "on 16 jan. 2013",      "2013 01 16 0:00:00",
2837            "EEEEEE d",        "fp", "1970 01 17 0:00:00", "l\u00F6 17",          "1970 01 17 0:00:00",
2838            "cccccc d",        "fp", "1970 01 17 0:00:00", "L\u00F6 17",          "1970 01 17 0:00:00",
2839            "cccccc",          "fp", "1970 01 03 0:00:00", "L\u00F6",             "1970 01 03 0:00:00",
2840        };
2841
2842        expect(EN_DATA, new Locale("en", "", ""));
2843        expect(SV_DATA, new Locale("sv", "", ""));
2844    }
2845
2846    public void TestNarrowNames()
2847    {
2848        String EN_DATA[] = {
2849                "yyyy MM dd HH:mm:ss",
2850
2851                "yyyy MMMMM dd H:mm:ss", "2004 03 10 16:36:31", "2004 M 10 16:36:31",
2852                "yyyy LLLLL dd H:mm:ss",  "2004 03 10 16:36:31", "2004 M 10 16:36:31",
2853
2854                "MMMMM", "1970 01 01 0:00:00", "J",
2855                "MMMMM", "1970 02 01 0:00:00", "F",
2856                "MMMMM", "1970 03 01 0:00:00", "M",
2857                "MMMMM", "1970 04 01 0:00:00", "A",
2858                "MMMMM", "1970 05 01 0:00:00", "M",
2859                "MMMMM", "1970 06 01 0:00:00", "J",
2860                "MMMMM", "1970 07 01 0:00:00", "J",
2861                "MMMMM", "1970 08 01 0:00:00", "A",
2862                "MMMMM", "1970 09 01 0:00:00", "S",
2863                "MMMMM", "1970 10 01 0:00:00", "O",
2864                "MMMMM", "1970 11 01 0:00:00", "N",
2865                "MMMMM", "1970 12 01 0:00:00", "D",
2866
2867                "LLLLL", "1970 01 01 0:00:00", "J",
2868                "LLLLL", "1970 02 01 0:00:00", "F",
2869                "LLLLL", "1970 03 01 0:00:00", "M",
2870                "LLLLL", "1970 04 01 0:00:00", "A",
2871                "LLLLL", "1970 05 01 0:00:00", "M",
2872                "LLLLL", "1970 06 01 0:00:00", "J",
2873                "LLLLL", "1970 07 01 0:00:00", "J",
2874                "LLLLL", "1970 08 01 0:00:00", "A",
2875                "LLLLL", "1970 09 01 0:00:00", "S",
2876                "LLLLL", "1970 10 01 0:00:00", "O",
2877                "LLLLL", "1970 11 01 0:00:00", "N",
2878                "LLLLL", "1970 12 01 0:00:00", "D",
2879
2880                "EEEEE", "1970 01 04 0:00:00", "S",
2881                "EEEEE", "1970 01 05 0:00:00", "M",
2882                "EEEEE", "1970 01 06 0:00:00", "T",
2883                "EEEEE", "1970 01 07 0:00:00", "W",
2884                "EEEEE", "1970 01 01 0:00:00", "T",
2885                "EEEEE", "1970 01 02 0:00:00", "F",
2886                "EEEEE", "1970 01 03 0:00:00", "S",
2887
2888                "ccccc", "1970 01 04 0:00:00", "S",
2889                "ccccc", "1970 01 05 0:00:00", "M",
2890                "ccccc", "1970 01 06 0:00:00", "T",
2891                "ccccc", "1970 01 07 0:00:00", "W",
2892                "ccccc", "1970 01 01 0:00:00", "T",
2893                "ccccc", "1970 01 02 0:00:00", "F",
2894                "ccccc", "1970 01 03 0:00:00", "S",
2895
2896                "h:mm a",     "2015 01 01 10:00:00", "10:00 AM",
2897                "h:mm a",     "2015 01 01 22:00:00", "10:00 PM",
2898                "h:mm aaaaa", "2015 01 01 10:00:00", "10:00 a",
2899                "h:mm aaaaa", "2015 01 01 22:00:00", "10:00 p",
2900            };
2901
2902            String CS_DATA[] = {
2903                "yyyy MM dd HH:mm:ss",
2904
2905                "yyyy LLLLL dd H:mm:ss", "2004 04 10 16:36:31", "2004 4 10 16:36:31",
2906                "yyyy MMMMM dd H:mm:ss", "2004 04 10 16:36:31", "2004 4 10 16:36:31",
2907
2908                "MMMMM", "1970 01 01 0:00:00", "1",
2909                "MMMMM", "1970 02 01 0:00:00", "2",
2910                "MMMMM", "1970 03 01 0:00:00", "3",
2911                "MMMMM", "1970 04 01 0:00:00", "4",
2912                "MMMMM", "1970 05 01 0:00:00", "5",
2913                "MMMMM", "1970 06 01 0:00:00", "6",
2914                "MMMMM", "1970 07 01 0:00:00", "7",
2915                "MMMMM", "1970 08 01 0:00:00", "8",
2916                "MMMMM", "1970 09 01 0:00:00", "9",
2917                "MMMMM", "1970 10 01 0:00:00", "10",
2918                "MMMMM", "1970 11 01 0:00:00", "11",
2919                "MMMMM", "1970 12 01 0:00:00", "12",
2920
2921                "LLLLL", "1970 01 01 0:00:00", "1",
2922                "LLLLL", "1970 02 01 0:00:00", "2",
2923                "LLLLL", "1970 03 01 0:00:00", "3",
2924                "LLLLL", "1970 04 01 0:00:00", "4",
2925                "LLLLL", "1970 05 01 0:00:00", "5",
2926                "LLLLL", "1970 06 01 0:00:00", "6",
2927                "LLLLL", "1970 07 01 0:00:00", "7",
2928                "LLLLL", "1970 08 01 0:00:00", "8",
2929                "LLLLL", "1970 09 01 0:00:00", "9",
2930                "LLLLL", "1970 10 01 0:00:00", "10",
2931                "LLLLL", "1970 11 01 0:00:00", "11",
2932                "LLLLL", "1970 12 01 0:00:00", "12",
2933
2934                "EEEEE", "1970 01 04 0:00:00", "N",
2935                "EEEEE", "1970 01 05 0:00:00", "P",
2936                "EEEEE", "1970 01 06 0:00:00", "\u00DA",
2937                "EEEEE", "1970 01 07 0:00:00", "S",
2938                "EEEEE", "1970 01 01 0:00:00", "\u010C",
2939                "EEEEE", "1970 01 02 0:00:00", "P",
2940                "EEEEE", "1970 01 03 0:00:00", "S",
2941
2942                "ccccc", "1970 01 04 0:00:00", "N",
2943                "ccccc", "1970 01 05 0:00:00", "P",
2944                "ccccc", "1970 01 06 0:00:00", "\u00DA",
2945                "ccccc", "1970 01 07 0:00:00", "S",
2946                "ccccc", "1970 01 01 0:00:00", "\u010C",
2947                "ccccc", "1970 01 02 0:00:00", "P",
2948                "ccccc", "1970 01 03 0:00:00", "S",
2949
2950                "h:mm a",     "2015 01 01 10:00:00", "10:00 dopoledne",
2951                "h:mm a",     "2015 01 01 22:00:00", "10:00 odpoledne",
2952                "h:mm aaaaa", "2015 01 01 10:00:00", "10:00 dop.",
2953                "h:mm aaaaa", "2015 01 01 22:00:00", "10:00 odp.",
2954            };
2955
2956            String CA_DATA[] = {
2957                "yyyy MM dd HH:mm:ss",
2958
2959                "h:mm a",     "2015 01 01 10:00:00", "10:00 a. m.",
2960                "h:mm a",     "2015 01 01 22:00:00", "10:00 p. m.",
2961                "h:mm aaaaa", "2015 01 01 10:00:00", "10:00 a.m.",
2962                "h:mm aaaaa", "2015 01 01 22:00:00", "10:00 p.m.",
2963            };
2964
2965            expectFormat(EN_DATA, new Locale("en", "", ""));
2966            expectFormat(CS_DATA, new Locale("cs", "", ""));
2967            expectFormat(CA_DATA, new Locale("ca", "", ""));
2968    }
2969
2970    public void TestEras()
2971    {
2972        String EN_DATA[] = {
2973            "yyyy MM dd",
2974
2975            "MMMM dd yyyy G",    "fp", "1951 07 17", "July 17 1951 AD",          "1951 07 17",
2976            "MMMM dd yyyy GG",   "fp", "1951 07 17", "July 17 1951 AD",          "1951 07 17",
2977            "MMMM dd yyyy GGG",  "fp", "1951 07 17", "July 17 1951 AD",          "1951 07 17",
2978            "MMMM dd yyyy GGGG", "fp", "1951 07 17", "July 17 1951 Anno Domini", "1951 07 17",
2979
2980            "MMMM dd yyyy G",    "fp", "-438 07 17", "July 17 0439 BC",            "-438 07 17",
2981            "MMMM dd yyyy GG",   "fp", "-438 07 17", "July 17 0439 BC",            "-438 07 17",
2982            "MMMM dd yyyy GGG",  "fp", "-438 07 17", "July 17 0439 BC",            "-438 07 17",
2983            "MMMM dd yyyy GGGG", "fp", "-438 07 17", "July 17 0439 Before Christ", "-438 07 17",
2984       };
2985
2986        expect(EN_DATA, new Locale("en", "", ""));
2987    }
2988/*
2989    public void TestQuarters()
2990    {
2991        String EN_DATA[] = {
2992            "yyyy MM dd",
2993
2994            "Q",    "fp", "1970 01 01", "1",           "1970 01 01",
2995            "QQ",   "fp", "1970 04 01", "02",          "1970 04 01",
2996            "QQQ",  "fp", "1970 07 01", "Q3",          "1970 07 01",
2997            "QQQQ", "fp", "1970 10 01", "4th quarter", "1970 10 01",
2998
2999            "q",    "fp", "1970 01 01", "1",           "1970 01 01",
3000            "qq",   "fp", "1970 04 01", "02",          "1970 04 01",
3001            "qqq",  "fp", "1970 07 01", "Q3",          "1970 07 01",
3002            "qqqq", "fp", "1970 10 01", "4th quarter", "1970 10 01",
3003       };
3004
3005        expect(EN_DATA, new Locale("en", "", ""));
3006    }
3007*/
3008
3009    /**
3010     * Test DateFormat's parsing of default GMT variants.  See ticket#6135
3011     */
3012    public void TestGMTParsing() {
3013        String DATA[] = {
3014            "HH:mm:ss Z",
3015
3016            // pattern, input, expected output (in quotes)
3017            "HH:mm:ss Z",       "10:20:30 GMT+03:00",   "10:20:30 +0300",
3018            "HH:mm:ss Z",       "10:20:30 UT-02:00",    "10:20:30 -0200",
3019            "HH:mm:ss Z",       "10:20:30 GMT",         "10:20:30 +0000",
3020            "HH:mm:ss vvvv",    "10:20:30 UT+10:00",    "10:20:30 +1000",
3021            "HH:mm:ss zzzz",    "10:20:30 UTC",         "10:20:30 +0000",   // standalone "UTC"
3022            "ZZZZ HH:mm:ss",    "UT 10:20:30",          "10:20:30 +0000",
3023            "z HH:mm:ss",       "UT+0130 10:20:30",     "10:20:30 +0130",
3024            "z HH:mm:ss",       "UTC+0130 10:20:30",    "10:20:30 +0130",
3025            // Note: GMT-1100 no longer works because of the introduction of the short
3026            // localized GMT support. Previous implementation support this level of
3027            // leniency (no separator char in localized GMT format), but the new
3028            // implementation handles GMT-11 as the legitimate short localized GMT format
3029            // and stop at there. Otherwise, roundtrip would be broken.
3030            //"HH mm Z ss",       "10 20 GMT-1100 30",      "10:20:30 -1100",
3031            "HH mm Z ss",       "10 20 GMT-11 30",      "10:20:30 -1100",
3032            "HH:mm:ssZZZZZ",    "14:25:45Z",            "14:25:45 +0000",
3033            "HH:mm:ssZZZZZ",    "15:00:00-08:00",       "15:00:00 -0800",
3034        };
3035        expectParse(DATA, new Locale("en", "", ""));
3036    }
3037
3038    /**
3039     * Test parsing.  Input is an array that starts with the following
3040     * header:
3041     *
3042     * [0]   = pattern string to parse [i+2] with
3043     *
3044     * followed by test cases, each of which is 3 array elements:
3045     *
3046     * [i]   = pattern, or null to reuse prior pattern
3047     * [i+1] = input string
3048     * [i+2] = expected parse result (parsed with pattern [0])
3049     *
3050     * If expect parse failure, then [i+2] should be null.
3051     */
3052    void expectParse(String[] data, Locale loc) {
3053        Date FAIL = null;
3054        String FAIL_STR = "parse failure";
3055        int i = 0;
3056
3057        SimpleDateFormat fmt = new SimpleDateFormat("", loc);
3058        SimpleDateFormat ref = new SimpleDateFormat(data[i++], loc);
3059        SimpleDateFormat gotfmt = new SimpleDateFormat("G yyyy MM dd HH:mm:ss z", loc);
3060
3061        String currentPat = null;
3062        while (i<data.length) {
3063            String pattern  = data[i++];
3064            String input    = data[i++];
3065            String expected = data[i++];
3066
3067            if (pattern != null) {
3068                fmt.applyPattern(pattern);
3069                currentPat = pattern;
3070            }
3071            String gotstr = FAIL_STR;
3072            Date got;
3073            try {
3074                got = fmt.parse(input);
3075                gotstr = gotfmt.format(got);
3076            } catch (ParseException e1) {
3077                got = FAIL;
3078            }
3079
3080            Date exp = FAIL;
3081            String expstr = FAIL_STR;
3082            if (expected != null) {
3083                expstr = expected;
3084                try {
3085                    exp = ref.parse(expstr);
3086                } catch (ParseException e2) {
3087                    errln("FAIL: Internal test error");
3088                }
3089            }
3090
3091            if (got == exp || (got != null && got.equals(exp))) {
3092                logln("Ok: " + input + " x " +
3093                      currentPat + " => " + gotstr);
3094            } else {
3095                errln("FAIL: " + input + " x " +
3096                      currentPat + " => " + gotstr + ", expected " +
3097                      expstr);
3098            }
3099        }
3100    }
3101
3102    /**
3103     * Test formatting.  Input is an array of String that starts
3104     * with a single 'header' element
3105     *
3106     * [0]   = reference dateformat pattern string (ref)
3107     *
3108     * followed by test cases, each of which is 4 or 5 elements:
3109     *
3110     * [i]   = test dateformat pattern string (test), or null to reuse prior test pattern
3111     * [i+1] = data string A
3112     * [i+2] = data string B
3113     *
3114     * Formats a date, checks the result.
3115     *
3116     * Examples:
3117     * "y/M/d H:mm:ss.SSS", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.567"
3118     * -- ref.parse A, get t0
3119     * -- test.format t0, get r0
3120     * -- compare r0 to B, fail if not equal
3121     */
3122    void expectFormat(String[] data, Locale loc)
3123    {
3124        int i = 1;
3125        String currentPat = null;
3126        SimpleDateFormat ref = new SimpleDateFormat(data[0], loc);
3127
3128        while (i<data.length) {
3129            SimpleDateFormat fmt = new SimpleDateFormat("", loc);
3130            String pattern  = data[i++];
3131            if (pattern != null) {
3132                fmt.applyPattern(pattern);
3133                currentPat = pattern;
3134            }
3135
3136            String datestr = data[i++];
3137            String string = data[i++];
3138            Date date = null;
3139
3140            try {
3141                date = ref.parse(datestr);
3142            } catch (ParseException e) {
3143                errln("FAIL: Internal test error; can't parse " + datestr);
3144                continue;
3145            }
3146
3147            assertEquals("\"" + currentPat + "\".format(" + datestr + ")",
3148                         string,
3149                         fmt.format(date));
3150        }
3151    }
3152
3153    /**
3154     * Test formatting and parsing.  Input is an array of String that starts
3155     * with a single 'header' element
3156     *
3157     * [0]   = reference dateformat pattern string (ref)
3158     *
3159     * followed by test cases, each of which is 4 or 5 elements:
3160     *
3161     * [i]   = test dateformat pattern string (test), or null to reuse prior test pattern
3162     * [i+1] = control string, either "fp", "pf", or "F".
3163     * [i+2] = data string A
3164     * [i+3] = data string B
3165     * [i+4] = data string C (not present for 'F' control string)
3166     *
3167     * Note: the number of data strings depends on the control string.
3168     *
3169     * fp formats a date, checks the result, then parses the result and checks against a (possibly different) date
3170     * pf parses a string, checks the result, then formats the result and checks against a (possibly different) string
3171     * F is a shorthand for fp when the second date is the same as the first
3172     * P is a shorthand for pf when the second string is the same as the first
3173     *
3174     * Examples:
3175     * (fp) "y/M/d H:mm:ss.SS", "fp", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.56", "2004 03 10 16:36:31.560",
3176     * -- ref.parse A, get t0
3177     * -- test.format t0, get r0
3178     * -- compare r0 to B, fail if not equal
3179     * -- test.parse B, get t1
3180     * -- ref.parse C, get t2
3181     * -- compare t1 and t2, fail if not equal
3182     *
3183     * (F) "y/M/d H:mm:ss.SSS", "F", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.567"
3184     * -- ref.parse A, get t0
3185     * -- test.format t0, get r0
3186     * -- compare r0 to B, fail if not equal
3187     * -- test.parse B, get t1
3188     * -- compare t1 and t0, fail if not equal
3189     *
3190     * (pf) "y/M/d H:mm:ss.SSSS", "pf", "2004/3/10 16:36:31.5679", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.5670",
3191     * -- test.parse A, get t0
3192     * -- ref.parse B, get t1
3193     * -- compare t0 to t1, fail if not equal
3194     * -- test.format t1, get r0
3195     * -- compare r0 and C, fail if not equal
3196     *
3197     * (P) "y/M/d H:mm:ss.SSSS", "P", "2004/3/10 16:36:31.5679", "2004 03 10 16:36:31.567"",
3198     * -- test.parse A, get t0
3199     * -- ref.parse B, get t1
3200     * -- compare t0 to t1, fail if not equal
3201     * -- test.format t1, get r0
3202     * -- compare r0 and A, fail if not equal
3203     */
3204    void expect(String[] data, Locale loc) {
3205        expect(data, loc, false);
3206    }
3207
3208    void expect(String[] data, Locale loc, boolean parseAllTZStyles) {
3209        int i = 1;
3210        SimpleDateFormat univ = new SimpleDateFormat("EE G yyyy MM dd HH:mm:ss.SSS zzz", loc);
3211        String currentPat = null;
3212        SimpleDateFormat ref = new SimpleDateFormat(data[0], loc);
3213
3214        while (i<data.length) {
3215            SimpleDateFormat fmt = new SimpleDateFormat("", loc);
3216
3217            if (parseAllTZStyles) {
3218                TimeZoneFormat tzfmt = fmt.getTimeZoneFormat().cloneAsThawed();
3219                tzfmt.setDefaultParseOptions(EnumSet.of(ParseOption.ALL_STYLES)).freeze();
3220                fmt.setTimeZoneFormat(tzfmt);
3221            }
3222
3223            String pattern  = data[i++];
3224            if (pattern != null) {
3225                fmt.applyPattern(pattern);
3226                currentPat = pattern;
3227            }
3228
3229            String control = data[i++];
3230
3231            if (control.equals("fp") || control.equals("F")) {
3232                // 'f'
3233                String datestr = data[i++];
3234                String string = data[i++];
3235                String datestr2 = datestr;
3236                if (control.length() == 2) {
3237                    datestr2 = data[i++];
3238                }
3239                Date date = null;
3240                try {
3241                    date = ref.parse(datestr);
3242                } catch (ParseException e) {
3243                    errln("FAIL: Internal test error; can't parse " + datestr);
3244                    continue;
3245                }
3246                assertEquals("\"" + currentPat + "\".format(" + datestr + ")",
3247                             string,
3248                             fmt.format(date));
3249                // 'p'
3250                if (!datestr2.equals(datestr)) {
3251                    try {
3252                        date = ref.parse(datestr2);
3253                    } catch (ParseException e2) {
3254                        errln("FAIL: Internal test error; can't parse " + datestr2);
3255                        continue;
3256                    }
3257                }
3258                try {
3259                    Date parsedate = fmt.parse(string);
3260                    assertEquals("\"" + currentPat + "\".parse(" + string + ")",
3261                                 univ.format(date),
3262                                 univ.format(parsedate));
3263                } catch (ParseException e3) {
3264                    errln("FAIL: \"" + currentPat + "\".parse(" + string + ") => " +
3265                          e3);
3266                    continue;
3267                }
3268            }
3269            else if (control.equals("pf") || control.equals("P")) {
3270                // 'p'
3271                String string = data[i++];
3272                String datestr = data[i++];
3273                String string2 = string;
3274                if (control.length() == 2) {
3275                    string2 = data[i++];
3276                }
3277
3278                Date date = null;
3279                try {
3280                    date = ref.parse(datestr);
3281                } catch (ParseException e) {
3282                    errln("FAIL: Internal test error; can't parse " + datestr);
3283                    continue;
3284                }
3285                try {
3286                    Date parsedate = fmt.parse(string);
3287                    assertEquals("\"" + currentPat + "\".parse(" + string + ")",
3288                                 univ.format(date),
3289                                 univ.format(parsedate));
3290                } catch (ParseException e2) {
3291                    errln("FAIL: \"" + currentPat + "\".parse(" + string + ") => " +
3292                          e2);
3293                    continue;
3294                }
3295                // 'f'
3296                assertEquals("\"" + currentPat + "\".format(" + datestr + ")",
3297                             string2,
3298                             fmt.format(date));
3299            }
3300            else {
3301                errln("FAIL: Invalid control string " + control);
3302                return;
3303            }
3304        }
3305    }
3306    /*
3307    public void TestJB4757(){
3308        DateFormat dfmt = DateFormat.getDateInstance(DateFormat.FULL, ULocale.ROOT);
3309    }
3310    */
3311
3312    /*
3313     * Test case for formatToCharacterIterator
3314     */
3315    public void TestFormatToCharacterIterator() {
3316        // Generate pattern string including all pattern letters with various length
3317        AttributedCharacterIterator acit;
3318        final char SEPCHAR = '~';
3319        String[] patterns = new String[5];
3320        StringBuffer sb = new StringBuffer();
3321        for (int i = 0; i < patterns.length; i++) {
3322            sb.setLength(0);
3323            for (int j = 0; j < PATTERN_CHARS.length(); j++) {
3324                if (j != 0) {
3325                    for (int k = 0; k <= i; k++) {
3326                        sb.append(SEPCHAR);
3327                    }
3328                }
3329                char letter = PATTERN_CHARS.charAt(j);
3330                for (int k = 0; k <= i; k++) {
3331                    sb.append(letter);
3332                }
3333            }
3334            patterns[i] = sb.toString();
3335        }
3336        if (isVerbose()) {
3337            for (int i = 0; i < patterns.length; i++) {
3338                logln("patterns[" + i + "] = " + patterns[i]);
3339            }
3340        }
3341
3342        Calendar cal = Calendar.getInstance();
3343        cal.set(2007, Calendar.JULY, 16, 8, 20, 25);
3344        cal.set(Calendar.MILLISECOND, 567);
3345        final Date d = cal.getTime();
3346
3347        // Test AttributedCharacterIterator returned by SimpleDateFormat
3348        for (int i = 0; i < patterns.length; i++) {
3349            SimpleDateFormat sdf = new SimpleDateFormat(patterns[i]);
3350            acit = sdf.formatToCharacterIterator(d);
3351            int patidx = 0;
3352
3353            while (true) {
3354                Map map = acit.getAttributes();
3355                int limit = acit.getRunLimit();
3356                if (map.isEmpty()) {
3357                    // Must be pattern literal - '~'
3358                    while (acit.getIndex() < limit) {
3359                        if (acit.current() != SEPCHAR) {
3360                            errln("FAIL: Invalid pattern literal at " + acit.current() + " in patterns[" + i + "]");
3361                        }
3362                        acit.next();
3363                    }
3364                } else {
3365                    Set keySet = map.keySet();
3366                    if (keySet.size() == 1) {
3367                        // Check the attribute
3368                        Iterator keyIterator = keySet.iterator();
3369                        DateFormat.Field attr = (DateFormat.Field)keyIterator.next();
3370                        if (!DATEFORMAT_FIELDS[patidx].equals(attr)) {
3371                            errln("FAIL: The attribute at " + acit.getIndex() + " in patterns[" + i + "" +
3372                                    "] is " + attr + " - Expected: " + DATEFORMAT_FIELDS[patidx]);
3373                        }
3374                    } else {
3375                        // SimpleDateFormat#formatToCharacterIterator never set multiple
3376                        // attributes to a single text run.
3377                        errln("FAIL: Multiple attributes were set");
3378                    }
3379                    patidx++;
3380                    // Move to the run limit
3381                    acit.setIndex(limit);
3382                }
3383                if (acit.current() == CharacterIterator.DONE) {
3384                    break;
3385                }
3386            }
3387        }
3388
3389        // ChineseDateFormat has pattern letter 'l' for leap month marker in addition to regular DateFormat
3390        cal.clear();
3391        cal.set(2009, Calendar.JUNE, 22); // 26x78-5-30
3392        Date nonLeapMonthDate = cal.getTime(); // non-leap month
3393        cal.set(2009, Calendar.JUNE, 23); // 26x78-5*-1
3394        Date leapMonthDate = cal.getTime(); // leap month
3395
3396        ChineseDateFormat cdf = new ChineseDateFormat("y'x'G-Ml-d", ULocale.US);
3397        acit = cdf.formatToCharacterIterator(nonLeapMonthDate);
3398        Set keys = acit.getAllAttributeKeys();
3399        if (keys.contains(ChineseDateFormat.Field.IS_LEAP_MONTH)) {
3400            errln("FAIL: separate IS_LEAP_MONTH field should not be present for a Chinese calendar non-leap date"
3401                    + cdf.format(nonLeapMonthDate));
3402        }
3403        acit = cdf.formatToCharacterIterator(leapMonthDate);
3404        keys = acit.getAllAttributeKeys();
3405        if (keys.contains(ChineseDateFormat.Field.IS_LEAP_MONTH)) {
3406            errln("FAIL: separate IS_LEAP_MONTH field should no longer be present for a Chinese calendar leap date"
3407                    + cdf.format(leapMonthDate));
3408        }
3409    }
3410
3411    /*
3412     * API coverage test case for formatToCharacterIterator
3413     */
3414    public void TestFormatToCharacterIteratorCoverage() {
3415        // Calling formatToCharacterIterator, using various argument types
3416        DateFormat df = DateFormat.getDateTimeInstance();
3417        AttributedCharacterIterator acit = null;
3418
3419        Calendar cal = Calendar.getInstance();
3420        try {
3421            acit = df.formatToCharacterIterator(cal);
3422            if (acit == null) {
3423                errln("FAIL: null AttributedCharacterIterator returned by formatToCharacterIterator(Calendar)");
3424            }
3425        } catch (IllegalArgumentException iae) {
3426            errln("FAIL: Calendar must be accepted by formatToCharacterIterator");
3427        }
3428
3429        Date d = cal.getTime();
3430        try {
3431            acit = df.formatToCharacterIterator(d);
3432            if (acit == null) {
3433                errln("FAIL: null AttributedCharacterIterator returned by formatToCharacterIterator(Date)");
3434            }
3435        } catch (IllegalArgumentException iae) {
3436            errln("FAIL: Date must be accepted by formatToCharacterIterator");
3437        }
3438
3439        Number num = new Long(d.getTime());
3440        try {
3441            acit = df.formatToCharacterIterator(num);
3442            if (acit == null) {
3443                errln("FAIL: null AttributedCharacterIterator returned by formatToCharacterIterator(Number)");
3444            }
3445        } catch (IllegalArgumentException iae) {
3446            errln("FAIL: Number must be accepted by formatToCharacterIterator");
3447        }
3448
3449        boolean isException = false;
3450        String str = df.format(d);
3451        try {
3452            acit = df.formatToCharacterIterator(str);
3453            if (acit == null) {
3454                errln("FAIL: null AttributedCharacterIterator returned by formatToCharacterIterator(String)");
3455            }
3456        } catch (IllegalArgumentException iae) {
3457            logln("IllegalArgumentException is thrown by formatToCharacterIterator");
3458            isException = true;
3459        }
3460        if (!isException) {
3461            errln("FAIL: String must not be accepted by formatToCharacterIterator");
3462        }
3463
3464        // DateFormat.Field#ofCalendarField and getCalendarField
3465        for (int i = 0; i < DATEFORMAT_FIELDS.length; i++) {
3466            int calField = DATEFORMAT_FIELDS[i].getCalendarField();
3467            if (calField != -1) {
3468                DateFormat.Field field = DateFormat.Field.ofCalendarField(calField);
3469                if (field != DATEFORMAT_FIELDS[i]) {
3470                    errln("FAIL: " + field + " is returned for a Calendar field " + calField
3471                            + " - Expected: " + DATEFORMAT_FIELDS[i]);
3472                }
3473            }
3474        }
3475
3476        // IllegalArgument for ofCalendarField
3477        isException = false;
3478        try {
3479            DateFormat.Field.ofCalendarField(-1);
3480        } catch (IllegalArgumentException iae) {
3481            logln("IllegalArgumentException is thrown by ofCalendarField");
3482            isException = true;
3483        }
3484        if (!isException) {
3485            errln("FAIL: IllegalArgumentException must be thrown by ofCalendarField for calendar field value -1");
3486        }
3487
3488        // ChineseDateFormat.Field#ofCalendarField and getCalendarField
3489        int ccalField = ChineseDateFormat.Field.IS_LEAP_MONTH.getCalendarField();
3490        if (ccalField != Calendar.IS_LEAP_MONTH) {
3491            errln("FAIL: ChineseCalendar field " + ccalField + " is returned for ChineseDateFormat.Field.IS_LEAP_MONTH.getCalendarField()");
3492        } else {
3493            DateFormat.Field cfield = ChineseDateFormat.Field.ofCalendarField(ccalField);
3494            if (cfield != ChineseDateFormat.Field.IS_LEAP_MONTH) {
3495                errln("FAIL: " + cfield + " is returned for a ChineseCalendar field " + ccalField
3496                        + " - Expected: " + ChineseDateFormat.Field.IS_LEAP_MONTH);
3497            }
3498        }
3499    }
3500
3501    /*
3502     * Test for checking SimpleDateFormat/DateFormatSymbols creation
3503     * honor the calendar keyword in the given locale.  See ticket#6100
3504     */
3505    public void TestCalendarType() {
3506        final String testPattern = "GGGG y MMMM d EEEE";
3507
3508        final ULocale[] testLocales = {
3509                new ULocale("de"),
3510                new ULocale("fr_FR@calendar=gregorian"),
3511                new ULocale("en@calendar=islamic"),
3512                new ULocale("ja_JP@calendar=japanese"),
3513                new ULocale("zh_Hans_CN@calendar=bogus"),
3514                new ULocale("ko_KR@calendar=dangi"),
3515        };
3516
3517        SimpleDateFormat[] formatters = new SimpleDateFormat[5];
3518        for (int i = 0; i < testLocales.length; i++) {
3519            // Create a locale with no keywords
3520            StringBuffer locStrBuf = new StringBuffer();
3521            if (testLocales[i].getLanguage().length() > 0) {
3522                locStrBuf.append(testLocales[i].getLanguage());
3523            }
3524            if (testLocales[i].getScript().length() > 0) {
3525                locStrBuf.append('_');
3526                locStrBuf.append(testLocales[i].getScript());
3527            }
3528            if (testLocales[i].getCountry().length() > 0) {
3529                locStrBuf.append('_');
3530                locStrBuf.append(testLocales[i].getCountry());
3531            }
3532            ULocale locNoKeywords = new ULocale(locStrBuf.toString());
3533
3534            Calendar cal = Calendar.getInstance(testLocales[i]);
3535
3536            // Calendar getDateFormat method
3537            DateFormat df = cal.getDateTimeFormat(DateFormat.MEDIUM, DateFormat.MEDIUM, locNoKeywords);
3538            if (df instanceof SimpleDateFormat) {
3539                formatters[0] = (SimpleDateFormat)df;
3540                formatters[0].applyPattern(testPattern);
3541            } else {
3542                formatters[0] = null;
3543            }
3544
3545            // DateFormat constructor with locale
3546            df = DateFormat.getDateInstance(DateFormat.MEDIUM, testLocales[i]);
3547            if (df instanceof SimpleDateFormat) {
3548                formatters[1] = (SimpleDateFormat)df;
3549                formatters[1].applyPattern(testPattern);
3550            } else {
3551                formatters[1] = null;
3552            }
3553
3554            // DateFormat constructor with Calendar
3555            df = DateFormat.getDateInstance(cal, DateFormat.MEDIUM, locNoKeywords);
3556            if (df instanceof SimpleDateFormat) {
3557                formatters[2] = (SimpleDateFormat)df;
3558                formatters[2].applyPattern(testPattern);
3559            } else {
3560                formatters[2] = null;
3561            }
3562
3563            // SimpleDateFormat constructor
3564            formatters[3] = new SimpleDateFormat(testPattern, testLocales[i]);
3565
3566            // SimpleDateFormat with DateFormatSymbols
3567            DateFormatSymbols dfs = new DateFormatSymbols(testLocales[i]);
3568            formatters[4] = new SimpleDateFormat(testPattern, dfs, testLocales[i]);
3569
3570            // All SimpleDateFormat instances should produce the exact
3571            // same result.
3572            String expected = null;
3573            Date d = new Date();
3574            for (int j = 0; j < formatters.length; j++) {
3575                if (formatters[j] != null) {
3576                    String tmp = formatters[j].format(d);
3577                    if (expected == null) {
3578                        expected = tmp;
3579                    } else if (!expected.equals(tmp)) {
3580                        errln("FAIL: formatter[" + j + "] returned \"" + tmp + "\" in locale " +
3581                                testLocales[i] + " - expected: " + expected);
3582                    }
3583                }
3584            }
3585        }
3586    }
3587
3588    /*
3589     * Test for format/parse method with calendar which is different
3590     * from what DateFormat instance internally use.  See ticket#6420.
3591     */
3592    public void TestRoundtripWithCalendar() {
3593        TimeZone tz = TimeZone.getTimeZone("Europe/Paris");
3594        TimeZone gmt = TimeZone.getTimeZone("Etc/GMT");
3595
3596        final Calendar[] calendars = {
3597            new GregorianCalendar(tz),
3598            new BuddhistCalendar(tz),
3599            new HebrewCalendar(tz),
3600            new IslamicCalendar(tz),
3601            new JapaneseCalendar(tz),
3602        };
3603
3604        final String pattern = "GyMMMMdEEEEHHmmssVVVV";
3605
3606        //FIXME The formatters commented out below are currently failing because of
3607        // the calendar calculation problem reported by #6691
3608
3609        // The order of test formatters mus match the order of calendars above.
3610        final DateFormat[] formatters = {
3611            DateFormat.getPatternInstance(pattern, new ULocale("en_US")), //calendar=gregorian
3612            DateFormat.getPatternInstance(pattern, new ULocale("th_TH")), //calendar=buddhist
3613            DateFormat.getPatternInstance(pattern, new ULocale("he_IL@calendar=hebrew")),
3614//            DateFormat.getPatternInstance(pattern, new ULocale("ar_EG@calendar=islamic")),
3615//            DateFormat.getPatternInstance(pattern, new ULocale("ja_JP@calendar=japanese")),
3616        };
3617
3618        Date d = new Date();
3619        StringBuffer buf = new StringBuffer();
3620        FieldPosition fpos = new FieldPosition(0);
3621        ParsePosition ppos = new ParsePosition(0);
3622
3623        for (int i = 0; i < formatters.length; i++) {
3624            buf.setLength(0);
3625            fpos.setBeginIndex(0);
3626            fpos.setEndIndex(0);
3627            calendars[i].setTime(d);
3628
3629            // Normal case output - the given calendar matches the calendar
3630            // used by the formatter
3631            formatters[i].format(calendars[i], buf, fpos);
3632            String refStr = buf.toString();
3633
3634            for (int j = 0; j < calendars.length; j++) {
3635                if (j == i) {
3636                    continue;
3637                }
3638                buf.setLength(0);
3639                fpos.setBeginIndex(0);
3640                fpos.setEndIndex(0);
3641                calendars[j].setTime(d);
3642
3643                // Even the different calendar type is specified,
3644                // we should get the same result.
3645                formatters[i].format(calendars[j], buf, fpos);
3646                if (!refStr.equals(buf.toString())) {
3647                    errln("FAIL: Different format result with a different calendar for the same time -"
3648                            + "\n Reference calendar type=" + calendars[i].getType()
3649                            + "\n Another calendar type=" + calendars[j].getType()
3650                            + "\n Expected result=" + refStr
3651                            + "\n Actual result=" + buf.toString());
3652                }
3653            }
3654
3655            calendars[i].setTimeZone(gmt);
3656            calendars[i].clear();
3657            ppos.setErrorIndex(-1);
3658            ppos.setIndex(0);
3659
3660            // Normal case parse result - the given calendar matches the calendar
3661            // used by the formatter
3662            formatters[i].parse(refStr, calendars[i], ppos);
3663
3664            for (int j = 0; j < calendars.length; j++) {
3665                if (j == i) {
3666                    continue;
3667                }
3668                calendars[j].setTimeZone(gmt);
3669                calendars[j].clear();
3670                ppos.setErrorIndex(-1);
3671                ppos.setIndex(0);
3672
3673                // Even the different calendar type is specified,
3674                // we should get the same time and time zone.
3675                formatters[i].parse(refStr, calendars[j], ppos);
3676                if (calendars[i].getTimeInMillis() != calendars[j].getTimeInMillis()
3677                        || !calendars[i].getTimeZone().equals(calendars[j].getTimeZone())) {
3678                    errln("FAIL: Different parse result with a different calendar for the same string -"
3679                            + "\n Reference calendar type=" + calendars[i].getType()
3680                            + "\n Another calendar type=" + calendars[j].getType()
3681                            + "\n Date string=" + refStr
3682                            + "\n Expected time=" + calendars[i].getTimeInMillis()
3683                            + "\n Expected time zone=" + calendars[i].getTimeZone().getID()
3684                            + "\n Actual time=" + calendars[j].getTimeInMillis()
3685                            + "\n Actual time zone=" + calendars[j].getTimeZone().getID());
3686                }
3687            }
3688        }
3689    }
3690
3691    // based on TestRelativeDateFormat() in icu/trunk/source/test/cintltst/cdattst.c
3692    public void TestRelativeDateFormat() {
3693        ULocale loc = ULocale.US;
3694        TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
3695        Calendar cal = new GregorianCalendar(tz, loc);
3696        Date now = new Date();
3697        cal.setTime(now);
3698        cal.set(Calendar.HOUR_OF_DAY, 18);
3699        cal.set(Calendar.MINUTE, 49);
3700        cal.set(Calendar.SECOND, 0);
3701        Date today = cal.getTime();
3702        String minutesStr = "49"; // minutes string to search for in formatted result
3703        int[] dateStylesList = { DateFormat.RELATIVE_FULL, DateFormat.RELATIVE_LONG, DateFormat.RELATIVE_MEDIUM, DateFormat.RELATIVE_SHORT };
3704
3705        for (int i = 0; i < dateStylesList.length; i++) {
3706            int dateStyle = dateStylesList[i];
3707            DateFormat fmtRelDateTime = DateFormat.getDateTimeInstance(dateStyle, DateFormat.SHORT, loc);
3708            DateFormat fmtRelDate = DateFormat.getDateInstance(dateStyle, loc);
3709            DateFormat fmtTime = DateFormat.getTimeInstance(DateFormat.SHORT, loc);
3710
3711            for (int dayOffset = -2; dayOffset <= 2; dayOffset++ ) {
3712                StringBuffer dateTimeStr = new StringBuffer(64);
3713                StringBuffer dateStr = new StringBuffer(64);
3714                StringBuffer timeStr = new StringBuffer(64);
3715                FieldPosition fp = new FieldPosition(DateFormat.MINUTE_FIELD);
3716                cal.setTime(today);
3717                cal.add(Calendar.DATE, dayOffset);
3718
3719                fmtRelDateTime.format(cal, dateTimeStr, fp);
3720                fmtRelDate.format(cal, dateStr, new FieldPosition(0) );
3721                fmtTime.format(cal, timeStr, new FieldPosition(0) );
3722                logln(dayOffset + ", " + dateStyle + ", " + dateTimeStr);
3723                logln(dayOffset + ", " + dateStyle + ", " + dateStr);
3724                logln(dayOffset + ", " + dateStyle + ", " + timeStr);
3725
3726                // check that dateStr is in dateTimeStr
3727                if ( dateTimeStr.toString().indexOf( dateStr.toString() ) < 0 ) {
3728                    errln("relative date string not found in datetime format with timeStyle SHORT, dateStyle " +
3729                            dateStyle + " for dayOffset " + dayOffset );
3730                    errln("datetime format is " + dateTimeStr.toString() + ", date string is " + dateStr.toString() );
3731                }
3732                // check that timeStr is in dateTimeStr
3733                if ( dateTimeStr.toString().indexOf( timeStr.toString() ) < 0 ) {
3734                    errln("short time string not found in datetime format with timeStyle SHORT, dateStyle " +
3735                            dateStyle + " for dayOffset " + dayOffset );
3736                    errln("datetime format is " + dateTimeStr.toString() + ", time string is " + timeStr.toString() );
3737                }
3738                // check index of minutesStr
3739                int minutesStrIndex = dateTimeStr.toString().indexOf( minutesStr );
3740                if ( fp.getBeginIndex() != minutesStrIndex ) {
3741                    errln("FieldPosition beginIndex " + fp.getBeginIndex() + " instead of " + minutesStrIndex + " for datetime format with timeStyle SHORT, dateStyle " +
3742                            dateStyle + " for dayOffset " + dayOffset );
3743                    errln("datetime format is " + dateTimeStr.toString() );
3744                }
3745            }
3746        }
3747    }
3748
3749    public void Test6880() {
3750        Date d1, d2, dp1, dp2, dexp1, dexp2;
3751        String s1, s2;
3752
3753        TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai");
3754        GregorianCalendar gcal = new GregorianCalendar(tz);
3755
3756        gcal.clear();
3757        gcal.set(1900, Calendar.JANUARY, 1, 12, 00);    // offset 8:05:43
3758        d1 = gcal.getTime();
3759
3760        gcal.clear();
3761        gcal.set(1950, Calendar.JANUARY, 1, 12, 00);    // offset 8:00
3762        d2 = gcal.getTime();
3763
3764        gcal.clear();
3765        gcal.set(1970, Calendar.JANUARY, 1, 12, 00);
3766        dexp2 = gcal.getTime();
3767        dexp1 = new Date(dexp2.getTime() - (5*60 + 43)*1000);   // subtract 5m43s
3768
3769        DateFormat fmt = DateFormat.getTimeInstance(DateFormat.FULL, new ULocale("zh"));
3770        fmt.setTimeZone(tz);
3771
3772        s1 = fmt.format(d1);
3773        s2 = fmt.format(d2);
3774
3775        try {
3776            dp1 = fmt.parse(s1);
3777            dp2 = fmt.parse(s2);
3778
3779            if (!dp1.equals(dexp1)) {
3780                errln("FAIL: Failed to parse " + s1 + " parsed: " + dp1 + " expected: " + dexp1);
3781            }
3782            if (!dp2.equals(dexp2)) {
3783                errln("FAIL: Failed to parse " + s2 + " parsed: " + dp2 + " expected: " + dexp2);
3784            }
3785        } catch (ParseException pe) {
3786            errln("FAIL: Parse failure");
3787        }
3788    }
3789
3790    /*
3791     * Tests the constructor public SimpleDateFormat(String pattern, String override, ULocale loc)
3792     */
3793    public void TestSimpleDateFormatConstructor_String_String_ULocale() {
3794        try {
3795            SimpleDateFormat sdf = new SimpleDateFormat("", "", null);
3796            sdf = (SimpleDateFormat) sdf.clone();
3797        } catch (Exception e) {
3798            errln("SimpleDateFormat(String pattern, String override, ULocale loc) "
3799                    + "was not suppose to return an exception when constructing a new " + "SimpleDateFormat object.");
3800        }
3801    }
3802
3803    /*
3804     * Tests the method public static DateFormat.Field ofCalendarField(int calendarField)
3805     */
3806    public void TestOfCalendarField() {
3807        // Tests when if (calendarField == ChineseCalendar.IS_LEAP_MONTH) is false
3808        int[] cases = { Calendar.IS_LEAP_MONTH - 1};
3809        for (int i = 0; i < cases.length; i++) {
3810            try {
3811                Field.ofCalendarField(cases[i]);
3812            } catch (Exception e) {
3813                errln("Field.ofCalendarField(int) is not suppose to " + "return an exception for parameter " + cases[i]);
3814            }
3815        }
3816    }
3817
3818    /* Tests the method public final static DateFormat getPatternInstance */
3819    public void TestGetPatternInstance(){
3820        //public final static DateFormat getPatternInstance(String pattern)
3821        try{
3822            @SuppressWarnings("unused")
3823            DateFormat df = DateFormat.getPatternInstance("");
3824            df = DateFormat.getPatternInstance("", new Locale("en_US"));
3825            df = DateFormat.getPatternInstance(null, "", new Locale("en_US"));
3826        } catch(Exception e) {
3827            errln("DateFormat.getPatternInstance is not suppose to return an exception.");
3828        }
3829    }
3830
3831    /*
3832     * Test case for very long numeric field patterns (ticket#7595)
3833     */
3834    public void TestLongNumericPattern() {
3835        String DATA[] = {
3836            "yyyy MM dd",
3837
3838            "yyyy.MM.dd", "fp", "2010 04 01",
3839            "2010.04.01", "2010 04 01",
3840
3841            "yyyyyyyyyy.MM.dd", "fp", "2010 04 01",
3842            "0000002010.04.01", "2010 04 01",
3843
3844            "yyyyyyyyyyy.MM.dd", "fp", "2010 04 01",
3845            "00000002010.04.01", "2010 04 01",
3846
3847            "yyyyyyyyyyy.M.dddddddddd", "fp", "2010 04 01",
3848            "00000002010.4.0000000001", "2010 04 01",
3849
3850            "y.M.ddddddddddd", "fp", "2010 10 11",
3851            "2010.10.00000000011", "2010 10 11",
3852        };
3853        expect(DATA, new Locale("en", "", ""));
3854    }
3855
3856    /*
3857     * Test case for very long contiguous numeric patterns (ticket#7480)
3858     */
3859    public void TestLongContiguousNumericPattern() {
3860        String DATA[] = {
3861                "yyyy-MM-dd HH:mm:ss.SSS",
3862
3863                "yyyyMMddHHmmssSSSSSS", "fp", "2010-04-16 12:23:34.456",
3864                "20100416122334456000", "2010-04-16 12:23:34.456",
3865
3866                "yyyyyyMMddHHHHmmmmssssSSSSSS", "fp", "2010-04-16 12:23:34.456",
3867                "0020100416001200230034456000", "2010-04-16 12:23:34.456",
3868        };
3869            expect(DATA, new Locale("en", "", ""));
3870    }
3871
3872    /*
3873 * Test case for ISO Era processing (ticket#7357)
3874 */
3875    public void TestISOEra()
3876    {
3877
3878        String data[] = {
3879        // input, output
3880        "BC 4004-10-23T07:00:00Z", "BC 4004-10-23T07:00:00Z",
3881        "AD 4004-10-23T07:00:00Z", "AD 4004-10-23T07:00:00Z",
3882        "-4004-10-23T07:00:00Z"  , "BC 4005-10-23T07:00:00Z",
3883        "4004-10-23T07:00:00Z"   , "AD 4004-10-23T07:00:00Z",
3884        };
3885
3886        int numData = 8;
3887
3888        // create formatter
3889        SimpleDateFormat fmt1 = new SimpleDateFormat("GGG yyyy-MM-dd'T'HH:mm:ss'Z");
3890
3891        for (int i = 0; i < numData; i += 2)
3892        {
3893
3894            // create input string
3895            String in = data[i];
3896
3897            // parse string to date
3898            Date dt1;
3899            try
3900            {
3901                dt1 = fmt1.parse(in);
3902            }
3903            catch (Exception e)
3904            {
3905                errln("DateFormat.parse is not suppose to return an exception.");
3906                break;
3907            }
3908            // format date back to string
3909            String out;
3910            out = fmt1.format(dt1);
3911
3912            // check that roundtrip worked as expected
3913            String expected = data[i + 1];
3914            if (!out.equals(expected))
3915            {
3916                errln((String)"FAIL: " + in + " -> " + out + " expected -> " + expected);
3917            }
3918        }
3919    }
3920
3921    public void TestFormalChineseDate() {
3922
3923        String pattern = "y\u5e74M\u6708d\u65e5";
3924        String override = "y=hanidec;M=hans;d=hans";
3925
3926        // create formatter
3927        SimpleDateFormat sdf = new SimpleDateFormat(pattern,override,ULocale.CHINA);
3928
3929        Calendar cal = Calendar.getInstance(ULocale.ENGLISH);
3930        cal.clear(Calendar.MILLISECOND);
3931        cal.set(2009, 6, 28, 0,0,0);
3932        FieldPosition pos = new FieldPosition(0);
3933        StringBuffer result = new StringBuffer();
3934        sdf.format(cal,result,pos);
3935        String res1 = result.toString();
3936        String expected = "\u4e8c\u3007\u3007\u4e5d\u5e74\u4e03\u6708\u4e8c\u5341\u516b\u65e5";
3937        if (! res1.equals(expected)) {
3938            errln((String)"FAIL: -> " + result.toString() + " expected -> " + expected);
3939        }
3940        ParsePosition pp = new ParsePosition(0);
3941        Date parsedate = sdf.parse(expected, pp);
3942        long time1 = parsedate.getTime();
3943        long time2 = cal.getTimeInMillis();
3944        if ( time1 != time2 ) {
3945            errln("FAIL: parsed -> " + parsedate.toString() + " expected -> " + cal.toString());
3946        }
3947    }
3948
3949    public void TestOverrideNumberForamt() {
3950        SimpleDateFormat fmt = new SimpleDateFormat("MM/dd/yy z");
3951
3952        // test override get/set NumberFormat
3953        for (int i = 0; i < 100; i++) {
3954            NumberFormat check_nf = NumberFormat.getInstance(new ULocale("en_US"));
3955            fmt.setNumberFormat("y", check_nf);
3956            NumberFormat get_nf = fmt.getNumberFormat('y');
3957            if (!get_nf.equals(check_nf))
3958                errln("FAIL: getter and setter do not work");
3959        }
3960
3961        NumberFormat reused_nf = NumberFormat.getInstance(new ULocale("en_US"));
3962        fmt.setNumberFormat("y", reused_nf);
3963        fmt.setNumberFormat(reused_nf); // test the same override NF will not crash
3964
3965        // DATA[i][0] is to tell which field to set, DATA[i][1] is the expected result
3966        String[][] DATA = {
3967                { "", "\u521D\u516D \u5341\u4E94" },
3968                { "M", "\u521D\u516D 15" },
3969                { "Mo", "\u521D\u516D \u5341\u4E94" },
3970                { "Md", "\u521D\u516D \u5341\u4E94" },
3971                { "MdMMd", "\u521D\u516D \u5341\u4E94" },
3972                { "mixed", "\u521D\u516D \u5341\u4E94" },
3973        };
3974
3975        NumberFormat override = NumberFormat.getInstance(new ULocale("en@numbers=hanidays"));
3976        Calendar cal = Calendar.getInstance();
3977        cal.set(1997, Calendar.JUNE, 15);
3978        Date test_date = cal.getTime();
3979
3980        for (int i = 0; i < DATA.length; i++) {
3981            fmt = new SimpleDateFormat("MM d", new ULocale("en_US"));
3982            String field = DATA[i][0];
3983
3984            if (field == "") { // use the one w/o field
3985                fmt.setNumberFormat(override);
3986            } else if (field == "mixed") { // set 1 field at first but then full override, both(M & d) should be override
3987                NumberFormat single_override = NumberFormat.getInstance(new ULocale("en@numbers=hebr"));
3988                fmt.setNumberFormat("M", single_override);
3989                fmt.setNumberFormat(override);
3990            } else if (field == "Mo") { // o is invalid field
3991                try {
3992                    fmt.setNumberFormat(field, override);
3993                } catch (IllegalArgumentException e) {
3994                    logln("IllegalArgumentException is thrown for invalid fields");
3995                    continue;
3996                }
3997            } else {
3998                fmt.setNumberFormat(field, override);
3999            }
4000            String result = fmt.format(test_date);
4001            String expected  = DATA[i][1];
4002
4003            if (!result.equals(expected))
4004                errln((String) "FAIL: -> " + result.toString() + " expected -> " + expected);
4005        }
4006    }
4007
4008    public void TestParsePosition() {
4009        class ParseTestData {
4010            String pattern; // format pattern
4011            String input;   // input date string
4012            int startPos;   // start position
4013            int resPos;     // expected result parse position
4014
4015            ParseTestData(String pattern, String dateStr) {
4016                this.pattern = pattern;
4017                this.input = dateStr;
4018                this.startPos = 0;
4019                this.resPos = dateStr.length();
4020            }
4021
4022            ParseTestData(String pattern, String lead, String dateStr, String trail) {
4023                this.pattern = pattern;
4024                this.input = lead + dateStr + trail;
4025                this.startPos = lead.length();
4026                this.resPos = lead.length() + dateStr.length();
4027            }
4028        }
4029
4030        ParseTestData[] TestData = {
4031            new ParseTestData("yyyy-MM-dd HH:mm:ssZ", "2010-01-10 12:30:00+0500"),
4032            new ParseTestData("yyyy-MM-dd HH:mm:ss ZZZZ", "2010-01-10 12:30:00 GMT+05:00"),
4033            new ParseTestData("Z HH:mm:ss", "-0100 13:20:30"),
4034            new ParseTestData("y-M-d Z", "", "2011-8-25 -0400", " Foo"),
4035            new ParseTestData("y/M/d H:mm:ss z", "2011/7/1 12:34:00 PDT"),
4036            new ParseTestData("y/M/d H:mm:ss z", "+123", "2011/7/1 12:34:00 PDT", " PST"),
4037            new ParseTestData("vvvv a h:mm:ss", "Pacific Time AM 10:21:45"),
4038            new ParseTestData("HH:mm v M/d", "111", "14:15 PT 8/10", " 12345"),
4039            new ParseTestData("'time zone:' VVVV 'date:' yyyy-MM-dd", "xxxx", "time zone: Los Angeles Time date: 2010-02-25", "xxxx"),
4040        };
4041
4042        for (ParseTestData data : TestData) {
4043            SimpleDateFormat sdf = new SimpleDateFormat(data.pattern);
4044            ParsePosition pos = new ParsePosition(data.startPos);
4045            /* Date d = */sdf.parse(data.input, pos);
4046            if (pos.getIndex() != data.resPos) {
4047                errln("FAIL: Parsing [" + data.input + "] with pattern [" + data.pattern + "] returns position - "
4048                        + pos.getIndex() + ", expected - " + data.resPos);
4049            }
4050        }
4051    }
4052
4053    public void TestChineseDateFormatSymbols() {
4054        class ChineseDateFormatSymbolItem {
4055            public ULocale locale;
4056            String marker;
4057            public ChineseDateFormatSymbolItem(ULocale loc, String mrk) {
4058                locale = loc;
4059                marker = mrk;
4060            }
4061        };
4062        final ChineseDateFormatSymbolItem[] items = {
4063            new ChineseDateFormatSymbolItem( ULocale.ENGLISH, "bis" ),
4064            new ChineseDateFormatSymbolItem( ULocale.SIMPLIFIED_CHINESE, "\u95F0" ),
4065            new ChineseDateFormatSymbolItem( ULocale.TRADITIONAL_CHINESE, "\u958F" ),
4066        };
4067        ChineseCalendar cal = new ChineseCalendar();
4068        for ( ChineseDateFormatSymbolItem item: items ) {
4069            ChineseDateFormatSymbols cdfSymbols = new ChineseDateFormatSymbols(cal, item.locale);
4070            if ( !cdfSymbols.getLeapMonth(0).contentEquals("") || !cdfSymbols.getLeapMonth(1).contentEquals(item.marker) ) {
4071                errln("FAIL: isLeapMonth [0],[1] for locale " + item.locale + "; expected \"\", \"" + item.marker + "\"; got \"" + cdfSymbols.getLeapMonth(0) + "\", \"" + cdfSymbols.getLeapMonth(1) + "\"");
4072            }
4073        }
4074    }
4075
4076    public void TestMonthPatterns() {
4077        class ChineseCalTestDate {
4078            public int era;
4079            public int year;
4080            public int month; // here 1-based
4081            public int isLeapMonth;
4082            public int day;
4083             // Simple constructor
4084            public ChineseCalTestDate(int e, int y, int m, int il, int d) {
4085                era = e;
4086                year = y;
4087                month = m;
4088                isLeapMonth = il;
4089                day = d;
4090            }
4091        };
4092        final ChineseCalTestDate[] dates = {
4093            //                      era yr mo lp da
4094            new ChineseCalTestDate( 78, 29, 4, 0, 2 ), // (in chinese era 78) gregorian 2012-4-22
4095            new ChineseCalTestDate( 78, 29, 4, 1, 2 ), // (in chinese era 78) gregorian 2012-5-22
4096            new ChineseCalTestDate( 78, 29, 5, 0, 2 ), // (in chinese era 78) gregorian 2012-6-20
4097        };
4098        class MonthPatternItem {
4099            public String locale;
4100            public int style;
4101            public String[] dateString;
4102             // Simple constructor
4103            public MonthPatternItem(String loc, int styl, String dateStr0, String dateStr1, String dateStr2) {
4104                locale = loc;
4105                style = styl;
4106                dateString = new String[3];
4107                dateString[0] = dateStr0;
4108                dateString[1] = dateStr1;
4109                dateString[2] = dateStr2;
4110            }
4111        };
4112        // Android patch: Revert to "9" instead of "Month9".
4113        final MonthPatternItem[] items = {
4114            new MonthPatternItem( "root@calendar=chinese",    DateFormat.LONG,  "2012(ren-chen) M04 2",  "2012(ren-chen) M04bis 2",  "2012(ren-chen) M05 2" ),
4115            new MonthPatternItem( "root@calendar=chinese",    DateFormat.SHORT, "2012-04-02",            "2012-04bis-02",            "2012-05-02" ),
4116            new MonthPatternItem( "root@calendar=chinese",    -1,               "29-4-2",                "29-4bis-2",                "29-5-2" ),
4117            new MonthPatternItem( "root@calendar=chinese",    -2,               "78x29-4-2",             "78x29-4bis-2",             "78x29-5-2" ),
4118            new MonthPatternItem( "root@calendar=chinese",    -3,               "ren-chen-4-2",          "ren-chen-4bis-2",          "ren-chen-5-2" ),
4119            new MonthPatternItem( "root@calendar=chinese",    -4,               "ren-chen M04 2",        "ren-chen M04bis 2",        "ren-chen M05 2" ),
4120            new MonthPatternItem( "en@calendar=gregorian",    -3,               "2012-4-22",             "2012-5-22",                "2012-6-20" ),
4121            new MonthPatternItem( "en@calendar=chinese",      DateFormat.LONG,  "4 2, 2012(ren-chen)", "4bis 2, 2012(ren-chen)", "5 2, 2012(ren-chen)" ),
4122            new MonthPatternItem( "en@calendar=chinese",      DateFormat.SHORT, "4/2/2012",              "4bis/2/2012",              "5/2/2012" ),
4123            new MonthPatternItem( "zh@calendar=chinese",      DateFormat.LONG,  "2012\u58EC\u8FB0\u5E74\u56DB\u6708\u521D\u4E8C",
4124                                                                                "2012\u58EC\u8FB0\u5E74\u95F0\u56DB\u6708\u521D\u4E8C",
4125                                                                                "2012\u58EC\u8FB0\u5E74\u4E94\u6708\u521D\u4E8C" ),
4126            new MonthPatternItem( "zh@calendar=chinese",      DateFormat.SHORT, "2012-4-2",              "2012-\u95F04-2",           "2012-5-2" ),
4127            new MonthPatternItem( "zh@calendar=chinese",      -3,               "\u58EC\u8FB0-4-2",
4128                                                                                "\u58EC\u8FB0-\u95F04-2",
4129                                                                                "\u58EC\u8FB0-5-2" ),
4130            new MonthPatternItem( "zh@calendar=chinese",      -4,               "\u58EC\u8FB0 \u56DB\u6708 2",
4131                                                                                "\u58EC\u8FB0 \u95F0\u56DB\u6708 2",
4132                                                                                "\u58EC\u8FB0 \u4E94\u6708 2" ),
4133            new MonthPatternItem( "zh_Hant@calendar=chinese", DateFormat.LONG,  "2012\u58EC\u8FB0\u5E74\u56DB\u6708\u521D\u4E8C",
4134                                                                                "2012\u58EC\u8FB0\u5E74\u958F\u56DB\u6708\u521D\u4E8C",
4135                                                                                "2012\u58EC\u8FB0\u5E74\u4E94\u6708\u521D\u4E8C" ),
4136            new MonthPatternItem( "zh_Hant@calendar=chinese", DateFormat.SHORT, "2012/4/2",              "2012/\u958F4/2",           "2012/5/2" ),
4137            new MonthPatternItem( "fr@calendar=chinese",      DateFormat.LONG,  "2 s\u00ECyu\u00E8 ren-chen",  "2 s\u00ECyu\u00E8bis ren-chen",  "2 w\u01D4yu\u00E8 ren-chen" ),
4138            new MonthPatternItem( "fr@calendar=chinese",      DateFormat.SHORT, "2/4/29",                      "2/4bis/29",                      "2/5/29" ),
4139            new MonthPatternItem( "en@calendar=dangi",        DateFormat.LONG,  "3bis 2, 2012(ren-chen)", "4 2, 2012(ren-chen)",       "5 1, 2012(ren-chen)" ),
4140            new MonthPatternItem( "en@calendar=dangi",        DateFormat.SHORT, "3bis/2/2012",                 "4/2/2012",                       "5/1/2012" ),
4141            new MonthPatternItem( "en@calendar=dangi",        -2,               "78x29-3bis-2",                "78x29-4-2",                      "78x29-5-1" ),
4142            new MonthPatternItem( "ko@calendar=dangi",        DateFormat.LONG,  "\uC784\uC9C4\uB144 \uC7243\uC6D4 2\uC77C",
4143                                                                                "\uC784\uC9C4\uB144 4\uC6D4 2\uC77C",
4144                                                                                "\uC784\uC9C4\uB144 5\uC6D4 1\uC77C" ),
4145            new MonthPatternItem( "ko@calendar=dangi",        DateFormat.SHORT, "29. \uC7243. 2.",
4146                                                                                "29. 4. 2.",
4147                                                                                "29. 5. 1." ),
4148        };
4149        // Android patch end.
4150        //                         style: -1        -2            -3       -4
4151        final String[] customPatterns = { "y-Ml-d", "G'x'y-Ml-d", "U-M-d", "U MMM d" }; // previously G and l for chinese cal only handled by ChineseDateFormat
4152        Calendar rootChineseCalendar = Calendar.getInstance(new ULocale("root@calendar=chinese"));
4153        for (MonthPatternItem item: items) {
4154            ULocale locale = new ULocale(item.locale);
4155            DateFormat dfmt = (item.style >= 0)? DateFormat.getDateInstance(item.style, locale): new SimpleDateFormat(customPatterns[-item.style - 1], locale);
4156            int idate = 0;
4157            for (ChineseCalTestDate date: dates) {
4158                rootChineseCalendar.clear();
4159                rootChineseCalendar.set( Calendar.ERA, date.era );
4160                rootChineseCalendar.set( date.year, date.month-1, date.day );
4161                rootChineseCalendar.set( Calendar.IS_LEAP_MONTH, date.isLeapMonth );
4162                StringBuffer result = new StringBuffer();
4163                FieldPosition fpos = new FieldPosition(0);
4164                dfmt.format(rootChineseCalendar, result, fpos);
4165                if (result.toString().compareTo(item.dateString[idate]) != 0) {
4166                    errln("FAIL: Chinese calendar format for locale " + item.locale +  ", style " + item.style +
4167                            ", expected \"" + item.dateString[idate] + "\", got \"" + result + "\"");
4168                } else {
4169                    // formatted OK, try parse
4170                    ParsePosition ppos = new ParsePosition(0);
4171                    // ensure we are really parsing the fields we should be
4172                    rootChineseCalendar.set( Calendar.YEAR, 1 );
4173                    rootChineseCalendar.set( Calendar.MONTH, 0 );
4174                    rootChineseCalendar.set( Calendar.IS_LEAP_MONTH, 0 );
4175                    rootChineseCalendar.set( Calendar.DATE, 1 );
4176                    //
4177                    dfmt.parse(result.toString(), rootChineseCalendar, ppos);
4178                    int era = rootChineseCalendar.get(Calendar.ERA);
4179                    int year = rootChineseCalendar.get(Calendar.YEAR);
4180                    int month = rootChineseCalendar.get(Calendar.MONTH) + 1;
4181                    int isLeapMonth = rootChineseCalendar.get(Calendar.IS_LEAP_MONTH);
4182                    int day = rootChineseCalendar.get(Calendar.DATE);
4183                    if ( ppos.getIndex() < result.length() || year != date.year || month != date.month || isLeapMonth != date.isLeapMonth || day != date.day) {
4184                        errln("FAIL: Chinese calendar parse for locale " + item.locale +  ", style " + item.style +
4185                                ", string \"" + result + "\", expected " + date.year+"-"+date.month+"("+date.isLeapMonth+")-"+date.day +
4186                                ", got pos " + ppos.getIndex() + " era("+era+")-"+year+"-"+month+"("+isLeapMonth+")-"+day );
4187                    }
4188                }
4189                idate++;
4190            }
4191        }
4192    }
4193
4194    public void TestNonGregoFmtParse() {
4195        class CalAndFmtTestItem {
4196            public int era;
4197            public int year;
4198            public int month;
4199            public int day;
4200            public int hour;
4201            public int minute;
4202            public String formattedDate;
4203             // Simple constructor
4204            public CalAndFmtTestItem(int er, int yr, int mo, int da, int hr, int mi, String fd) {
4205                era = er;
4206                year = yr;
4207                month = mo;
4208                day = da;
4209                hour = hr;
4210                minute = mi;
4211                formattedDate = fd;
4212            }
4213        };
4214        // test items for he@calendar=hebrew, long date format
4215        final CalAndFmtTestItem[] cafti_he_hebrew_long = {
4216            //                     era    yr  mo  da  hr  mi  formattedDate
4217            new CalAndFmtTestItem(   0, 4999, 12, 29, 12,  0, "\u05DB\u05F4\u05D8 \u05D1\u05D0\u05DC\u05D5\u05DC \u05D3\u05F3\u05EA\u05EA\u05E7\u05E6\u05F4\u05D8" ),
4218            new CalAndFmtTestItem(   0, 5100,  0,  1, 12,  0, "\u05D0\u05F3 \u05D1\u05EA\u05E9\u05E8\u05D9 \u05E7\u05F3" ),
4219            new CalAndFmtTestItem(   0, 5774,  5,  1, 12,  0, "\u05D0\u05F3 \u05D1\u05D0\u05D3\u05E8 \u05D0\u05F3 \u05EA\u05E9\u05E2\u05F4\u05D3" ),
4220            new CalAndFmtTestItem(   0, 5999, 12, 29, 12,  0, "\u05DB\u05F4\u05D8 \u05D1\u05D0\u05DC\u05D5\u05DC \u05EA\u05EA\u05E7\u05E6\u05F4\u05D8" ),
4221            new CalAndFmtTestItem(   0, 6100,  0,  1, 12,  0, "\u05D0\u05F3 \u05D1\u05EA\u05E9\u05E8\u05D9 \u05D5\u05F3\u05E7\u05F3" ),
4222        };
4223        final CalAndFmtTestItem[] cafti_zh_chinese_custU = {
4224            //                     era    yr  mo  da  hr  mi  formattedDate
4225            new CalAndFmtTestItem(  78,   31,  0,  1, 12,  0, "2014\u7532\u5348\u5E74\u6B63\u67081" ),
4226            new CalAndFmtTestItem(  77,   31,  0,  1, 12,  0, "1954\u7532\u5348\u5E74\u6B63\u67081" ),
4227        };
4228        final CalAndFmtTestItem[] cafti_zh_chinese_custNoU = {
4229            //                     era    yr  mo  da  hr  mi  formattedDate
4230            new CalAndFmtTestItem(  78,   31,  0,  1, 12, 0, "2014\u5E74\u6B63\u67081" ),
4231            new CalAndFmtTestItem(  77,   31,  0,  1, 12, 0, "1954\u5E74\u6B63\u67081" ),
4232        };
4233        final CalAndFmtTestItem[] cafti_ja_japanese_custGy = {
4234            //                     era    yr  mo  da  hr  mi  formattedDate
4235            new CalAndFmtTestItem( 235,   26,  2,  5, 12, 0, "2014(\u5E73\u621026)\u5E743\u67085\u65E5" ),
4236            new CalAndFmtTestItem( 234,   60,  2,  5, 12, 0, "1985(\u662D\u548C60)\u5E743\u67085\u65E5" ),
4237        };
4238        final CalAndFmtTestItem[] cafti_ja_japanese_custNoGy = {
4239            //                     era    yr  mo  da  hr  mi  formattedDate
4240            new CalAndFmtTestItem( 235,   26,  2,  5, 12, 0, "2014\u5E743\u67085\u65E5" ),
4241            new CalAndFmtTestItem( 234,   60,  2,  5, 12, 0, "1985\u5E743\u67085\u65E5" ),
4242        };
4243        final CalAndFmtTestItem[] cafti_en_islamic_cust = {
4244            //                     era    yr  mo  da  hr  mi  formattedDate
4245            new CalAndFmtTestItem(   0, 1384,  0,  1, 12, 0, "1 Muh. 1384 AH, 1964" ),
4246            new CalAndFmtTestItem(   0, 1436,  0,  1, 12, 0, "1 Muh. 1436 AH, 2014" ),
4247            new CalAndFmtTestItem(   0, 1487,  0,  1, 12, 0, "1 Muh. 1487 AH, 2064" ),
4248        };
4249        class TestNonGregoItem {
4250            public String locale;
4251            public int style;
4252            public String pattern;  // ignored unless style == DateFormat.NONE
4253            public CalAndFmtTestItem[] caftItems;
4254             // Simple constructor
4255            public TestNonGregoItem(String loc, int styl, String pat, CalAndFmtTestItem[] items) {
4256                locale = loc;
4257                style = styl;
4258                pattern = pat;
4259                caftItems = items;
4260            }
4261        };
4262        final TestNonGregoItem[] items = {
4263            new TestNonGregoItem( "he@calendar=hebrew",   DateFormat.LONG, "",                          cafti_he_hebrew_long ),
4264            new TestNonGregoItem( "zh@calendar=chinese",  DateFormat.NONE, "rU\u5E74MMMd",              cafti_zh_chinese_custU ),
4265            new TestNonGregoItem( "zh@calendar=chinese",  DateFormat.NONE, "r\u5E74MMMd",               cafti_zh_chinese_custNoU ),
4266            new TestNonGregoItem( "ja@calendar=japanese", DateFormat.NONE, "r(Gy)\u5E74M\u6708d\u65E5", cafti_ja_japanese_custGy ),
4267            new TestNonGregoItem( "ja@calendar=japanese", DateFormat.NONE, "r\u5E74M\u6708d\u65E5",     cafti_ja_japanese_custNoGy ),
4268            new TestNonGregoItem( "en@calendar=islamic",  DateFormat.NONE, "d MMM y G, r",              cafti_en_islamic_cust ),
4269        };
4270        for (TestNonGregoItem item: items) {
4271            ULocale locale = new ULocale(item.locale);
4272            DateFormat dfmt = null;
4273            if (item.style != DateFormat.NONE) {
4274                dfmt = DateFormat.getDateInstance(item.style, locale);
4275            } else {
4276                dfmt = new SimpleDateFormat(item.pattern, locale);
4277            }
4278            Calendar cal = dfmt.getCalendar();
4279
4280            for (CalAndFmtTestItem caftItem: item.caftItems) {
4281                cal.clear();
4282                cal.set(Calendar.ERA, caftItem.era);
4283                cal.set(caftItem.year, caftItem.month, caftItem.day, caftItem.hour, caftItem.minute, 0);
4284                StringBuffer result = new StringBuffer();
4285                FieldPosition fpos = new FieldPosition(0);
4286                dfmt.format(cal, result, fpos);
4287                if (result.toString().compareTo(caftItem.formattedDate) != 0) {
4288                    errln("FAIL: date format for locale " + item.locale +  ", style " + item.style +
4289                            ", expected \"" + caftItem.formattedDate + "\", got \"" + result + "\"");
4290                } else {
4291                    // formatted OK, try parse
4292                    ParsePosition ppos = new ParsePosition(0);
4293                    dfmt.parse(result.toString(), cal, ppos);
4294                    int era = cal.get(Calendar.ERA);
4295                    int year = cal.get(Calendar.YEAR);
4296                    int month = cal.get(Calendar.MONTH);
4297                    int day = cal.get(Calendar.DATE);
4298                    if ( ppos.getIndex() < result.length() || era != caftItem.era || year != caftItem.year || month != caftItem.month || day != caftItem.day) {
4299                        errln("FAIL: date parse for locale " + item.locale +  ", style " + item.style +
4300                                ", string \"" + result + "\", expected " + caftItem.era+":" +caftItem.year+"-"+caftItem.month+"-"+caftItem.day +
4301                                ", got pos " + ppos.getIndex() + " "+year+"-"+month+"-"+day );
4302                    }
4303                }
4304            }
4305        }
4306    }
4307
4308    public void TestTwoDigitWOY() { // See ICU Ticket #8514
4309        String dateText = new String("98MON01");
4310
4311        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYEEEww");
4312        simpleDateFormat.set2DigitYearStart(new GregorianCalendar(1999,0,1).getTime());
4313
4314        Calendar cal = new GregorianCalendar();
4315        cal.clear();
4316        cal.setFirstDayOfWeek(Calendar.SUNDAY);
4317        cal.setMinimalDaysInFirstWeek(4);
4318
4319        ParsePosition pp = new ParsePosition(0);
4320
4321        simpleDateFormat.parse(dateText, cal, pp);
4322
4323        if (pp.getErrorIndex() >= 0) {
4324            errln("FAIL: Error in parsing two digit WOY");
4325        }
4326
4327        simpleDateFormat.applyPattern("Y");
4328
4329        String result = simpleDateFormat.format(cal.getTime());
4330        if ( !result.equals("2098") ) {
4331            errln("FAIL: Unexpected result in two digit WOY parse.  Expected 2098, got " + result);
4332        }
4333    }
4334
4335    public void TestContext() {
4336        class TestContextItem {
4337            public String locale;
4338            public String pattern;
4339            public DisplayContext capitalizationContext;
4340            public String expectedFormat;
4341             // Simple constructor
4342            public TestContextItem(String loc, String pat, DisplayContext capCtxt, String expFmt) {
4343                locale = loc;
4344                pattern = pat;
4345                capitalizationContext = capCtxt;
4346                expectedFormat = expFmt;
4347            }
4348        };
4349        final TestContextItem[] items = {
4350            new TestContextItem( "fr", "MMMM y", DisplayContext.CAPITALIZATION_NONE,                    "juillet 2008" ),
4351            new TestContextItem( "fr", "MMMM y", DisplayContext.CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE,  "juillet 2008" ),
4352            new TestContextItem( "fr", "MMMM y", DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, "Juillet 2008" ),
4353            new TestContextItem( "fr", "MMMM y", DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU,     "juillet 2008" ),
4354            new TestContextItem( "fr", "MMMM y", DisplayContext.CAPITALIZATION_FOR_STANDALONE,          "Juillet 2008" ),
4355            new TestContextItem( "cs", "LLLL y", DisplayContext.CAPITALIZATION_NONE,                    "\u010Dervenec 2008" ),
4356            new TestContextItem( "cs", "LLLL y", DisplayContext.CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE,  "\u010Dervenec 2008" ),
4357            new TestContextItem( "cs", "LLLL y", DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, "\u010Cervenec 2008" ),
4358            new TestContextItem( "cs", "LLLL y", DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU,     "\u010Cervenec 2008" ),
4359            new TestContextItem( "cs", "LLLL y", DisplayContext.CAPITALIZATION_FOR_STANDALONE,          "\u010Dervenec 2008" ),
4360        };
4361        class TestRelativeContextItem {
4362            public String locale;
4363            public DisplayContext capitalizationContext;
4364            public String expectedFormatToday;
4365            public String expectedFormatYesterday;
4366             // Simple constructor
4367            public TestRelativeContextItem(String loc, DisplayContext capCtxt, String expFmtToday, String expFmtYesterday) {
4368                locale = loc;
4369                capitalizationContext = capCtxt;
4370                expectedFormatToday = expFmtToday;
4371                expectedFormatYesterday = expFmtYesterday;
4372            }
4373        };
4374        final TestRelativeContextItem[] relItems = {
4375            new TestRelativeContextItem( "en", DisplayContext.CAPITALIZATION_NONE,                      "today", "yesterday" ),
4376            new TestRelativeContextItem( "en", DisplayContext.CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE,    "today", "yesterday" ),
4377            new TestRelativeContextItem( "en", DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, "Today", "Yesterday" ),
4378            new TestRelativeContextItem( "en", DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU,       "Today", "Yesterday" ),
4379            new TestRelativeContextItem( "en", DisplayContext.CAPITALIZATION_FOR_STANDALONE,            "Today", "Yesterday" ),
4380            new TestRelativeContextItem( "nb", DisplayContext.CAPITALIZATION_NONE,                      "i dag", "i g\u00E5r" ),
4381            new TestRelativeContextItem( "nb", DisplayContext.CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE,    "i dag", "i g\u00E5r" ),
4382            new TestRelativeContextItem( "nb", DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, "I dag", "I g\u00E5r" ),
4383            new TestRelativeContextItem( "nb", DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU,       "i dag", "i g\u00E5r" ),
4384            new TestRelativeContextItem( "nb", DisplayContext.CAPITALIZATION_FOR_STANDALONE,            "I dag", "I g\u00E5r" ),
4385        };
4386
4387        Calendar cal = new GregorianCalendar(2008, Calendar.JULY, 2);
4388        for (TestContextItem item: items) {
4389            ULocale locale = new ULocale(item.locale);
4390            SimpleDateFormat sdfmt = new SimpleDateFormat(item.pattern, locale);
4391
4392            // now try context & standard format call
4393            sdfmt.setContext(item.capitalizationContext);
4394            SimpleDateFormat sdfmtClone = (SimpleDateFormat)sdfmt.clone();
4395            if (!sdfmtClone.equals(sdfmt)) {
4396                errln("FAIL: for locale " + item.locale +  ", capitalizationContext " + item.capitalizationContext +
4397                        ", sdfmt.clone() != sdfmt (for SimpleDateFormat)");
4398            }
4399
4400            StringBuffer result2 = new StringBuffer();
4401            FieldPosition fpos2 = new FieldPosition(0);
4402            sdfmt.format(cal, result2, fpos2);
4403            if (result2.toString().compareTo(item.expectedFormat) != 0) {
4404                errln("FAIL: format for locale " + item.locale +  ", capitalizationContext " + item.capitalizationContext +
4405                        ", expected \"" + item.expectedFormat + "\", got \"" + result2 + "\"");
4406            }
4407
4408            // now read back context, make sure it is what we set (testing with DateFormat subclass)
4409            DisplayContext capitalizationContext = sdfmt.getContext(DisplayContext.Type.CAPITALIZATION);
4410            if (capitalizationContext != item.capitalizationContext) {
4411                errln("FAIL: getContext for locale " + item.locale +  ", capitalizationContext " + item.capitalizationContext +
4412                        ", but got context " + capitalizationContext);
4413            }
4414        }
4415        for (TestRelativeContextItem relItem: relItems) {
4416            ULocale locale = new ULocale(relItem.locale);
4417            DateFormat dfmt = DateFormat.getDateInstance(DateFormat.RELATIVE_LONG, locale);
4418            Date today = new Date();
4419
4420            // now try context & standard format call
4421            dfmt.setContext(relItem.capitalizationContext);
4422
4423            // write to stream, then read a copy from stream & compare
4424            boolean serializeTestFail = false;
4425            ByteArrayOutputStream baos = null;
4426            DateFormat dfmtFromStream = null;
4427            try {
4428                baos = new ByteArrayOutputStream();
4429                ObjectOutputStream oos = new ObjectOutputStream(baos);
4430                oos.writeObject(dfmt);
4431                oos.close();
4432            } catch (IOException i) {
4433                errln("FAIL: for locale " + relItem.locale +  ", capitalizationContext " + relItem.capitalizationContext +
4434                        ", serialization of RELATIVE_LONG DateFormat fails with IOException");
4435                serializeTestFail = true;
4436            }
4437            if (!serializeTestFail) {
4438                byte[] buf = baos.toByteArray();
4439                try {
4440                    ByteArrayInputStream bais = new ByteArrayInputStream(buf);
4441                    ObjectInputStream ois = new ObjectInputStream(bais);
4442                    dfmtFromStream = (DateFormat)ois.readObject();
4443                    ois.close();
4444                } catch (IOException i) {
4445                    errln("FAIL: for locale " + relItem.locale +  ", capitalizationContext " + relItem.capitalizationContext +
4446                            ", deserialization of RELATIVE_LONG DateFormat fails with IOException");
4447                    serializeTestFail = true;
4448                } catch (ClassNotFoundException c) {
4449                    errln("FAIL: for locale " + relItem.locale +  ", capitalizationContext " + relItem.capitalizationContext +
4450                            ", deserialization of RELATIVE_LONG DateFormat fails with ClassNotFoundException");
4451                    serializeTestFail = true;
4452                }
4453            }
4454            if (!serializeTestFail && dfmtFromStream==null) {
4455                errln("FAIL: for locale " + relItem.locale +  ", capitalizationContext " + relItem.capitalizationContext +
4456                        ", dfmtFromStream is null (for RELATIVE_LONG)");
4457                serializeTestFail = true;
4458            }
4459            if (!serializeTestFail && !dfmtFromStream.equals(dfmt)) {
4460                errln("FAIL: for locale " + relItem.locale +  ", capitalizationContext " + relItem.capitalizationContext +
4461                        ", dfmtFromStream != dfmt (for RELATIVE_LONG)");
4462                serializeTestFail = true;
4463            }
4464
4465            cal.setTime(today);
4466            StringBuffer result2 = new StringBuffer();
4467            FieldPosition fpos2 = new FieldPosition(0);
4468            dfmt.format(cal, result2, fpos2);
4469            if (result2.toString().compareTo(relItem.expectedFormatToday) != 0) {
4470                errln("FAIL: format today for locale " + relItem.locale +  ", capitalizationContext " + relItem.capitalizationContext +
4471                        ", expected \"" + relItem.expectedFormatToday + "\", got \"" + result2 + "\"");
4472            }
4473            if (!serializeTestFail) {
4474                result2.setLength(0);
4475                dfmtFromStream.format(cal, result2, fpos2);
4476                if (result2.toString().compareTo(relItem.expectedFormatToday) != 0) {
4477                    errln("FAIL: use dfmtFromStream to format today for locale " + relItem.locale +  ", capitalizationContext " +
4478                            relItem.capitalizationContext + ", expected \"" + relItem.expectedFormatToday + "\", got \"" + result2 + "\"");
4479                }
4480            }
4481
4482            cal.add(Calendar.DATE, -1);
4483            result2.setLength(0);
4484            dfmt.format(cal, result2, fpos2);
4485            if (result2.toString().compareTo(relItem.expectedFormatYesterday) != 0) {
4486                errln("FAIL: format yesterday for locale " + relItem.locale +  ", capitalizationContext " + relItem.capitalizationContext +
4487                        ", expected \"" + relItem.expectedFormatYesterday + "\", got \"" + result2 + "\"");
4488            }
4489
4490            // now read back context, make sure it is what we set (testing with DateFormat itself)
4491            DisplayContext capitalizationContext = dfmt.getContext(DisplayContext.Type.CAPITALIZATION);
4492            if (capitalizationContext != relItem.capitalizationContext) {
4493                errln("FAIL: getContext for locale " + relItem.locale +  ", capitalizationContext " + relItem.capitalizationContext +
4494                        ", but got context " + capitalizationContext);
4495            }
4496        }
4497    }
4498
4499    static Date TEST_DATE = new Date(2012-1900, 1-1, 15); // January 15, 2012
4500
4501    public void TestDotAndAtLeniency() {
4502        for (ULocale locale : Arrays.asList(ULocale.ENGLISH, ULocale.FRENCH)) {
4503            List<Object[]> tests = new ArrayList();
4504
4505            for (int dateStyle = DateFormat.FULL; dateStyle <= DateFormat.SHORT; ++dateStyle) {
4506                DateFormat dateFormat = DateFormat.getDateInstance(dateStyle, locale);
4507
4508                for (int timeStyle = DateFormat.FULL; timeStyle <= DateFormat.SHORT; ++timeStyle) {
4509                    DateFormat format = DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale);
4510                    DateFormat timeFormat = DateFormat.getTimeInstance(timeStyle, locale);
4511                    String formattedString = format.format(TEST_DATE);
4512
4513                    tests.add(new Object[]{format, formattedString});
4514
4515                    formattedString = dateFormat.format(TEST_DATE) + "  " + timeFormat.format(TEST_DATE);
4516                    tests.add(new Object[]{format, formattedString});
4517                    if (formattedString.contains("n ")) { // will add "." after the end of text ending in 'n', like Jan.
4518                        tests.add(new Object[]{format, formattedString.replace("n ", "n. ") + "."});
4519                    }
4520                    if (formattedString.contains(". ")) { // will subtract "." at the end of strings.
4521                        tests.add(new Object[]{format, formattedString.replace(". ", " ")});
4522                    }
4523                }
4524            }
4525            for (Object[] test : tests) {
4526                DateFormat format = (DateFormat) test[0];
4527                String formattedString = (String) test[1];
4528                if (!showParse(format, formattedString)) {
4529                    // showParse(format, formattedString); // for debugging
4530                }
4531            }
4532        }
4533
4534    }
4535
4536    private boolean showParse(DateFormat format, String formattedString) {
4537        ParsePosition parsePosition = new ParsePosition(0);
4538        parsePosition.setIndex(0);
4539        Date parsed = format.parse(formattedString, parsePosition);
4540        boolean ok = TEST_DATE.equals(parsed) && parsePosition.getIndex() == formattedString.length();
4541        if (ok) {
4542            logln(format + "\t" + formattedString);
4543        } else {
4544            errln(format + "\t" + formattedString);
4545        }
4546        return ok;
4547    }
4548
4549    public void TestDateFormatLeniency() {
4550        // For details see http://bugs.icu-project.org/trac/ticket/10261
4551
4552        class TestDateFormatLeniencyItem {
4553            public ULocale locale;
4554            public boolean leniency;
4555            public String parseString;
4556            public String pattern;
4557            public String expectedResult;   // null indicates expected error
4558             // Simple constructor
4559            public TestDateFormatLeniencyItem(ULocale loc, boolean len, String parString, String patt, String expResult) {
4560                locale = loc;
4561                leniency = len;
4562                pattern = patt;
4563                parseString = parString;
4564                expectedResult = expResult;
4565            }
4566        };
4567
4568        final TestDateFormatLeniencyItem[] items = {
4569            //                             locale               leniency    parse String    pattern             expected result
4570            new TestDateFormatLeniencyItem(ULocale.ENGLISH,     true,       "2008-07 02",   "yyyy-LLLL dd",     "2008-July 02"),
4571            new TestDateFormatLeniencyItem(ULocale.ENGLISH,     false,      "2008-07 02",   "yyyy-LLLL dd",     null),
4572            new TestDateFormatLeniencyItem(ULocale.ENGLISH,     true,       "2008-Jan 02",  "yyyy-LLL. dd",     "2008-Jan. 02"),
4573            new TestDateFormatLeniencyItem(ULocale.ENGLISH,     false,      "2008-Jan 02",  "yyyy-LLL. dd",     null),
4574            new TestDateFormatLeniencyItem(ULocale.ENGLISH,     true,       "2008-Jan--02", "yyyy-MMM' -- 'dd", "2008-Jan -- 02"),
4575            new TestDateFormatLeniencyItem(ULocale.ENGLISH,     false,      "2008-Jan--02", "yyyy-MMM' -- 'dd", null),
4576        };
4577
4578        for (TestDateFormatLeniencyItem item : items) {
4579            SimpleDateFormat sdfmt = new SimpleDateFormat(item.pattern, item.locale);
4580            sdfmt.setBooleanAttribute(BooleanAttribute.PARSE_ALLOW_WHITESPACE, item.leniency)
4581                    .setBooleanAttribute(BooleanAttribute.PARSE_ALLOW_NUMERIC, item.leniency)
4582                    .setBooleanAttribute(BooleanAttribute.PARSE_PARTIAL_MATCH, item.leniency);
4583
4584            ParsePosition p = new ParsePosition(0);
4585            Date d = sdfmt.parse(item.parseString, p);
4586            if (item.expectedResult == null) {
4587                if (p.getErrorIndex() != -1)
4588                    continue;
4589                else
4590                    errln("error: unexpected parse success..." + item.parseString + " w/ lenient=" + item.leniency
4591                            + " should have failed");
4592            }
4593            if (p.getErrorIndex() != -1) {
4594                errln("error: parse error for string " + item.parseString + " -- idx[" + p.getIndex() + "] errIdx["
4595                        + p.getErrorIndex() + "]");
4596                continue;
4597            }
4598
4599            String result = sdfmt.format(d);
4600            if (!result.equalsIgnoreCase(item.expectedResult)) {
4601                errln("error: unexpected format result. expected - " + item.expectedResult + "  but result was - "
4602                        + result);
4603            } else {
4604                logln("formatted results match! - " + result);
4605            }
4606        }
4607    }
4608
4609    // A regression test case for ticket#10632.
4610    // Make sure RELATIVE style works for getInstance overloads taking
4611    // Calendar instance.
4612    public void Test10632() {
4613        Date[] testDates = new Date[3];
4614        Calendar cal = Calendar.getInstance();
4615
4616        // today
4617        testDates[0] = cal.getTime();
4618
4619        // tomorrow
4620        cal.add(Calendar.DATE, 1);
4621        testDates[1] = cal.getTime();
4622
4623        // yesterday
4624        cal.add(Calendar.DATE, -2);
4625        testDates[2] = cal.getTime();
4626
4627
4628        // Relative styles for testing
4629        int[] dateStylesList = {
4630                DateFormat.RELATIVE_FULL,
4631                DateFormat.RELATIVE_LONG,
4632                DateFormat.RELATIVE_MEDIUM,
4633                DateFormat.RELATIVE_SHORT
4634        };
4635
4636        Calendar fmtCal = DateFormat.getInstance().getCalendar();
4637
4638        for (int i = 0; i < dateStylesList.length; i++) {
4639            DateFormat fmt0 = DateFormat.getDateTimeInstance(dateStylesList[i], DateFormat.DEFAULT);
4640            DateFormat fmt1 = DateFormat.getDateTimeInstance(fmtCal, dateStylesList[i], DateFormat.DEFAULT);
4641
4642            for (int j = 0; j < testDates.length; j++) {
4643                String s0 = fmt0.format(testDates[j]);
4644                String s1 = fmt1.format(testDates[j]);
4645
4646                if (!s0.equals(s1)) {
4647                    errln("FAIL: Different results returned by two equivalent relative formatters: s0="
4648                            + s0 + ", s1=" + s1);
4649                }
4650            }
4651        }
4652    }
4653
4654    public void TestParseMultiPatternMatch() {
4655        // For details see http://bugs.icu-project.org/trac/ticket/10336
4656
4657        class TestMultiPatternMatchItem {
4658            public boolean leniency;
4659            public String parseString;
4660            public String pattern;
4661            public String expectedResult;   // null indicates expected error
4662             // Simple constructor
4663            public TestMultiPatternMatchItem(boolean len, String parString, String patt, String expResult) {
4664                leniency = len;
4665                pattern = patt;
4666                parseString = parString;
4667                expectedResult = expResult;
4668            }
4669        };
4670
4671        final TestMultiPatternMatchItem[] items = {
4672                //                            leniency    parse String                  pattern                 expected result
4673                new TestMultiPatternMatchItem(true,       "2013-Sep 13",                "yyyy-MMM dd",          "2013-Sep 13"),
4674                new TestMultiPatternMatchItem(true,       "2013-September 14",          "yyyy-MMM dd",          "2013-Sep 14"),
4675                new TestMultiPatternMatchItem(false,      "2013-September 15",          "yyyy-MMM dd",          null),
4676                new TestMultiPatternMatchItem(false,      "2013-September 16",          "yyyy-MMMM dd",         "2013-September 16"),
4677                new TestMultiPatternMatchItem(true,       "2013-Sep 17",                "yyyy-LLL dd",          "2013-Sep 17"),
4678                new TestMultiPatternMatchItem(true,       "2013-September 18",          "yyyy-LLL dd",          "2013-Sep 18"),
4679                new TestMultiPatternMatchItem(false,      "2013-September 19",          "yyyy-LLL dd",          null),
4680                new TestMultiPatternMatchItem(false,      "2013-September 20",          "yyyy-LLLL dd",         "2013-September 20"),
4681                new TestMultiPatternMatchItem(true,       "2013 Sat Sep 21",            "yyyy EEE MMM dd",      "2013 Sat Sep 21"),
4682                new TestMultiPatternMatchItem(true,       "2013 Sunday Sep 22",         "yyyy EEE MMM dd",      "2013 Sun Sep 22"),
4683                new TestMultiPatternMatchItem(false,      "2013 Monday Sep 23",         "yyyy EEE MMM dd",      null),
4684                new TestMultiPatternMatchItem(false,      "2013 Tuesday Sep 24",        "yyyy EEEE MMM dd",     "2013 Tuesday Sep 24"),
4685                new TestMultiPatternMatchItem(true,       "2013 Wed Sep 25",            "yyyy eee MMM dd",      "2013 Wed Sep 25"),
4686                new TestMultiPatternMatchItem(true,       "2013 Thu Sep 26",            "yyyy eee MMM dd",      "2013 Thu Sep 26"),
4687                new TestMultiPatternMatchItem(false,      "2013 Friday Sep 27",         "yyyy eee MMM dd",      null),
4688                new TestMultiPatternMatchItem(false,      "2013 Saturday Sep 28",       "yyyy eeee MMM dd",    "2013 Saturday Sep 28"),
4689                new TestMultiPatternMatchItem(true,       "2013 Sun Sep 29",            "yyyy ccc MMM dd",      "2013 Sun Sep 29"),
4690                new TestMultiPatternMatchItem(true,       "2013 Monday Sep 30",         "yyyy ccc MMM dd",      "2013 Mon Sep 30"),
4691                new TestMultiPatternMatchItem(false,      "2013 Sunday Oct 13",         "yyyy ccc MMM dd",      null),
4692                new TestMultiPatternMatchItem(false,      "2013 Monday Oct 14",         "yyyy cccc MMM dd",     "2013 Monday Oct 14"),
4693                new TestMultiPatternMatchItem(true,       "2013 Oct 15 Q4",             "yyyy MMM dd QQQ",      "2013 Oct 15 Q4"),
4694                new TestMultiPatternMatchItem(true,       "2013 Oct 16 4th quarter",    "yyyy MMM dd QQQ",      "2013 Oct 16 Q4"),
4695                new TestMultiPatternMatchItem(false,      "2013 Oct 17 4th quarter",    "yyyy MMM dd QQQ",      null),
4696                new TestMultiPatternMatchItem(false,      "2013 Oct 18 Q4",             "yyyy MMM dd QQQ",      "2013 Oct 18 Q4"),
4697                new TestMultiPatternMatchItem(true,       "2013 Oct 19 Q4",             "yyyy MMM dd qqqq",      "2013 Oct 19 4th quarter"),
4698                new TestMultiPatternMatchItem(true,       "2013 Oct 20 4th quarter",    "yyyy MMM dd qqqq",      "2013 Oct 20 4th quarter"),
4699                new TestMultiPatternMatchItem(false,      "2013 Oct 21 Q4",             "yyyy MMM dd qqqq",      null),
4700                new TestMultiPatternMatchItem(false,      "2013 Oct 22 4th quarter",    "yyyy MMM dd qqqq",      "2013 Oct 22 4th quarter"),
4701        };
4702
4703        StringBuffer result = new StringBuffer();
4704        Date d = new Date();
4705        GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"), Locale.US);
4706        SimpleDateFormat sdfmt = new SimpleDateFormat();
4707        ParsePosition p = new ParsePosition(0);
4708        for (TestMultiPatternMatchItem item: items) {
4709            cal.clear();
4710            sdfmt.setCalendar(cal);
4711            sdfmt.applyPattern(item.pattern);
4712            sdfmt.setLenient(item.leniency);
4713            sdfmt.setBooleanAttribute(BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH, item.leniency);
4714            result.setLength(0);
4715            p.setIndex(0);
4716            p.setErrorIndex(-1);
4717            d = sdfmt.parse(item.parseString, p);
4718            if(item.expectedResult == null) {
4719                if(p.getErrorIndex() != -1)
4720                    continue;
4721                else
4722                    errln("error: unexpected parse success..."+item.parseString + " w/ lenient="+item.leniency+" should have failed");
4723            }
4724            if(p.getErrorIndex() != -1) {
4725                errln("error: parse error for string " +item.parseString + " -- idx["+p.getIndex()+"] errIdx["+p.getErrorIndex()+"]");
4726                continue;
4727            }
4728            cal.setTime(d);
4729            result = sdfmt.format(cal, result, new FieldPosition(0));
4730            if(!result.toString().equalsIgnoreCase(item.expectedResult)) {
4731                errln("error: unexpected format result. expected - " + item.expectedResult + "  but result was - " + result);
4732            } else {
4733                logln("formatted results match! - " + result.toString());
4734            }
4735        }
4736
4737    }
4738
4739    public void TestParseLeniencyAPIs() {
4740        DateFormat fmt = DateFormat.getInstance();
4741
4742        assertTrue("isLenient default", fmt.isLenient());
4743        assertTrue("isCalendarLenient default", fmt.isCalendarLenient());
4744        assertTrue("ALLOW_WHITESPACE default", fmt.getBooleanAttribute(BooleanAttribute.PARSE_ALLOW_WHITESPACE));
4745        assertTrue("ALLOW_NUMERIC default", fmt.getBooleanAttribute(BooleanAttribute.PARSE_ALLOW_NUMERIC));
4746        assertTrue("PARTIAL_MATCH default", fmt.getBooleanAttribute(BooleanAttribute.PARSE_PARTIAL_MATCH));
4747        assertTrue("MULTIPLE_PATTERNS default", fmt.getBooleanAttribute(BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH));
4748
4749        // Set calendar to strict
4750        fmt.setCalendarLenient(false);
4751
4752        assertFalse("isLeninent after setCalendarLenient(FALSE)", fmt.isLenient());
4753        assertFalse("isCalendarLenient after setCalendarLenient(FALSE)", fmt.isCalendarLenient());
4754        assertTrue("ALLOW_WHITESPACE after setCalendarLenient(FALSE)", fmt.getBooleanAttribute(BooleanAttribute.PARSE_ALLOW_WHITESPACE));
4755        assertTrue("ALLOW_NUMERIC  after setCalendarLenient(FALSE)", fmt.getBooleanAttribute(BooleanAttribute.PARSE_ALLOW_NUMERIC));
4756
4757        // Set to strict
4758        fmt.setLenient(false);
4759
4760        assertFalse("isLeninent after setLenient(FALSE)", fmt.isLenient());
4761        assertFalse("isCalendarLenient after setLenient(FALSE)", fmt.isCalendarLenient());
4762        assertFalse("ALLOW_WHITESPACE after setLenient(FALSE)", fmt.getBooleanAttribute(BooleanAttribute.PARSE_ALLOW_WHITESPACE));
4763        assertFalse("ALLOW_NUMERIC  after setLenient(FALSE)", fmt.getBooleanAttribute(BooleanAttribute.PARSE_ALLOW_NUMERIC));
4764        // These two boolean attributes are NOT affected according to the API specification
4765        assertTrue("PARTIAL_MATCH after setLenient(FALSE)", fmt.getBooleanAttribute(BooleanAttribute.PARSE_PARTIAL_MATCH));
4766        assertTrue("MULTIPLE_PATTERNS after setLenient(FALSE)", fmt.getBooleanAttribute(BooleanAttribute.PARSE_MULTIPLE_PATTERNS_FOR_MATCH));
4767
4768        // Allow white space leniency
4769        fmt.setBooleanAttribute(BooleanAttribute.PARSE_ALLOW_WHITESPACE, true);
4770
4771        assertFalse("isLeninent after ALLOW_WHITESPACE/TRUE", fmt.isLenient());
4772        assertFalse("isCalendarLenient after ALLOW_WHITESPACE/TRUE", fmt.isCalendarLenient());
4773        assertTrue("ALLOW_WHITESPACE after ALLOW_WHITESPACE/TRUE", fmt.getBooleanAttribute(BooleanAttribute.PARSE_ALLOW_WHITESPACE));
4774        assertFalse("ALLOW_NUMERIC  after ALLOW_WHITESPACE/TRUE", fmt.getBooleanAttribute(BooleanAttribute.PARSE_ALLOW_NUMERIC));
4775
4776        // Set to lenient
4777        fmt.setLenient(true);
4778
4779        assertTrue("isLenient after setLenient(TRUE)", fmt.isLenient());
4780        assertTrue("isCalendarLenient after setLenient(TRUE)", fmt.isCalendarLenient());
4781        assertTrue("ALLOW_WHITESPACE after setLenient(TRUE)", fmt.getBooleanAttribute(BooleanAttribute.PARSE_ALLOW_WHITESPACE));
4782        assertTrue("ALLOW_NUMERIC after setLenient(TRUE)", fmt.getBooleanAttribute(BooleanAttribute.PARSE_ALLOW_NUMERIC));
4783
4784    }
4785}
4786