17935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/*
27935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Copyright (C) 2001-2010, International Business Machines Corporation and    *
47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * others. All Rights Reserved.                                                *
57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/**
97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Port From:   ICU4C v1.8.1 : format : DateFormatRoundTripTest
107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Source File: $ICU4CRoot/source/test/intltest/dtfmtrtts.cpp
117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert **/
127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.dev.test.format;
147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.FieldPosition;
167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.ParseException;
177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Date;
187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Locale;
197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Random;
207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.DateFormat;
227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.SimpleDateFormat;
237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.Calendar;
247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.GregorianCalendar;
257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.TimeZone;
267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/**
287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Performs round-trip tests for DateFormat
297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert **/
307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpublic class DateFormatRoundTripTest extends com.ibm.icu.dev.test.TestFmwk {
317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public boolean INFINITE = false;
327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public boolean quick = true;
337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private SimpleDateFormat dateFormat;
347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private Calendar getFieldCal;
357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int SPARSENESS = 18;
367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int TRIALS = 4;
377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int DEPTH = 5;
387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private Random ran;
397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public static void main(String[] args) throws Exception {
417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        new DateFormatRoundTripTest().run(args);
427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void TestDateFormatRoundTrip() {
457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        dateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss.SSS zzz yyyy G");
467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        getFieldCal = Calendar.getInstance();
477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ran = createRandom(); // use test framework's random seed
487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        final Locale[] avail = DateFormat.getAvailableLocales();
507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int locCount = avail.length;
517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("DateFormat available locales: " + locCount);
527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (quick) {
537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (locCount > 5)
547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                locCount = 5;
557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("Quick mode: only testing first 5 Locales");
567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        TimeZone tz = TimeZone.getDefault();
587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("Default TimeZone:             " + tz.getID());
597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (INFINITE) {
617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Special infinite loop test mode for finding hard to reproduce errors
627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            Locale loc = Locale.getDefault();
637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("ENTERING INFINITE TEST LOOP FOR Locale: " + loc.getDisplayName());
647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (;;) {
657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                _test(loc);
667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            _test(Locale.getDefault());
697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (int i = 0; i < locCount; ++i) {
707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                _test(avail[i]);
717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public String styleName(int s) {
767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        switch (s) {
777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case DateFormat.SHORT :
787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return "SHORT";
797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case DateFormat.MEDIUM :
807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return "MEDIUM";
817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case DateFormat.LONG :
827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return "LONG";
837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case DateFormat.FULL :
847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return "FULL";
857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            default :
867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return "Unknown";
877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void _test(Locale loc) {
917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (!INFINITE) {
927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("Locale: " + loc.getDisplayName());
937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Total possibilities = 24
957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        //  4 date
967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        //  4 time
977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        //  16 date-time
987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean[] TEST_TABLE = new boolean[24];
997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int i = 0;
1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (i = 0; i < 24; ++i)
1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            TEST_TABLE[i] = true;
1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // If we have some sparseness, implement it here.  Sparseness decreases
1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // test time by eliminating some tests, up to 23.
1057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (i = 0; i < SPARSENESS; i++) {
1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int random = (int) (ran.nextDouble() * 24);
1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (random >= 0 && random < 24 && TEST_TABLE[i]) {
1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                TEST_TABLE[random] = false;
1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int itable = 0;
1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int style = 0;
1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (style = DateFormat.FULL; style <= DateFormat.SHORT; ++style) {
1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (TEST_TABLE[itable++]) {
1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                logln("Testing style " + styleName(style));
1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                DateFormat df = DateFormat.getDateInstance(style, loc);
1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                _test(df, false);
1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (style = DateFormat.FULL; style <= DateFormat.SHORT; ++style) {
1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (TEST_TABLE[itable++]) {
1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                logln("Testing style " + styleName(style));
1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                DateFormat  df = DateFormat.getTimeInstance(style, loc);
1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                _test(df, true);
1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (int dstyle = DateFormat.FULL; dstyle <= DateFormat.SHORT; ++dstyle) {
1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (int tstyle = DateFormat.FULL; tstyle <= DateFormat.SHORT; ++tstyle) {
1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (TEST_TABLE[itable++]) {
1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    logln("Testing dstyle " + styleName(dstyle) + ", tstyle " + styleName(tstyle));
1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    DateFormat df = DateFormat.getDateTimeInstance(dstyle, tstyle, loc);
1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    _test(df, false);
1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void _test(DateFormat fmt, boolean timeOnly) {
1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (!(fmt instanceof SimpleDateFormat)) {
1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            errln("DateFormat wasn't a SimpleDateFormat");
1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return;
1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String pat = ((SimpleDateFormat) fmt).toPattern();
1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln(pat);
1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // NOTE TO MAINTAINER
1527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // This indexOf check into the pattern needs to be refined to ignore
1537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // quoted characters.  Currently, this isn't a problem with the locale
1547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // patterns we have, but it may be a problem later.
1557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean hasEra = (pat.indexOf("G") != -1);
1577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean hasZoneDisplayName = (pat.indexOf("z") != -1) || (pat.indexOf("v") != -1) || (pat.indexOf("V") != -1);
1587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Because patterns contain incomplete data representing the Date,
1607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // we must be careful of how we do the roundtrip.  We start with
1617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // a randomly generated Date because they're easier to generate.
1627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // From this we get a string.  The string is our real starting point,
1637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // because this string should parse the same way all the time.  Note
1647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // that it will not necessarily parse back to the original date because
1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // of incompleteness in patterns.  For example, a time-only pattern won't
1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // parse back to the same date.
1677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        try {
1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (int i = 0; i < TRIALS; ++i) {
1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                Date[] d = new Date[DEPTH];
1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                String[] s = new String[DEPTH];
1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                d[0] = generateDate();
1747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // We go through this loop until we achieve a match or until
1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // the maximum loop count is reached.  We record the points at
1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // which the date and the string starts to match.  Once matching
1787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // starts, it should continue.
1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int loop;
1807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int dmatch = 0; // d[dmatch].getTime() == d[dmatch-1].getTime()
1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int smatch = 0; // s[smatch].equals(s[smatch-1])
1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                for (loop = 0; loop < DEPTH; ++loop) {
1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (loop > 0) {
1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        d[loop] = fmt.parse(s[loop - 1]);
1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    s[loop] = fmt.format(d[loop]);
1887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (loop > 0) {
1907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (smatch == 0) {
1917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            boolean match = s[loop].equals(s[loop - 1]);
1927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (smatch == 0) {
1937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (match)
1947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    smatch = loop;
1957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            } else
1967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (!match)
1977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    errln("FAIL: String mismatch after match");
1987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
1997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (dmatch == 0) {
2017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // {sfb} watch out here, this might not work
2027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            boolean match = d[loop].getTime() == d[loop - 1].getTime();
2037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (dmatch == 0) {
2047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (match)
2057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    dmatch = loop;
2067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            } else
2077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (!match)
2087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    errln("FAIL: Date mismatch after match");
2097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
2107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (smatch != 0 && dmatch != 0)
2127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
2137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
2147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
2157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // At this point loop == DEPTH if we've failed, otherwise loop is the
2167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // max(smatch, dmatch), that is, the index at which we have string and
2177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // date matching.
2187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // Date usually matches in 2.  Exceptions handled below.
2207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int maxDmatch = 2;
2217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int maxSmatch = 1;
2227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (dmatch > maxDmatch || smatch > maxSmatch) {
2237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    //If the Date is BC
2247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (!timeOnly && !hasEra && getField(d[0], Calendar.ERA) == GregorianCalendar.BC) {
2257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        maxDmatch = 3;
2267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        maxSmatch = 2;
2277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
2287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (hasZoneDisplayName &&
2297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            (fmt.getTimeZone().inDaylightTime(d[0])
2307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    || fmt.getTimeZone().inDaylightTime(d[1])
2317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    || d[0].getTime() < 0L /* before 1970 */)) {
2327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        maxSmatch = 2;
2337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (timeOnly) {
2347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            maxDmatch = 3;
2357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
2367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
2377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
2387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (dmatch > maxDmatch || smatch > maxSmatch) {
2407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    SimpleDateFormat sdf = new SimpleDateFormat("EEEE, MMMM d, yyyy HH:mm:ss, z G", Locale.US);
2417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    logln("Date = " + sdf.format(d[0]) + "; ms = " + d[0].getTime());
2427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    logln("Dmatch: " + dmatch + " maxD: " + maxDmatch + " Smatch:" + smatch + " maxS:" + maxSmatch);
2437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    for (int j = 0; j <= loop && j < DEPTH; ++j) {
2447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        StringBuffer temp = new StringBuffer("");
2457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        FieldPosition pos = new FieldPosition(0);
2467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        logln((j > 0 ? " P> " : "    ") + dateFormat.format(d[j], temp, pos)
2477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            + " F> " + s[j] + (j > 0 && d[j].getTime() == d[j - 1].getTime() ? " d==" : "")
2487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            + (j > 0 && s[j].equals(s[j - 1]) ? " s==" : ""));
2497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
2507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    errln("Pattern: " + pat + " failed to match" + "; ms = " + d[0].getTime());
2517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
2527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } catch (ParseException e) {
2547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            errln("Exception: " + e.getMessage());
2557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln(e.toString());
2567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int getField(Date d, int f) {
2607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        getFieldCal.setTime(d);
2617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int ret = getFieldCal.get(f);
2627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return ret;
2637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public Date generateDate() {
2667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        double a = ran.nextDouble();
2677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Now 'a' ranges from 0..1; scale it to range from 0 to 8000 years
2687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        a *= 8000;
2697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Range from (4000-1970) BC to (8000-1970) AD
2707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        a -= 4000;
2717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Now scale up to ms
2727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        a *= 365.25 * 24 * 60 * 60 * 1000;
2737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return new Date((long)a);
2747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert}
276