
// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
/*
 *******************************************************************************
 * Copyright (C) 2001-2016, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */

/**
 * Port From:   ICU4C v1.8.1 : format : DateIntervalFormatTest
 * Source File: $ICU4CRoot/source/test/intltest/dtifmtts.cpp
 **/

package com.ibm.icu.dev.test.format;

import java.text.FieldPosition;
import java.text.ParseException;
import java.text.ParsePosition;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

import com.ibm.icu.dev.test.TestFmwk;
import com.ibm.icu.impl.Utility;
import com.ibm.icu.text.ConstrainedFieldPosition;
import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.DateIntervalFormat;
import com.ibm.icu.text.DateIntervalFormat.FormattedDateInterval;
import com.ibm.icu.text.DateIntervalInfo;
import com.ibm.icu.text.DateIntervalInfo.PatternInfo;
import com.ibm.icu.text.SimpleDateFormat;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.DateInterval;
import com.ibm.icu.util.Output;
import com.ibm.icu.util.TimeZone;
import com.ibm.icu.util.ULocale;

@RunWith(JUnit4.class)
public class DateIntervalFormatTest extends TestFmwk {

    /**
     *
     */
    private static final ULocale SPANISH = new ULocale("es");
    /**
     *
     */
    private static final ULocale LA_SPANISH = new ULocale("es-419");

    /**
     * Test format
     */
    @Test
    public void TestFormat() {
        // first item is date pattern
        // followed by a group of locale/from_data/to_data/skeleton/interval_data
        // Note that from_data/to_data are specified using era names from root, for the calendar specified by locale.
        String[] DATA = {
                "GGGGG y MM dd HH:mm:ss", // pattern for from_data/to_data
                // test root
                "root", "CE 2007 11 10 10:10:10", "CE 2007 12 10 10:10:10", "yM", "2007-11 \\u2013 2007-12",

                // test 'H' and 'h', using availableFormat in fallback
                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 10 15:10:10", "Hms", "10:10:10 \\u2013 15:10:10",
                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 10 15:10:10", "hms", "10:10:10 AM \\u2013 3:10:10 PM",

                // test skeleton with both date and time
                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMMMyhm", "Nov 10, 2007, 10:10 AM \\u2013 Nov 20, 2007, 10:10 AM",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 10 11:10:10", "dMMMyhm", "Nov 10, 2007, 10:10 \\u2013 11:10 AM",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 10 11:10:10", "hms", "10:10:10 AM \\u2013 11:10:10 AM",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EEEEdMMMMy", "Wednesday, October 10, 2007 \\u2013 Friday, October 10, 2008",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dMMMMy", "October 10, 2007 \\u2013 October 10, 2008",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dMMMM", "October 10, 2007 \\u2013 October 10, 2008",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "MMMMy", "October 2007 \\u2013 October 2008",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EEEEdMMMM", "Wednesday, October 10, 2007 \\u2013 Friday, October 10, 2008",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EdMMMy", "Wed, Oct 10, 2007 \\u2013 Fri, Oct 10, 2008",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dMMMy", "Oct 10, 2007 \\u2013 Oct 10, 2008",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dMMM", "Oct 10, 2007 \\u2013 Oct 10, 2008",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "MMMy", "Oct 2007 \\u2013 Oct 2008",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EdMMM", "Wed, Oct 10, 2007 \\u2013 Fri, Oct 10, 2008",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EdMy", "Wed, 10/10/2007 \\u2013 Fri, 10/10/2008",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dMy", "10/10/2007 \\u2013 10/10/2008",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dM", "10/10/2007 \\u2013 10/10/2008",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "My", "10/2007 \\u2013 10/2008",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EdM", "Wed, 10/10/2007 \\u2013 Fri, 10/10/2008",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "d", "10/10/2007 \\u2013 10/10/2008",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "Ed", "10 Wed \\u2013 10 Fri",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "y", "2007 \\u2013 2008",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "M", "10/2007 \\u2013 10/2008",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "MMM", "Oct 2007 \\u2013 Oct 2008",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "MMMM", "October 2007 \\u2013 October 2008",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hm", "10/10/2007, 10:10 AM \\u2013 10/10/2008, 10:10 AM",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hmv", "10/10/2007, 10:10 AM PT \\u2013 10/10/2008, 10:10 AM PT",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hmz", "10/10/2007, 10:10 AM PDT \\u2013 10/10/2008, 10:10 AM PDT",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "h", "10/10/2007, 10 AM \\u2013 10/10/2008, 10 AM",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hv", "10/10/2007, 10 AM PT \\u2013 10/10/2008, 10 AM PT",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hz", "10/10/2007, 10 AM PDT \\u2013 10/10/2008, 10 AM PDT",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EEddMMyyyy", "Wed, 10/10/2007 \\u2013 Fri, 10/10/2008",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EddMMy", "Wed, 10/10/2007 \\u2013 Fri, 10/10/2008",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hhmm", "10/10/2007, 10:10 AM \\u2013 10/10/2008, 10:10 AM",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hhmmzz", "10/10/2007, 10:10 AM PDT \\u2013 10/10/2008, 10:10 AM PDT",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hms", "10/10/2007, 10:10:10 AM \\u2013 10/10/2008, 10:10:10 AM",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dMMMMMy", "O 10, 2007 \\u2013 O 10, 2008",

                "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EEEEEdM", "W, 10/10/2007 \\u2013 F, 10/10/2008",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EEEEdMMMMy", "Wednesday, October 10 \\u2013 Saturday, November 10, 2007",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dMMMMy", "October 10 \\u2013 November 10, 2007",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dMMMM", "October 10 \\u2013 November 10",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "MMMMy", "October \\u2013 November 2007",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EEEEdMMMM", "Wednesday, October 10 \\u2013 Saturday, November 10",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EdMMMy", "Wed, Oct 10 \\u2013 Sat, Nov 10, 2007",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dMMMy", "Oct 10 \\u2013 Nov 10, 2007",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dMMM", "Oct 10 \\u2013 Nov 10",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "MMMy", "Oct \\u2013 Nov 2007",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EdMMM", "Wed, Oct 10 \\u2013 Sat, Nov 10",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EdMy", "Wed, 10/10/2007 \\u2013 Sat, 11/10/2007",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dMy", "10/10/2007 \\u2013 11/10/2007",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dM", "10/10 \\u2013 11/10",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "My", "10/2007 \\u2013 11/2007",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EdM", "Wed, 10/10 \\u2013 Sat, 11/10",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "d", "10/10 \\u2013 11/10",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "Ed", "10 Wed \\u2013 10 Sat",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "y", "2007",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "M", "10 \\u2013 11",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "MMM", "Oct \\u2013 Nov",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "MMMM", "October \\u2013 November",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hm", "10/10/2007, 10:10 AM \\u2013 11/10/2007, 10:10 AM",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hmv", "10/10/2007, 10:10 AM PT \\u2013 11/10/2007, 10:10 AM PT",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hmz", "10/10/2007, 10:10 AM PDT \\u2013 11/10/2007, 10:10 AM PST",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "h", "10/10/2007, 10 AM \\u2013 11/10/2007, 10 AM",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hv", "10/10/2007, 10 AM PT \\u2013 11/10/2007, 10 AM PT",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hz", "10/10/2007, 10 AM PDT \\u2013 11/10/2007, 10 AM PST",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EEddMMyyyy", "Wed, 10/10/2007 \\u2013 Sat, 11/10/2007",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EddMMy", "Wed, 10/10/2007 \\u2013 Sat, 11/10/2007",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hhmm", "10/10/2007, 10:10 AM \\u2013 11/10/2007, 10:10 AM",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hhmmzz", "10/10/2007, 10:10 AM PDT \\u2013 11/10/2007, 10:10 AM PST",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hms", "10/10/2007, 10:10:10 AM \\u2013 11/10/2007, 10:10:10 AM",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dMMMMMy", "O 10 \\u2013 N 10, 2007",

                "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EEEEEdM", "W, 10/10 \\u2013 S, 11/10",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EEEEdMMMMy", "Saturday, November 10 \\u2013 Tuesday, November 20, 2007",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMMMMy", "November 10 \\u2013 20, 2007",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMMMM", "November 10 \\u2013 20",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "MMMMy", "November 2007",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EEEEdMMMM", "Saturday, November 10 \\u2013 Tuesday, November 20",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EdMMMy", "Sat, Nov 10 \\u2013 Tue, Nov 20, 2007",


                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMMM", "Nov 10 \\u2013 20",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "MMMy", "Nov 2007",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EdMMM", "Sat, Nov 10 \\u2013 Tue, Nov 20",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EdMy", "Sat, 11/10/2007 \\u2013 Tue, 11/20/2007",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMy", "11/10/2007 \\u2013 11/20/2007",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dM", "11/10 \\u2013 11/20",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "My", "11/2007",
                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EdM", "Sat, 11/10 \\u2013 Tue, 11/20",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "d", "10 \\u2013 20",
                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "Ed", "10 Sat \\u2013 20 Tue",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "M", "11",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "MMM", "Nov",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hm", "11/10/2007, 10:10 AM \\u2013 11/20/2007, 10:10 AM",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hmv", "11/10/2007, 10:10 AM PT \\u2013 11/20/2007, 10:10 AM PT",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hmz", "11/10/2007, 10:10 AM PST \\u2013 11/20/2007, 10:10 AM PST",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hz", "11/10/2007, 10 AM PST \\u2013 11/20/2007, 10 AM PST",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EEddMMyyyy", "Sat, 11/10/2007 \\u2013 Tue, 11/20/2007",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EddMMy", "Sat, 11/10/2007 \\u2013 Tue, 11/20/2007",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hhmm", "11/10/2007, 10:10 AM \\u2013 11/20/2007, 10:10 AM",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hms", "11/10/2007, 10:10:10 AM \\u2013 11/20/2007, 10:10:10 AM",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMMMMMy", "N 10 \\u2013 20, 2007",

                "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EEEEEdM", "S, 11/10 \\u2013 T, 11/20",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EEEEdMMMMy", "Wednesday, January 10, 2007",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "dMMMMy", "January 10, 2007",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "dMMMM", "January 10",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "MMMMy", "January 2007",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EEEEdMMMM", "Wednesday, January 10",


                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "dMMMy", "Jan 10, 2007",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "dMMM", "Jan 10",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "MMMy", "Jan 2007",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EdMMM", "Wed, Jan 10",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EdMy", "Wed, 1/10/2007",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "dMy", "1/10/2007",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "dM", "1/10",


                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EdM", "Wed, 1/10",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "d", "10",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "Ed", "10 Wed",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "y", "2007",


                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "MMM", "Jan",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "MMMM", "January",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hm", "10:00 AM \\u2013 2:10 PM",


                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hmz", "10:00 AM \\u2013 2:10 PM PST",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "h", "10 AM \\u2013 2 PM",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hv", "10 AM \\u2013 2 PM PT",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hz", "10 AM \\u2013 2 PM PST",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EEddMMyyyy", "Wed, 01/10/2007",


                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hhmm", "10:00 AM \\u2013 2:10 PM",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hhmmzz", "10:00 AM \\u2013 2:10 PM PST",


                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "dMMMMMy", "J 10, 2007",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EEEEEdM", "W, 1/10",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "EEEEdMMMMy", "Wednesday, January 10, 2007",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "dMMMMy", "January 10, 2007",


                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "MMMMy", "January 2007",


                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "EdMMMy", "Wed, Jan 10, 2007",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "dMMMy", "Jan 10, 2007",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "dMMM", "Jan 10",


                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "EdMMM", "Wed, Jan 10",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "EdMy", "Wed, 1/10/2007",


                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "dM", "1/10",


                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "EdM", "Wed, 1/10",



                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "y", "2007",


                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "MMM", "Jan",


                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hm", "10:00 \\u2013 10:20 AM",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hmv", "10:00 \\u2013 10:20 AM PT",


                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "h", "10 AM",


                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hz", "10 AM PST",


                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "EddMMy", "Wed, 01/10/2007",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hhmm", "10:00 \\u2013 10:20 AM",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hhmmzz", "10:00 \\u2013 10:20 AM PST",

                "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hms", "10:00:10 AM \\u2013 10:20:10 AM",

                "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "dMMMM", "January 10",

                "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "EEEEdMMMM", "Wednesday, January 10",

                "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "EdMMMy", "Wed, Jan 10, 2007",

                "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "dMMM", "Jan 10",

                "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "EdMMM", "Wed, Jan 10",
                "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "dM", "1/10",

                "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "My", "1/2007",

                "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "EdM", "Wed, 1/10",
                "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "d", "10",

                "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "Ed", "10 Wed",

                "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "y", "2007",

                "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "M", "1",

                "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "MMM", "Jan",

                "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "MMMM", "January",

                "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hm", "10:10 AM",

                "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hmv", "10:10 AM PT",

                "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hmz", "10:10 AM PST",

                "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "h", "10 AM",


                "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hz", "10 AM PST",

                "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hhmmzz", "10:10 AM PST",

                "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hms", "10:10:10 AM \u2013 10:10:20 AM",

                "en", "CE 2007 01 01 22:00:00", "CE 2007 01 01 23:00:00", "yMMMMdHm", "January 1, 2007, 22:00 \u2013 23:00",

                "zh", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EEEEdMMMMy", "2007\\u5e7410\\u670810\\u65e5\\u661f\\u671f\\u4e09\\u81f32008\\u5e7410\\u670810\\u65e5\\u661f\\u671f\\u4e94",

                "zh", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hm", "2007/10/10 \\u4e0a\\u534810:10 \\u2013 2008/10/10 \\u4e0a\\u534810:10",

                "zh", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dMMMMy", "2007\\u5e7410\\u670810\\u65e5\\u81f311\\u670810\\u65e5",

                "zh", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dMMMM", "10\\u670810\\u65e5\\u81f311\\u670810\\u65e5",

                "zh", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "MMMMy", "2007\\u5e7410\\u6708\\u81f311\\u6708",

                "zh", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EEEEdMMMM", "10\\u670810\\u65e5\\u661f\\u671f\\u4e09\\u81f311\\u670810\\u65e5\\u661f\\u671f\\u516d",

                "zh", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hmv", "2007/10/10 \\u6D1B\\u6749\\u77F6\\u65F6\\u95F4 \\u4E0A\\u534810:10 \\u2013 2007/11/10 \\u6D1B\\u6749\\u77F6\\u65F6\\u95F4 \\u4E0A\\u534810:10",

                "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EEEEdMMMMy", "2007\\u5e7411\\u670810\\u65e5\\u661f\\u671f\\u516d\\u81f320\\u65e5\\u661f\\u671f\\u4e8c",

                "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMMMMy", "2007\\u5e7411\\u670810\\u65e5\\u81f320\\u65e5",

                "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMMMM", "11\\u670810\\u65e5\\u81f320\\u65e5",

                "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "MMMMy", "2007\\u5E7411\\u6708", // (fixed expected result per ticket 6872<-6626)

                "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EEEEdMMMM", "11\\u670810\\u65e5\\u661f\\u671f\\u516d\\u81f320\\u65e5\\u661f\\u671f\\u4e8c",

                "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EdMMM", "11\\u670810\\u65e5\\u5468\\u516d\\u81f320\\u65e5\\u5468\\u4e8c",

                "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EdMy", "2007/11/10\\u5468\\u516d\\u81f32007/11/20\\u5468\\u4e8c",

                "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMy", "2007/11/10 \\u2013 2007/11/20",

                "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dM", "11/10 \\u2013 11/20",

                "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "My", "2007\u5E7411\u6708",
                "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EdM", "11/10\\u5468\\u516d\\u81f311/20\\u5468\\u4e8c",

                "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "d", "10\\u201320\\u65e5",

                "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "y", "2007\\u5E74", // (fixed expected result per ticket:6626:)

                "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "M", "11\\u6708",

                "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "MMM", "11\\u6708", // (fixed expected result per ticket 6872<-6626 and others)

                "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "MMMM", "\\u5341\\u4E00\\u6708", // (fixed expected result per ticket 6872<-6626 and others)

                "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hmz", "2007/11/10 GMT-8 \\u4e0a\\u534810:10 \\u2013 2007/11/20 GMT-8 \\u4e0a\\u534810:10",

                "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "h", "2007/11/10 \\u4e0a\\u534810\\u65f6 \\u2013 2007/11/20 \\u4e0a\\u534810\\u65f6",

                "zh", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EEEEdMMMMy", "2007\\u5e741\\u670810\\u65e5\\u661f\\u671f\\u4e09", // (fixed expected result per ticket 6872<-6626)

                "zh", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hm", "\\u4e0a\\u534810:00\\u81f3\\u4e0b\\u53482:10",

                "zh", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hmv", "\\u6D1B\\u6749\\u77F6\\u65F6\\u95F4\\u4E0A\\u534810:00\\u81F3\\u4E0B\\u53482:10",

                "zh", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hmz", "GMT-8\\u4e0a\\u534810:00\\u81f3\\u4e0b\\u53482:10",

                "zh", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "h", "\\u4e0a\\u534810\\u65F6\\u81f3\\u4e0b\\u53482\\u65f6",

                "zh", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hv", "\\u6D1B\\u6749\\u77F6\\u65F6\\u95F4\\u4E0A\\u534810\\u65F6\\u81F3\\u4E0B\\u53482\\u65F6",

                "zh", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hz", "GMT-8\\u4e0a\\u534810\\u65F6\\u81f3\\u4e0b\\u53482\\u65f6",

                "zh", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "dMMMM", "1\\u670810\\u65e5", // (fixed expected result per ticket 6872<-6626)

                "zh", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hm", "\\u4e0a\\u534810:00\\u81f310:20",

                "zh", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hmv", "\\u6D1B\\u6749\\u77F6\\u65F6\\u95F4\\u4E0A\\u534810:00\\u81F310:20",

                "zh", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "h", "\\u4e0a\\u534810\\u65f6",

                "zh", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hz", "GMT-8\\u4e0a\\u534810\\u65f6",

                "zh", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "EEEEdMMMMy", "2007\\u5e741\\u670810\\u65e5\\u661f\\u671f\\u4e09", // (fixed expected result per ticket 6872<-6626)

                "zh", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hm", "\\u4e0a\\u534810:10",

                "zh", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "h", "\\u4e0a\\u534810\\u65f6",

                "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EEEEdMMMy", "Mittwoch, 10. Okt. 2007 \\u2013 Freitag, 10. Okt. 2008",

                "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dMMMy", "10. Okt. 2007 \\u2013 10. Okt. 2008",

                "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dMMM", "10. Okt. 2007 \\u2013 10. Okt. 2008",

                "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "MMMy", "Okt. 2007 \\u2013 Okt. 2008",

                "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EEEdMMM", "Mi., 10. Okt. 2007 \\u2013 Fr., 10. Okt. 2008",

                "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EdMy", "Mi., 10.10.2007 \\u2013 Fr., 10.10.2008",

                "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dMy", "10.10.2007 \\u2013 10.10.2008",

                "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dM", "10.10.2007 \\u2013 10.10.2008",

                "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "My", "10.2007 \\u2013 10.2008",

                "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EdM", "Mi., 10.10.2007 \\u2013 Fr., 10.10.2008",

                "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "d", "10.10.2007 \\u2013 10.10.2008",

                "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "y", "2007\\u20132008",

                "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "M", "10.2007 \\u2013 10.2008",

                "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "MMM", "Okt. 2007 \\u2013 Okt. 2008",

                "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hm", "10.10.2007, 10:10 AM \\u2013 10.10.2008, 10:10 AM",

                "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "jm", "10.10.2007, 10:10 \\u2013 10.10.2008, 10:10",

                "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EEEEdMMMy", "Mittwoch, 10. Okt. \\u2013 Samstag, 10. Nov. 2007",

                "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dMMMy", "10. Okt. \\u2013 10. Nov. 2007",

                "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dMMM", "10. Okt. \\u2013 10. Nov.",

                "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "MMMy", "Okt.\\u2013Nov. 2007",

                "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EEEEdMMM", "Mittwoch, 10. Okt. \\u2013 Samstag, 10. Nov.",

                "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EdMy", "Mi., 10.10. \\u2013 Sa., 10.11.2007",

                "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dM", "10.10. \\u2013 10.11.",

                "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "My", "10.2007 \\u2013 11.2007",

                "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EdM", "Mi., 10.10. \\u2013 Sa., 10.11.",

                "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "d", "10.10. \\u2013 10.11.",


                "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "M", "10.\\u201311.",

                "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "MMM", "Okt.\\u2013Nov.",

                "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hmv", "10.10.2007, 10:10 AM Los Angeles Zeit \\u2013 10.11.2007, 10:10 AM Los Angeles Zeit",

                "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "jmv", "10.10.2007, 10:10 Los Angeles Zeit \\u2013 10.11.2007, 10:10 Los Angeles Zeit",

                "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hms", "10.10.2007, 10:10:10 AM \\u2013 10.11.2007, 10:10:10 AM",

                "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EEEEdMMMy", "Samstag, 10. \\u2013 Dienstag, 20. Nov. 2007",

                "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMMMy", "10.\\u201320. Nov. 2007",

                "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMMM", "10.\\u201320. Nov.",

                "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "MMMy", "Nov. 2007",

                "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EEEEdMMM", "Samstag, 10. \\u2013 Dienstag, 20. Nov.",

                "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EdMy", "Sa., 10. \\u2013 Di., 20.11.2007",

                "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMy", "10.\\u201320.11.2007",

                "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dM", "10.\\u201320.11.",

                "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "My", "11.2007",

                "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EdM", "Sa., 10. \\u2013 Di., 20.11.",

                "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "d", "10.\\u201320.",

                "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "y", "2007",

                "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "M", "11",

                "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hmv", "10.11.2007, 10:10 AM Los Angeles Zeit \\u2013 20.11.2007, 10:10 AM Los Angeles Zeit",

                "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "jmv", "10.11.2007, 10:10 Los Angeles Zeit \\u2013 20.11.2007, 10:10 Los Angeles Zeit",

                "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EEEEdMMMy", "Mittwoch, 10. Jan. 2007",

                "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "dMMMy", "10. Jan. 2007",

                "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "dMMM", "10. Jan.",

                "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "MMMy", "Jan. 2007",

                "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EEEEdMMM", "Mittwoch, 10. Jan.",

                "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hmz", "10:00 AM \\u2013 2:10 PM GMT-8",

                "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "h", "10 Uhr AM \\u2013 2 Uhr PM",

                "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "EEEEdMMM", "Mittwoch, 10. Jan.",

                "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hm", "10:00\\u201310:20 AM",

                "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hmv", "10:00\\u201310:20 AM Los Angeles Zeit",

                "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hmz", "10:00\\u201310:20 AM GMT-8",

                "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "h", "10 Uhr AM",

                "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hv", "10 Uhr AM Los Angeles Zeit",

                "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hz", "10 Uhr AM GMT-8",

                "de", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "EEEEdMMMy", "Mittwoch, 10. Jan. 2007",

                "de", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hm", "10:10 AM",

                "de", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "jm", "10:10",

                "de", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hmv", "10:10 AM Los Angeles Zeit",

                "de", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "jmv", "10:10 Los Angeles Zeit",

                "de", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hmz", "10:10 AM GMT-8",

                "de", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "jmz", "10:10 GMT-8",

                "de", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "h", "10 Uhr AM",

                "de", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hv", "10 Uhr AM Los Angeles Zeit",

                "de", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hz", "10 Uhr AM GMT-8",

                // Thai (default calendar buddhist)

                "th", "BE 2550 10 10 10:10:10", "BE 2551 10 10 10:10:10", "EEEEdMMMy", "\\u0E27\\u0E31\\u0E19\\u0E1E\\u0E38\\u0E18\\u0E17\\u0E35\\u0E48 10 \\u0E15.\\u0E04. 2550 \\u2013 \\u0E27\\u0E31\\u0E19\\u0E28\\u0E38\\u0E01\\u0E23\\u0E4C\\u0E17\\u0E35\\u0E48 10 \\u0E15.\\u0E04. 2551",


                "th", "BE 2550 10 10 10:10:10", "BE 2551 10 10 10:10:10", "dMMM", "10 \\u0E15.\\u0E04. 2550 \\u2013 10 \\u0E15.\\u0E04. 2551",

                "th", "BE 2550 10 10 10:10:10", "BE 2551 10 10 10:10:10", "MMMy", "\\u0E15.\\u0E04. 2550 \\u2013 \\u0E15.\\u0E04. 2551",


                "th", "BE 2550 10 10 10:10:10", "BE 2551 10 10 10:10:10", "EdMy", "\\u0E1E. 10/10/2550 \\u2013 \\u0E28. 10/10/2551",

                "th", "BE 2550 10 10 10:10:10", "BE 2551 10 10 10:10:10", "dMy", "10/10/2550 \\u2013 10/10/2551",


                "th", "BE 2550 10 10 10:10:10", "BE 2551 10 10 10:10:10", "My", "10/2550 \\u2013 10/2551",

                "th", "BE 2550 10 10 10:10:10", "BE 2551 10 10 10:10:10", "EdM", "\\u0E1E. 10/10/2550 \\u2013 \\u0E28. 10/10/2551",


                "th", "BE 2550 10 10 10:10:10", "BE 2551 10 10 10:10:10", "y", "2550\\u20132551",

                "th", "BE 2550 10 10 10:10:10", "BE 2551 10 10 10:10:10", "M", "10/2550 \\u2013 10/2551",


                "th", "BE 2550 10 10 10:10:10", "BE 2550 11 10 10:10:10", "EEEEdMMMy", "\\u0E27\\u0E31\\u0E19\\u0E1E\\u0E38\\u0E18\\u0E17\\u0E35\\u0E48 10 \\u0E15.\\u0E04. \\u2013 \\u0E27\\u0E31\\u0E19\\u0E40\\u0E2A\\u0E32\\u0E23\\u0E4C\\u0E17\\u0E35\\u0E48 10 \\u0E1E.\\u0E22. 2550",


                "th", "BE 2550 10 10 10:10:10", "BE 2550 11 10 10:10:10", "dMMM", "10 \\u0E15.\\u0E04. \\u2013 10 \\u0E1E.\\u0E22.",

                "th", "BE 2550 10 10 10:10:10", "BE 2550 11 10 10:10:10", "MMMy", "\\u0E15.\\u0E04.\\u2013\\u0E1E.\\u0E22. 2550",

                "th", "BE 2550 10 10 10:10:10", "BE 2550 11 10 10:10:10", "dM", "10/10 \\u2013 10/11",

                "th", "BE 2550 10 10 10:10:10", "BE 2550 11 10 10:10:10", "My", "10/2550 \\u2013 11/2550",


                "th", "BE 2550 10 10 10:10:10", "BE 2550 11 10 10:10:10", "d", "10/10 \\u2013 10/11",

                "th", "BE 2550 10 10 10:10:10", "BE 2550 11 10 10:10:10", "y", "\u0E1E.\u0E28. 2550",


                "th", "BE 2550 10 10 10:10:10", "BE 2550 11 10 10:10:10", "MMM", "\u0E15.\u0E04.\u2013\u0E1E.\u0E22.",

                // Tests for Japanese calendar with eras, including new era in 2019 (Heisei 31 through April 30, then new era)

                "en-u-ca-japanese", "H 31 03 15 09:00:00", "H 31 04 15 09:00:00", "GyMMMd", "Mar 15 \u2013 Apr 15, 31 Heisei",

                "en-u-ca-japanese", "H 31 03 15 09:00:00", "H 31 04 15 09:00:00", "GGGGGyMd", "3/15/31 \u2013 4/15/31 H",

                "en-u-ca-japanese", "S 64 01 05 09:00:00", "H 1 01 15 09:00:00",  "GyMMMd", "Jan 5, 64 Sh\u014Dwa \u2013 Jan 15, 1 Heisei",

                "en-u-ca-japanese", "S 64 01 05 09:00:00", "H 1 01 15 09:00:00",  "GGGGGyMd", "1/5/64 S \u2013 1/15/1 H",

                "en-u-ca-japanese", "H 31 04 15 09:00:00", DateFormat.JP_ERA_2019_NARROW+" 1 05 15 09:00:00",  "GyMMMd", "Apr 15, 31 Heisei \u2013 May 15, 1 "+DateFormat.JP_ERA_2019_ROOT,

                "en-u-ca-japanese", "H 31 04 15 09:00:00", DateFormat.JP_ERA_2019_NARROW+" 1 05 15 09:00:00",  "GGGGGyMd", "4/15/31 H \u2013 5/15/1 "+DateFormat.JP_ERA_2019_NARROW,


                "ja-u-ca-japanese", "H 31 03 15 09:00:00", "H 31 04 15 09:00:00", "GyMMMd", "\u5E73\u621031\u5E743\u670815\u65E5\uFF5E4\u670815\u65E5",

                "ja-u-ca-japanese", "H 31 03 15 09:00:00", "H 31 04 15 09:00:00", "GGGGGyMd", "H31/03/15\uFF5E31/04/15",

                "ja-u-ca-japanese", "S 64 01 05 09:00:00", "H 1 01 15 09:00:00",  "GyMMMd", "\u662D\u548C64\u5E741\u67085\u65E5\uFF5E\u5E73\u6210\u5143\u5E741\u670815\u65E5",

                "ja-u-ca-japanese", "S 64 01 05 09:00:00", "H 1 01 15 09:00:00",  "GGGGGyMd", "S64/01/05\uFF5EH1/01/15",

                "ja-u-ca-japanese", "H 31 04 15 09:00:00", DateFormat.JP_ERA_2019_NARROW+" 1 05 15 09:00:00", "GGGGGyMd", "H31/04/15\uFF5E"+DateFormat.JP_ERA_2019_NARROW+"1/05/15",

        };
        expect(DATA, DATA.length);
    }


    private void expect(String[] data, int data_length) {
        int i = 0;
        String pattern = data[i++];

        while (i<data_length) {
            String locName = data[i++];
            String datestr = data[i++];
            String datestr_2 = data[i++];

            ULocale loc = new ULocale(locName);
            Calendar defCal = Calendar.getInstance(loc);
            String calType = defCal.getType();

            ULocale refLoc = ULocale.ROOT.setKeywordValue("calendar", calType);
            SimpleDateFormat ref = new SimpleDateFormat(pattern, refLoc);
            // 'f'
            Date date, date_2;
            try {
                date = ref.parse(datestr);
                date_2 = ref.parse(datestr_2);
            } catch ( ParseException e ) {
                errln("parse exception" + e);
                i += 2; // skip the rest of the strings for this item
                continue;
            }
            DateInterval dtitv = new DateInterval(date.getTime(),
                    date_2.getTime());
            String oneSkeleton = data[i++];
            DateIntervalFormat dtitvfmt = DateIntervalFormat.getInstance(
                    oneSkeleton, loc);
            String expected = data[i++];
            String formatted = dtitvfmt.format(dtitv);
            if ( !formatted.equals(Utility.unescape(expected)) )  {
                errln("\"" + locName + "\\" + oneSkeleton + "\\" + datestr + "\\" + datestr_2 + "\"\t expected: " + expected +"\tgot: " + formatted + "\n");
            }
        }
    }


    /*
     * Test format using user defined DateIntervalInfo
     */
    @Test
    public void TestFormatUserDII() {
        // first item is date pattern
        // followed by a group of locale/from_data/to_data/interval_data
        String[] DATA = {
                "yyyy MM dd HH:mm:ss",
                "en", "2007 10 10 10:10:10", "2008 10 10 10:10:10", "Oct 10, 2007 --- Oct 10, 2008",

                "en", "2007 10 10 10:10:10", "2007 11 10 10:10:10", "2007 Oct 10 - Nov 2007",

                "en", "2007 11 10 10:10:10", "2007 11 20 10:10:10", "Nov 10, 2007 --- Nov 20, 2007",

                "en", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "Jan 10, 2007",

                "en", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "Jan 10, 2007",

                "en", "2007 01 10 10:10:10", "2007 01 10 10:10:20", "Jan 10, 2007",

                "zh", "2007 10 10 10:10:10", "2008 10 10 10:10:10", "2007\\u5e7410\\u670810\\u65e5 --- 2008\\u5e7410\\u670810\\u65e5",


                "zh", "2007 11 10 10:10:10", "2007 11 20 10:10:10", "2007\\u5e7411\\u670810\\u65e5 --- 2007\\u5e7411\\u670820\\u65e5",

                "zh", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "2007\\u5e741\\u670810\\u65e5", // (fixed expected result per ticket 6872<-6626)

                "zh", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "2007\\u5e741\\u670810\\u65e5", // (fixed expected result per ticket 6872<-6626)

                "zh", "2007 01 10 10:10:10", "2007 01 10 10:10:20", "2007\\u5e741\\u670810\\u65e5", // (fixed expected result per ticket 6872<-6626)

                "de", "2007 10 10 10:10:10", "2008 10 10 10:10:10", "10. Okt. 2007 --- 10. Okt. 2008",

                "de", "2007 10 10 10:10:10", "2007 11 10 10:10:10", "2007 Okt. 10 - Nov. 2007",

                "de", "2007 11 10 10:10:10", "2007 11 20 10:10:10", "10. Nov. 2007 --- 20. Nov. 2007",

                "de", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "10. Jan. 2007",

                "de", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "10. Jan. 2007",

                "de", "2007 01 10 10:10:10", "2007 01 10 10:10:20", "10. Jan. 2007",

                "es", "2007 10 10 10:10:10", "2008 10 10 10:10:10", "10 oct. 2007 --- 10 oct. 2008",

                "es", "2007 10 10 10:10:10", "2007 11 10 10:10:10", "2007 oct. 10 - nov. 2007",

                "es", "2007 11 10 10:10:10", "2007 11 20 10:10:10", "10 nov. 2007 --- 20 nov. 2007",

                "es", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "10 ene. 2007",

                "es", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "10 ene. 2007",

                "es", "2007 01 10 10:10:10", "2007 01 10 10:10:20", "10 ene. 2007",
        };
        expectUserDII(DATA, DATA.length);
    }


    private void expectUserDII(String[] data, int data_length) {
        int i = 1;
        while (i<data_length) {
            String locName = data[i++];
            ULocale loc = new ULocale(locName);
            SimpleDateFormat ref = new SimpleDateFormat(data[0], loc);
            // 'f'
            String datestr = data[i++];
            String datestr_2 = data[i++];
            Date date, date_2;
            try {
                date = ref.parse(datestr);
                date_2 = ref.parse(datestr_2);
            } catch ( ParseException e ) {
                errln("parse exception" + e);
                continue;
            }
            DateInterval dtitv = new DateInterval(date.getTime(),
                    date_2.getTime());

            DateIntervalInfo dtitvinf = new DateIntervalInfo();
            dtitvinf.setFallbackIntervalPattern("{0} --- {1}");
            dtitvinf.setIntervalPattern("yMMMd", Calendar.MONTH, "yyyy MMM d - MMM y");
            dtitvinf.setIntervalPattern("yMMMd", Calendar.HOUR_OF_DAY, "yyyy MMM d HH:mm - HH:mm");
            DateIntervalFormat dtitvfmt = DateIntervalFormat.getInstance(
                    DateFormat.YEAR_ABBR_MONTH_DAY,
                    loc, dtitvinf);
            String expected = data[i++];
            String formatted = dtitvfmt.format(dtitv);
            if ( !formatted.equals(Utility.unescape(expected)) )  {
                errln("userDII: \"" + locName + "\\" + datestr + "\\" + datestr_2 + "\"\t expected: " + expected +"\tgot: " + formatted + "\n");
            }
        }
    }



    /*
     * Test format using user defined DateIntervalInfo
     */
    @Test
    public void TestFormatCLDR() {
        // first item is date pattern
        // followed by a group of locale/from_data/to_data/interval_data
        String[] DATA = {
                "yyyy MM dd HH:mm:ss",
                "en", "2007 10 10 10:10:10", "2008 10 10 10:10:10", "all diff",

                "en", "2007 10 10 10:10:10", "2007 11 10 10:10:10", "2007 diff Oct 10 - Nov 2007",

                "en", "2007 11 10 10:10:10", "2007 11 20 10:10:10", "2007 Nov 10 ~ 20",

                "en", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "Jan 10, 2007",

                "en", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "Jan 10, 2007",

                "en", "2007 01 10 10:10:10", "2007 01 10 10:10:20", "Jan 10, 2007",

                "zh", "2007 10 10 10:10:10", "2008 10 10 10:10:10", "all diff",

                "zh", "2007 10 10 10:10:10", "2007 11 10 10:10:10", "2007 diff 10\\u6708 10 - 11\\u6708 2007",

                "zh", "2007 11 10 10:10:10", "2007 11 20 10:10:10", "2007 11\\u6708 10 ~ 20",

                "zh", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "2007\u5E741\\u670810\u65E5", // (fixed expected result per ticket 6872<-6626)

                "zh", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "2007\u5E741\\u670810\u65E5", // (fixed expected result per ticket 6872<-6626)

                "zh", "2007 01 10 10:10:10", "2007 01 10 10:10:20", "2007\u5E741\\u670810\u65E5", // (fixed expected result per ticket 6872<-6626)
        };
        expectUserCLDR(DATA, DATA.length);
    }


    private void expectUserCLDR(String[] data, int data_length) {
        int i = 1;
        while (i<data_length) {
            String locName = data[i++];
            ULocale loc = new ULocale(locName);
            SimpleDateFormat ref = new SimpleDateFormat(data[0], loc);
            // 'f'
            String datestr = data[i++];
            String datestr_2 = data[i++];
            Date date, date_2;
            try {
                date = ref.parse(datestr);
                date_2 = ref.parse(datestr_2);
            } catch ( ParseException e ) {
                errln("parse exception" + e);
                continue;
            }
            DateInterval dtitv = new DateInterval(date.getTime(),
                    date_2.getTime());

            DateIntervalFormat dtitvfmt = DateIntervalFormat.getInstance("yyyyMMMdd", loc);
            //DateIntervalFormat dtitvfmt = DateIntervalFormat.getInstance("yMd");
            //SimpleDateFormat dtfmt = new SimpleDateFormat("yyyy 'year' MMM 'month' dd 'day'", loc);
            //dtitvfmt.setDateFormat(dtfmt);
            DateIntervalInfo dtitvinf = new DateIntervalInfo();
            dtitvinf.setFallbackIntervalPattern("{0} --- {1}");
            dtitvinf.setIntervalPattern("yMMMd", Calendar.YEAR, "'all diff'");
            dtitvinf.setIntervalPattern("yMMMd", Calendar.MONTH, "yyyy 'diff' MMM d - MMM y");
            dtitvinf.setIntervalPattern("yMMMd", Calendar.DATE, "yyyy MMM d ~ d");
            dtitvinf.setIntervalPattern("yMMMd", Calendar.HOUR_OF_DAY, "yyyy MMMd HH:mm ~ HH:mm");
            dtitvfmt.setDateIntervalInfo(dtitvinf);
            FieldPosition pos = new FieldPosition(0);
            StringBuffer str = new StringBuffer("");
            DateFormat dtfmt = dtitvfmt.getDateFormat();
            Calendar fromCalendar = (Calendar) dtfmt.getCalendar().clone();
            Calendar toCalendar = (Calendar) dtfmt.getCalendar().clone();
            fromCalendar.setTimeInMillis(dtitv.getFromDate());
            toCalendar.setTimeInMillis(dtitv.getToDate());
            dtitvfmt.format(fromCalendar, toCalendar, str, pos);

            String expected = data[i++];
            String formatted = dtitvfmt.format(dtitv).toString();
            if ( !formatted.equals(Utility.unescape(expected)) )  {
                errln("CLDR: \"" + locName + "\\" + datestr + "\\" + datestr_2 + "\"\t expected: " + expected +"\tgot: " + formatted + "\n");
            }
        }
    }


    /**
     * Stress test
     */
    @Test
    public void TestStress() {
        if (TestFmwk.getExhaustiveness() <= 5) {
            logln("INFO: Skipping test");
            return;
        }

        // test data.
        // The 1st is the format pattern,
        // Next are pairs in which the 1st in the pair is the earlier date
        // and the 2nd in the pair is the later date
        String[] DATA = {
                "yyyy MM dd HH:mm:ss",
                "2007 10 10 10:10:10", "2008 10 10 10:10:10",
                "2007 10 10 10:10:10", "2007 11 10 10:10:10",
                "2007 11 10 10:10:10", "2007 11 20 10:10:10",
                "2007 01 10 10:00:10", "2007 01 10 14:10:10",
                "2007 01 10 10:00:10", "2007 01 10 10:20:10",
                "2007 01 10 10:10:10", "2007 01 10 10:10:20",
        };


        String[][] testLocale = {
                {"en", "", ""},
                {"zh", "", ""},
                {"de", "", ""},
                {"ar", "", ""},
                {"en", "GB",  ""},
                {"fr", "", ""},
                {"it", "", ""},
                {"nl", "", ""},
                {"zh", "TW",  ""},
                {"ja", "", ""},
                {"pt", "BR", ""},
                {"ru", "", ""},
                {"tr", "", ""},
                {"es", "", ""},
                {"ko", "", ""},
                //{"th", "", ""},
                {"sv", "", ""},
                {"pl", "", ""},
                {"fi", "", ""},
                {"da", "", ""},
                {"pt", "PT", ""},
                {"ro", "", ""},
                {"hu", "", ""},
                {"he", "", ""},
                {"in", "", ""},
                {"cs", "", ""},
                {"el", "", ""},
                {"no", "", ""},
                {"vi", "", ""},
                {"bg", "", ""},
                {"hr", "", ""},
                {"lt", "", ""},
                {"sk", "", ""},
                {"sl", "", ""},
                {"sr", "", ""},
                {"ca", "", ""},
                {"lv", "", ""},
                {"uk", "", ""},
                {"hi", "", ""},
        };

        int localeIndex;
        for ( localeIndex = 0; localeIndex < testLocale.length; ++localeIndex) {
            stress(DATA, DATA.length, new Locale(testLocale[localeIndex][0],
                    testLocale[localeIndex][1], testLocale[localeIndex][2]),
                    testLocale[localeIndex][0]+testLocale[localeIndex][1]);
        }
    }

    private void stress(String[] data, int data_length, Locale loc, String locName) {
        String[] skeleton = {
                "EEEEdMMMMy",
                "dMMMMy",
                "dMMMM",
                "MMMMy",
                "EEEEdMMMM",
                "EEEdMMMy",
                "dMMMy",
                "dMMM",
                "MMMy",
                "EEEdMMM",
                "EEEdMy",
                "dMy",
                "dM",
                "My",
                "EEEdM",
                "d",
                "EEEd",
                "y",
                "M",
                "MMM",
                "MMMM",
                "hm",
                "hmv",
                "hmz",
                "h",
                "hv",
                "hz",
                "EEddMMyyyy", // following could be normalized
                "EddMMy",
                "hhmm",
                "hhmmzz",
                "hms",  // following could not be normalized
                "dMMMMMy",
                "EEEEEdM",
        };

        int i = 0;

        SimpleDateFormat ref = new SimpleDateFormat(data[i++], loc);

        while (i<data_length) {
            // 'f'
            String datestr = data[i++];
            String datestr_2 = data[i++];
            Date date;
            Date date_2;
            try {
                date = ref.parse(datestr);
                date_2 = ref.parse(datestr_2);
            } catch ( ParseException e ) {
                errln("parse exception" + e);
                continue;
            }
            DateInterval dtitv = new DateInterval(date.getTime(), date_2.getTime());

            for ( int skeletonIndex = 0;
                    skeletonIndex < skeleton.length;
                    ++skeletonIndex ) {
                String oneSkeleton = skeleton[skeletonIndex];
                // need special handle of "Thai" since the default calendar
                // of "Thai" is "Budd", not "Gregorian".
                DateIntervalFormat dtitvfmt = DateIntervalFormat.getInstance(oneSkeleton, loc);
                /*
                if ( locName.equals("th") ) {
                    // reset calendar to be Gregorian
                    GregorianCalendar gregCal = new GregorianCalendar(loc);
                    DateFormat dformat = dtitvfmt.getDateFormat();
                    DateFormat newOne = (DateFormat)dformat.clone();
                    newOne.setCalendar(gregCal);
                    dtitvfmt.setDateFormat(newOne);
                }
                 */
                dtitvfmt.format(dtitv);
            }


            // test interval format by algorithm
            for ( int style = DateFormat.FULL; style  < 4; ++style ) {
                SimpleDateFormat dtfmt = (SimpleDateFormat) DateFormat.getDateInstance(style, loc);
                FieldPosition pos = new FieldPosition(0);
                StringBuffer str = new StringBuffer("");
                Calendar fromCalendar = (Calendar) dtfmt.getCalendar().clone();
                Calendar toCalendar = (Calendar) dtfmt.getCalendar().clone();
                fromCalendar.setTimeInMillis(dtitv.getFromDate());
                toCalendar.setTimeInMillis(dtitv.getToDate());
                dtfmt.intervalFormatByAlgorithm(fromCalendar, toCalendar, str, pos);
            }
        }
    }

    /*
     * Ticket#6396 DateIntervalInfo of ICU4J 4.0d3 throw NullPointerException
     */
    @Test
    public void TestT6396() {
        DateIntervalInfo dii = new DateIntervalInfo(new ULocale("th_TH"));
        try {
            // ticket#6396 reported toString() throws NullPointerException
            String diiStr = dii.toString();
            logln("new DateIntervalInfo(new ULocale(\"th_TH\")).toString() - " + diiStr);

            // equals also had the similar problem
            DateIntervalInfo dii1 = (DateIntervalInfo)dii.clone();
            if (!dii.equals(dii1)) {
                errln("FAIL: Cloned DateIntervalInfo is not equal to the source");
            }
        } catch (Exception e) {
            errln("FAIL: Exception - " + e.getClass().getName());
        }
    }

    @Test
    public void TestConstructor() {
        DateIntervalInfo diiJapan = new DateIntervalInfo(ULocale.JAPAN);
        DateIntervalInfo diiJapanJ = new DateIntervalInfo(Locale.JAPAN);

        assertEquals("DateIntervalInfo constructors", diiJapan, diiJapanJ);
    }

    /* Tests the method
     *      public boolean equals(Object a)
     */
    @Test
    public void TestDateIntervalInfoEquals(){
        // Tests when "if ( a instanceof PatternInfo )" is false
        DateIntervalInfo diia = new DateIntervalInfo();
        if(diia.equals("dummy")){
            errln("DateIntervalInfo.equals(Object a) was suppose to return " +
                    "false for a String object.");
        }
        if(diia.equals(0)){
            errln("DateIntervalInfo.equals(Object a) was suppose to return " +
                    "false for an Integer object.");
        }
        if(diia.equals(0.0)){
            errln("DateIntervalInfo.equals(Object a) was suppose to return " +
                    "false for an Integer object.");
        }
        if(diia.equals(new Object())){
            errln("DateIntervalInfo.equals(Object a) was suppose to return " +
                    "false for an Integer object.");
        }
    }

    /* Tests the method
     *      public Object cloneAsThawed()
     */
    @Test
    public void TestCloseAsThawed(){
        DateIntervalInfo dii = new DateIntervalInfo();
        try{
            dii.cloneAsThawed();
        } catch(Exception e){
            errln("DateIntervalInfo.closeAsThawed() was not suppose to return " +
                    "an exception.");
        }
    }

    /* Tests the method
     *      public boolean isFrozen()
     */
    @Test
    public void TestIsFrozen(){
        DateIntervalInfo dii = new DateIntervalInfo();
        if(dii.isFrozen() != false){
            errln("DateIntervalInfo.isFrozen() is suppose to return false.");
        }
        dii.freeze();

        if(dii.isFrozen() != true){
            errln("DateIntervalInfo.isFrozen() is suppose to return true.");
        }
    }

    /* Tests the method
     *      public boolean clone()
     */
    @Test
    public void TestClone(){
        DateIntervalInfo dii = new DateIntervalInfo(new ULocale("en_US"));
        DateIntervalInfo dii_clone = (DateIntervalInfo) dii.clone();
        dii_clone.freeze();

        // Tests when "if ( frozen )" is true
        if(!dii.equals(dii_clone)){
            errln("DateIntervalInfo.clone() is suppose to return true for " +
                    "an original DateIntervalInfo object and a clone of the " +
                    "original DateIntervalInfo object.");
        }
    }

    /* Tests the method
     *      public void setFallbackIntervalPattern(String fallbackPattern)
     */
    @Test
    public void TestSetFallbackIntervalPattern(){
        DateIntervalInfo dii = new DateIntervalInfo(new ULocale("en_US"));
        // Tests when "if ( frozen )" is true
        try{
            dii.freeze();
            dii.setFallbackIntervalPattern("");
            errln("DateIntervalInfo.setFallbackIntervalPattern(String fallbackPattern) " +
                    "was suppose to return an exception for a frozen object.");
        } catch (Exception e){}

        // Tests when "if ( firstPatternIndex == -1 || secondPatternIndex == -1 )" is true
        dii = dii.cloneAsThawed();
        try{
            dii.setFallbackIntervalPattern("");
            errln("DateIntervalInfo.setFallbackIntervalPattern(String fallbackPattern) " +
                    "was suppose to return an exception for a string object of ''.");
        } catch(Exception e){}

        try{
            dii.setFallbackIntervalPattern("0");
            errln("DateIntervalInfo.setFallbackIntervalPattern(String fallbackPattern) " +
                    "was suppose to return an exception for a string object of 0.");
        } catch(Exception e){}

        // Tests when "if ( firstPatternIndex > secondPatternIndex )" is true
        dii.setFallbackIntervalPattern("{1}{0}");
        if(dii.getDefaultOrder() != true)
            errln("DateIntervalInfo.setFallbackIntervalPattern(String fallbackPattern) " +
                    "was suppose to change the variable 'fFirstDateInPtnIsLaterDate' " +
                    "to true.");
    }

    /* Tests the method
     *      public PatternInfo getIntervalPattern(String skeleton, int field)
     */
    @Test
    public void TestGetIntervalPattern(){
        // Tests when "if ( field > MINIMUM_SUPPORTED_CALENDAR_FIELD )" is true
        // MINIMUM_SUPPORTED_CALENDAR_FIELD = Calendar.SECOND;
        DateIntervalInfo dii = new DateIntervalInfo();
        try{
            dii.getIntervalPattern("", Calendar.SECOND+1);
            errln("DateIntervalInfo.getIntervalPattern(String,int) was suppose " +
                    "to return an exception for the 'int field' parameter " +
                    "when it exceeds MINIMUM_SUPPORTED_CALENDAR_FIELD.");
        } catch(Exception e){}
    }

    /* Tests the method
     *      public void setIntervalPattern(String skeleton, int lrgDiffCalUnit, String intervalPattern)
     */
    @Test
    public void TestSetIntervalPattern(){
        DateIntervalInfo dii = new DateIntervalInfo();
        // Tests when "if ( frozen )" is true
        try{
            dii.freeze();
            dii.setIntervalPattern("", 0, "");
            errln("DateIntervalInfo.setIntervalPattern(String,int,String) " +
                    "was suppose to return an exception when the " +
                    "DateIntervalInfo object is frozen.");
        } catch(Exception e){}

        // Tests when "if ( lrgDiffCalUnit > MINIMUM_SUPPORTED_CALENDAR_FIELD )" is true
        // MINIMUM_SUPPORTED_CALENDAR_FIELD = Calendar.SECOND;
        try{
            dii = dii.cloneAsThawed();
            dii.setIntervalPattern("", Calendar.SECOND+1, "");
            errln("DateIntervalInfo.setIntervalPattern(String,int,String) " +
                    "was suppose to return an exception when the " +
                    "variable 'lrgDiffCalUnit' is greater than " +
                    "MINIMUM_SUPPORTED_CALENDAR_FIELD.");
        } catch(Exception e){}
    }

    @Test
    public void TestSetIntervalPatternNoSideEffect() {
        PatternInfo patternInfo = new DateIntervalInfo(ULocale.ENGLISH).getIntervalPattern("yMd", Calendar.DATE);
        String expectedPattern = patternInfo.getFirstPart() + patternInfo.getSecondPart();
        new DateIntervalInfo(ULocale.ENGLISH).setIntervalPattern(
                "yMd", Calendar.DATE, "M/d/y \u2013 d");
        patternInfo = new DateIntervalInfo(ULocale.ENGLISH).getIntervalPattern("yMd", Calendar.DATE);
        String actualPattern = patternInfo.getFirstPart() + patternInfo.getSecondPart();
        assertEquals(
                "setIntervalPattern should not have side effects",
                expectedPattern,
                actualPattern);
    }

    @Test
    public void TestGetSetTimeZone(){
        DateIntervalFormat dtitvfmt = DateIntervalFormat.getInstance("MMMdHHmm", Locale.ENGLISH);
        long date1 = 1299090600000L; // 2011-Mar-02 1030 in US/Pacific, 2011-Mar-03 0330 in Asia/Tokyo
        long date2 = 1299115800000L; // 2011-Mar-02 1730 in US/Pacific, 2011-Mar-03 1030 in Asia/Tokyo
        DateInterval dtitv = new DateInterval(date1, date2);
        TimeZone tzCalif = TimeZone.getFrozenTimeZone("US/Pacific");
        TimeZone tzTokyo = TimeZone.getFrozenTimeZone("Asia/Tokyo");
        String fmtCalif = "Mar 2, 10:30 \u2013 17:30"; // ICU4C result is "Mar 2, 10:30 \u2013 17:30" (does not duplicate day)
        String fmtTokyo = "Mar 3, 03:30 \u2013 10:30"; // ICU4C result is "Mar 3, 03:30 \u2013 10:30" (does not duplicate day)

        StringBuffer buf = new StringBuffer();
        FieldPosition pos = new FieldPosition(0);
        dtitvfmt.setTimeZone(tzCalif);
        dtitvfmt.format(dtitv, buf, pos);
        if (!buf.toString().equals(fmtCalif)) {
            errln("DateIntervalFormat for tzCalif, expect \"" + fmtCalif + "\", get \"" + buf + "\"");
        }

        buf.setLength(0);
        pos.setBeginIndex(0);
        dtitvfmt.setTimeZone(tzTokyo);
        dtitvfmt.format(dtitv, buf, pos);
        if (!buf.toString().equals(fmtTokyo)) {
            errln("DateIntervalFormat for tzTokyo, expect \"" + fmtTokyo + "\", get \"" + buf + "\"");
        }

        if (!dtitvfmt.getTimeZone().equals(tzTokyo)) {
            errln("DateIntervalFormat.getTimeZone() returns mismatch");
        }
    }


    /* Tests the method
     *      public int hashCode()
     */
    @Test
    public void TestHashCode(){
        // Tests when
        //      "int hash = fIntervalPatternFirstPart != null ? fIntervalPatternFirstPart.hashCode() : 0;"
        // is false
        PatternInfo dp = new PatternInfo(null, null, false);
        if(dp.hashCode() != 0){
            errln("PatternInfo.hashCode() was suppose to return 0 for a null " +
                    "paramter in the constructor.");
        }
    }

    /* Tests the method
     *      public boolean equals(Object a)
     * in PatternInfo
     */
    @Test
    public void TestPattternInfoEquals(){
        // Tests when "if ( a instanceof PatternInfo )" is false
        PatternInfo pi = new PatternInfo("","", false);
        if(pi.equals(new Object())){
            errln("PatternInfo.equals(Object) is suppose to return false " +
                    "when it is not an instance of PatternInfo.");
        }
        if(pi.equals("")){
            errln("PatternInfo.equals(Object) is suppose to return false " +
                    "when it is not an instance of PatternInfo.");
        }
        if(pi.equals(0)){
            errln("PatternInfo.equals(Object) is suppose to return false " +
                    "when it is not an instance of PatternInfo.");
        }
        if(pi.equals(0.0)){
            errln("PatternInfo.equals(Object) is suppose to return false " +
                    "when it is not an instance of PatternInfo.");
        }
    }

    @Test
    public void TestDateIntervalCoverage() {
        DateInterval di = new DateInterval(0, 1);

        if (di.equals("Test")) {
            errln("Comparison test should fail.");
        }

        if (di.toString() == null) {
            errln("toString should not return null.");
        }

        if (di.hashCode() != 1) {
            errln("hasCode() should return 1.");
        }
    }

    @Test
    public void testGetInstance_String_DateIntervalInfo() {
        DateIntervalInfo dateIntervalInfo = new DateIntervalInfo(new ULocale("ca"));
        DateIntervalFormat dateIntervalFormat = DateIntervalFormat.getInstance(
                DateFormat.YEAR_MONTH, Locale.ENGLISH, dateIntervalInfo);
        Calendar from = Calendar.getInstance();
        from.set(2000, Calendar.JANUARY, 1, 12, 0);
        Calendar to = Calendar.getInstance();
        to.set(2001, Calendar.FEBRUARY, 1, 12, 0);
        DateInterval interval = new DateInterval(from.getTimeInMillis(), to.getTimeInMillis());
        dateIntervalFormat.setTimeZone(from.getTimeZone());
        // Month names are default (English), format is Catalan
        assertEquals("Wrong date interval",
                "January de 2000 – February de 2001", dateIntervalFormat.format(interval));
    }

    @Test
    public void testGetInstance_String_Locale_DateIntervalInfo() {
        DateIntervalInfo dateIntervalInfo = new DateIntervalInfo(new ULocale("ca"));
        DateIntervalFormat dateIntervalFormat = DateIntervalFormat.getInstance(
                DateFormat.YEAR_MONTH, Locale.GERMAN, dateIntervalInfo);
        Calendar from = Calendar.getInstance();
        from.set(2000, Calendar.JANUARY, 1, 12, 0);
        Calendar to = Calendar.getInstance();
        to.set(2001, Calendar.FEBRUARY, 1, 12, 0);
        DateInterval interval = new DateInterval(from.getTimeInMillis(), to.getTimeInMillis());
        dateIntervalFormat.setTimeZone(from.getTimeZone());
        // Month names are German, format is Catalan
        assertEquals("Wrong date interval",
                "Januar de 2000 – Februar de 2001", dateIntervalFormat.format(interval));
    }

    @Test(expected = UnsupportedOperationException.class)
    public void testParseObject_notSupported() throws ParseException {
        DateIntervalFormat.getInstance(DateFormat.YEAR_MONTH).parseObject("");
    }

    @Test
    public void TestDateIntervalFormatCoverage() throws Exception{
        long date1 = 1299090600000L;
        long date2 = 1299115800000L;
        DateInterval dtitv = new DateInterval(date1, date2);
        DateIntervalFormat dtitvfmt = DateIntervalFormat.getInstance("MMMd", Locale.ENGLISH);
        DateIntervalInfo dtintinf = new DateIntervalInfo(ULocale.ENGLISH);

        // Check the default private constructor
        checkDefaultPrivateConstructor(DateIntervalFormat.class);

        // Check clone
        DateIntervalFormat dtitvfmtClone = (DateIntervalFormat) dtitvfmt.clone();
        assertEquals("DateIntervalFormat.clone() failed", dtitvfmt.format(dtitv), dtitvfmtClone.format(dtitv));

        // Coverage for getInstance
        assertNotNull("Expected DateIntervalFormat object", DateIntervalFormat.getInstance("MMMd", dtintinf));
        assertNotNull("Expected DateIntervalFormat object",
                DateIntervalFormat.getInstance("MMMdHHmm", Locale.ENGLISH, dtintinf));

        // Coverage for parseObject. Exception expected.
        try {
            dtitvfmt.parseObject("", new ParsePosition(0));
            errln("Exception was expected when calling DateIntervalFormat.parseObject()");
        } catch (Exception e) { /* No op */ }

        // Check getPatterns()
        Output<String> secondPart = new Output<>();
        Calendar fromCalendar = Calendar.getInstance(Locale.ENGLISH);
        fromCalendar.set(2016, 5, 22);
        Calendar toCalendar= Calendar.getInstance(Locale.ENGLISH);
        toCalendar.set(2016, 5, 23);
        assertEquals("Date interval pattern mismatch.",
                dtitvfmt.getPatterns(fromCalendar, toCalendar, secondPart), "MMM d – ");
        assertEquals("Date interval pattern mismatch.", secondPart.value, "d");
    }

    @Test
    public void TestTicket9919GetInstance() {
        // Creating a DateIntervalFormat with a custom DateIntervalInfo
        // object used to corrupt the cache.
        DateIntervalFormat dif = DateIntervalFormat.getInstance(
                "yMd", ULocale.ENGLISH);
        Calendar from = Calendar.getInstance();
        Calendar to = Calendar.getInstance();
        from.set(2013, 3, 26);
        to.set(2013, 3, 28);

        // Save. This is the correct answer
        String expected =
                dif.format(from, to, new StringBuffer(), new FieldPosition(0))
                .toString();

        // Now create a DateIntervalFormat with same skeleton and
        // locale, but with a custom DateIntervalInfo. This used
        // to corrupt the cache.
        DateIntervalInfo dateIntervalInfo =
                new DateIntervalInfo(ULocale.ENGLISH);
        dateIntervalInfo.setIntervalPattern(
                "yMd", Calendar.DATE, "M/d/y \u2013 d");
        DateIntervalFormat.getInstance(
                "yMd", ULocale.ENGLISH, dateIntervalInfo);

        // Now create a DateIntervalFormat with same skeleton and
        // locale, but with default DateIntervalInfo. The cache should
        // not be corrupted, and we should get the same answer as before.
        dif = DateIntervalFormat.getInstance("yMd", ULocale.ENGLISH);

        assertEquals(
                "Custom DateIntervalInfo objects should not mess up cache",
                expected,
                dif.format(from, to, new StringBuffer(), new FieldPosition(0))
                .toString());

    }

    @Test
    public void TestTicket9919Setter() {

        // Creating a DateIntervalFormat with a custom DateIntervalInfo
        // object used to corrupt the cache.
        DateIntervalFormat dif = DateIntervalFormat.getInstance(
                "yMd", ULocale.ENGLISH);
        Calendar from = Calendar.getInstance();
        Calendar to = Calendar.getInstance();
        from.set(2013, 3, 26);
        to.set(2013, 3, 28);

        // Save. This is the correct answer
        String expected =
                dif.format(from, to, new StringBuffer(), new FieldPosition(0))
                .toString();

        // Now create a DateIntervalFormat with same skeleton and
        // locale, but with a custom DateIntervalInfo. This used
        // to corrupt the cache.
        DateIntervalInfo dateIntervalInfo =
                new DateIntervalInfo(ULocale.ENGLISH);
        dateIntervalInfo.setIntervalPattern(
                "yMd", Calendar.DATE, "M/d/y \u2013 d");
        DateIntervalFormat bad = DateIntervalFormat.getInstance(
                "yMd", ULocale.ENGLISH);
        bad.setDateIntervalInfo(dateIntervalInfo);

        // Now create a DateIntervalFormat with same skeleton and
        // locale, but with default DateIntervalInfo. The cache should
        // not be corrupted, and we should get the same answer as before.
        dif = DateIntervalFormat.getInstance("yMd", ULocale.ENGLISH);
        assertEquals(
                "Custom DateIntervalInfo objects should not mess up cache",
                expected,
                dif.format(from, to, new StringBuffer(), new FieldPosition(0))
                .toString());
    }

    @Test
    public void TestTicket9914() {
        DateIntervalInfo dateIntervalInfo =
                new DateIntervalInfo(ULocale.ENGLISH);

        Calendar from = Calendar.getInstance();
        Calendar to = Calendar.getInstance();
        from.set(113, 3, 26);
        to.set(113, 3, 28);
        DateIntervalFormat dif = DateIntervalFormat.getInstance(
                "yyyyMd", ULocale.ENGLISH, dateIntervalInfo);
        assertEquals(
                "yyyyMd skeleton.",
                "4/26/0113 \u2013 4/28/0113",
                dif.format(from, to, new StringBuffer(), new FieldPosition(0))
                .toString());

        dif = DateIntervalFormat.getInstance(
                "yyMd", ULocale.ENGLISH, dateIntervalInfo);
        assertEquals(
                "yyMd skeleton.",
                "4/26/13 \u2013 4/28/13",
                dif.format(from, to, new StringBuffer(), new FieldPosition(0))
                .toString());

        dif = DateIntervalFormat.getInstance(
                "yMd", ULocale.ENGLISH, dateIntervalInfo);
        assertEquals(
                "yMd skeleton.",
                "4/26/113 \u2013 4/28/113",
                dif.format(from, to, new StringBuffer(), new FieldPosition(0))
                .toString());
    }

    @Test
    public void TestTicket11583 () {
        ULocale[] locales = {
                ULocale.ENGLISH,
                SPANISH,
                LA_SPANISH,
                };
        String[] skeletons = {
                "yMMMMd", "yMMMM", "MMMM",
                "yMMMd", "yMMM", "MMM",
                "yMMd", "yMMdd", "yMM", "MM",
                "yMdd", "yMd", "yM", "M"
                };

        final long startDate = 1232364615000L;
        final long endDate = 1240399815000L;
        String filterPattern = null ; // "yMMM";

        for (ULocale locale : locales) {
            for (String skeleton : skeletons) {
                if (filterPattern != null && !skeleton.equals(filterPattern)) {
                    continue;
                }

                DateFormat dateFormat = DateFormat.getPatternInstance(skeleton, locale);
                String dateFormatPattern = ((SimpleDateFormat)dateFormat).toPattern();

                DateIntervalFormat intervalFormat = DateIntervalFormat.getInstance(skeleton, locale);
                DateIntervalInfo intervalInfo = intervalFormat.getDateIntervalInfo();

                if (skeleton.equals(filterPattern)) {
                    logln(filterPattern + " => " + intervalInfo.getRawPatterns().get(filterPattern));
                }

                DateInterval date_interval = new DateInterval(startDate, endDate);

                String interval = intervalFormat.format(date_interval);

                String formattedStart = dateFormat.format(startDate);
                String formattedEnd = dateFormat.format(endDate);

                PatternInfo patternInfo = intervalFormat.getRawPatterns().get("M");

                String firstPart = patternInfo.getFirstPart();
                String secondPart = patternInfo.getSecondPart();
                if (!matches(dateFormatPattern, firstPart, secondPart)) {
                    if (logKnownIssue("11585", "incompatible pattern between date format and date interval format")) {
                        logln("For skeleton " + skeleton + "/locale " + locale + ": mismatch between date format «"
                                + dateFormatPattern + "» and date interval format «" + firstPart + secondPart + "».");
                    } else {
                        errln("For skeleton " + skeleton + "/locale " + locale + ": mismatch between date format «"
                                + dateFormatPattern + "» and date interval format «" + firstPart + secondPart + "».");
                    }
                }

                logln(locale
                        + "\tskeleton: «" + skeleton
                        + "»\tpattern: «" + dateFormatPattern
                        + "»\tintervalPattern1: «" + firstPart
                        + "»\tintervalPattern2: «" + secondPart
                        + "»\tstartDate: «" + formattedStart
                        + "»\tendDate: «" + formattedEnd
                        + "»\tinterval: «" + interval
                        + "»"
                        );
            }
        }
    }


    /**
     * Return true if for some x, y: dateFormatPattern = firstPart(0,x) + secondPart(y, secondPart.length())
     * @param dateFormatPattern
     * @param firstPart
     * @param secondPart
     * @return
     */
    private boolean matches(String dateFormatPattern, String firstPart, String secondPart) {
        // brute force for now
        int lastButOne = dateFormatPattern.length()-1;
        for (int i = 1; i < lastButOne; ++i) {
            if (firstPart.startsWith(dateFormatPattern.substring(0,i))
                    && secondPart.endsWith(dateFormatPattern.substring(i,dateFormatPattern.length()))) {
                return true;
            }
        }
        return false;
    }

    @Test
    public void TestFPos_SkelWithSeconds () {

        final long[] deltas = {
	        0L, // none
	        200L, // 200 millisec
	        20000L, // 20 sec
	        1200000L, // 20 min
	        7200000L, // 2 hrs
	        43200000L, // 12 hrs
	        691200000L, // 8 days
	        1382400000L, // 16 days,
	        8640000000L, // 100 days
        };

        class ExpectPosAndFormat {
            public int posBegin;
            public int posEnd;
            public String format;
             // Simple constructor
            public ExpectPosAndFormat(int pBegin, int pEnd, String fmt) {
                posBegin = pBegin;
                posEnd = pEnd;
                format = fmt;
            }
        };

        final ExpectPosAndFormat[] exp_en_HHmm = {
            new ExpectPosAndFormat(  3,  5, "09:00" ),
            new ExpectPosAndFormat(  3,  5, "09:00" ),
            new ExpectPosAndFormat(  3,  5, "09:00" ),
            new ExpectPosAndFormat(  3,  5, "09:00 \u2013 09:20" ),
            new ExpectPosAndFormat(  3,  5, "09:00 \u2013 11:00" ),
            new ExpectPosAndFormat(  3,  5, "09:00 \u2013 21:00" ),
            new ExpectPosAndFormat( 15, 17, "11/20/2014, 09:00 \u2013 11/28/2014, 09:00" ),
            new ExpectPosAndFormat( 15, 17, "11/20/2014, 09:00 \u2013 12/6/2014, 09:00" ),
            new ExpectPosAndFormat( 15, 17, "11/20/2014, 09:00 \u2013 2/28/2015, 09:00" )
        };

        final ExpectPosAndFormat[] exp_en_HHmmss = {
            new ExpectPosAndFormat(  3,  5, "09:00:00" ),
            new ExpectPosAndFormat(  3,  5, "09:00:00" ),
            new ExpectPosAndFormat(  3,  5, "09:00:00 \u2013 09:00:20" ),
            new ExpectPosAndFormat(  3,  5, "09:00:00 \u2013 09:20:00" ),
            new ExpectPosAndFormat(  3,  5, "09:00:00 \u2013 11:00:00" ),
            new ExpectPosAndFormat(  3,  5, "09:00:00 \u2013 21:00:00" ),
            new ExpectPosAndFormat( 15, 17, "11/20/2014, 09:00:00 \u2013 11/28/2014, 09:00:00" ),
            new ExpectPosAndFormat( 15, 17, "11/20/2014, 09:00:00 \u2013 12/6/2014, 09:00:00" ),
            new ExpectPosAndFormat( 15, 17, "11/20/2014, 09:00:00 \u2013 2/28/2015, 09:00:00" )
        };

        final ExpectPosAndFormat[] exp_en_yyMMdd = {
            new ExpectPosAndFormat(  0,  0, "11/20/14" ),
            new ExpectPosAndFormat(  0,  0, "11/20/14" ),
            new ExpectPosAndFormat(  0,  0, "11/20/14" ),
            new ExpectPosAndFormat(  0,  0, "11/20/14" ),
            new ExpectPosAndFormat(  0,  0, "11/20/14" ),
            new ExpectPosAndFormat(  0,  0, "11/20/14" ),
            new ExpectPosAndFormat(  0,  0, "11/20/14 \u2013 11/28/14" ),
            new ExpectPosAndFormat(  0,  0, "11/20/14 \u2013 12/6/14" ),
            new ExpectPosAndFormat(  0,  0, "11/20/14 \u2013 2/28/15" )
        };

        final ExpectPosAndFormat[] exp_en_yyMMddHHmm = {
            new ExpectPosAndFormat( 13, 15, "11/20/14, 09:00" ),
            new ExpectPosAndFormat( 13, 15, "11/20/14, 09:00" ),
            new ExpectPosAndFormat( 13, 15, "11/20/14, 09:00" ),
            new ExpectPosAndFormat( 13, 15, "11/20/14, 09:00 \u2013 09:20" ),
            new ExpectPosAndFormat( 13, 15, "11/20/14, 09:00 \u2013 11:00" ),
            new ExpectPosAndFormat( 13, 15, "11/20/14, 09:00 \u2013 21:00" ),
            new ExpectPosAndFormat( 13, 15, "11/20/14, 09:00 \u2013 11/28/14, 09:00" ),
            new ExpectPosAndFormat( 13, 15, "11/20/14, 09:00 \u2013 12/06/14, 09:00" ),
            new ExpectPosAndFormat( 13, 15, "11/20/14, 09:00 \u2013 02/28/15, 09:00" )
        };

        final ExpectPosAndFormat[] exp_en_yyMMddHHmmss = {
            new ExpectPosAndFormat( 13, 15, "11/20/14, 09:00:00" ),
            new ExpectPosAndFormat( 13, 15, "11/20/14, 09:00:00" ),
            new ExpectPosAndFormat( 13, 15, "11/20/14, 09:00:00 \u2013 09:00:20" ),
            new ExpectPosAndFormat( 13, 15, "11/20/14, 09:00:00 \u2013 09:20:00" ),
            new ExpectPosAndFormat( 13, 15, "11/20/14, 09:00:00 \u2013 11:00:00" ),
            new ExpectPosAndFormat( 13, 15, "11/20/14, 09:00:00 \u2013 21:00:00" ),
            new ExpectPosAndFormat( 13, 15, "11/20/14, 09:00:00 \u2013 11/28/14, 09:00:00" ),
            new ExpectPosAndFormat( 13, 15, "11/20/14, 09:00:00 \u2013 12/06/14, 09:00:00" ),
            new ExpectPosAndFormat( 13, 15, "11/20/14, 09:00:00 \u2013 02/28/15, 09:00:00" )
        };

        @SuppressWarnings("unused")
        final ExpectPosAndFormat[] exp_en_yMMMdhmmssz = {
            new ExpectPosAndFormat( 16, 18, "Nov 20, 2014, 9:00:00 AM GMT" ),
            new ExpectPosAndFormat( 16, 18, "Nov 20, 2014, 9:00:00 AM GMT" ),
            new ExpectPosAndFormat( 16, 18, "Nov 20, 2014, 9:00:00 AM GMT \u2013 9:00:20 AM GMT" ),
            new ExpectPosAndFormat( 16, 18, "Nov 20, 2014, 9:00:00 AM GMT \u2013 9:20:00 AM GMT" ),
            new ExpectPosAndFormat( 16, 18, "Nov 20, 2014, 9:00:00 AM GMT \u2013 11:00:00 AM GMT" ),
            new ExpectPosAndFormat( 16, 18, "Nov 20, 2014, 9:00:00 AM GMT \u2013 9:00:00 PM GMT" ),
            new ExpectPosAndFormat( 16, 18, "Nov 20, 2014, 9:00:00 AM GMT \u2013 Nov 28, 2014, 9:00:00 AM GMT" ),
            new ExpectPosAndFormat( 16, 18, "Nov 20, 2014, 9:00:00 AM GMT \u2013 Dec 6, 2014, 9:00:00 AM GMT" ),
            new ExpectPosAndFormat( 16, 18, "Nov 20, 2014, 9:00:00 AM GMT \u2013 Feb 28, 2015, 9:00:00 AM GMT" )
        };

        final ExpectPosAndFormat[] exp_ja_yyMMddHHmm = {
            new ExpectPosAndFormat( 11, 13, "14/11/20 9:00" ),
            new ExpectPosAndFormat( 11, 13, "14/11/20 9:00" ),
            new ExpectPosAndFormat( 11, 13, "14/11/20 9:00" ),
            new ExpectPosAndFormat( 11, 13, "14/11/20 9\u664200\u5206\uFF5E9\u664220\u5206" ),
            new ExpectPosAndFormat( 11, 13, "14/11/20 9\u664200\u5206\uFF5E11\u664200\u5206" ),
            new ExpectPosAndFormat( 11, 13, "14/11/20 9\u664200\u5206\uFF5E21\u664200\u5206" ),
            new ExpectPosAndFormat( 11, 13, "14/11/20 9:00\uFF5E14/11/28 9:00" ),
            new ExpectPosAndFormat( 11, 13, "14/11/20 9:00\uFF5E14/12/06 9:00" ),
            new ExpectPosAndFormat( 11, 13, "14/11/20 9:00\uFF5E15/02/28 9:00" )
        };

        final ExpectPosAndFormat[] exp_ja_yyMMddHHmmss = {
            new ExpectPosAndFormat( 11, 13, "14/11/20 9:00:00" ),
            new ExpectPosAndFormat( 11, 13, "14/11/20 9:00:00" ),
            new ExpectPosAndFormat( 11, 13, "14/11/20 9:00:00\uFF5E9:00:20" ),
            new ExpectPosAndFormat( 11, 13, "14/11/20 9:00:00\uFF5E9:20:00" ),
            new ExpectPosAndFormat( 11, 13, "14/11/20 9:00:00\uFF5E11:00:00" ),
            new ExpectPosAndFormat( 11, 13, "14/11/20 9:00:00\uFF5E21:00:00" ),
            new ExpectPosAndFormat( 11, 13, "14/11/20 9:00:00\uFF5E14/11/28 9:00:00" ),
            new ExpectPosAndFormat( 11, 13, "14/11/20 9:00:00\uFF5E14/12/06 9:00:00" ),
            new ExpectPosAndFormat( 11, 13, "14/11/20 9:00:00\uFF5E15/02/28 9:00:00" )
        };

        final ExpectPosAndFormat[] exp_ja_yMMMdHHmmss = {
            new ExpectPosAndFormat( 14, 16, "2014\u5E7411\u670820\u65E5 9:00:00" ),
            new ExpectPosAndFormat( 14, 16, "2014\u5E7411\u670820\u65E5 9:00:00" ),
            new ExpectPosAndFormat( 14, 16, "2014\u5E7411\u670820\u65E5 9:00:00\uFF5E9:00:20" ),
            new ExpectPosAndFormat( 14, 16, "2014\u5E7411\u670820\u65E5 9:00:00\uFF5E9:20:00" ),
            new ExpectPosAndFormat( 14, 16, "2014\u5E7411\u670820\u65E5 9:00:00\uFF5E11:00:00" ),
            new ExpectPosAndFormat( 14, 16, "2014\u5E7411\u670820\u65E5 9:00:00\uFF5E21:00:00" ),
            new ExpectPosAndFormat( 14, 16, "2014\u5E7411\u670820\u65E5 9:00:00\uFF5E2014\u5E7411\u670828\u65E5 9:00:00" ),
            new ExpectPosAndFormat( 14, 16, "2014\u5E7411\u670820\u65E5 9:00:00\uFF5E2014\u5E7412\u67086\u65E5 9:00:00" ),
            new ExpectPosAndFormat( 14, 16, "2014\u5E7411\u670820\u65E5 9:00:00\uFF5E2015\u5E742\u670828\u65E5 9:00:00" )
        };

        class LocaleAndSkeletonItem {
            public String locale;
            public String skeleton;
            public int fieldToCheck;
            public ExpectPosAndFormat[] expected;
             // Simple constructor
            public LocaleAndSkeletonItem(String loc, String skel, int field, ExpectPosAndFormat[] exp) {
                locale = loc;
                skeleton = skel;
                fieldToCheck = field;
                expected = exp;
            }
        };

        final LocaleAndSkeletonItem[] locSkelItems = {
           new LocaleAndSkeletonItem( "en",		"HHmm",         DateFormat.MINUTE_FIELD, exp_en_HHmm ),
           new LocaleAndSkeletonItem( "en",		"HHmmss",       DateFormat.MINUTE_FIELD, exp_en_HHmmss ),
           new LocaleAndSkeletonItem( "en",		"yyMMdd",       DateFormat.MINUTE_FIELD, exp_en_yyMMdd ),
           new LocaleAndSkeletonItem( "en",		"yyMMddHHmm",   DateFormat.MINUTE_FIELD, exp_en_yyMMddHHmm ),
           new LocaleAndSkeletonItem( "en",		"yyMMddHHmmss", DateFormat.MINUTE_FIELD, exp_en_yyMMddHHmmss ),
        // skip the following until ICU4J DateIntervalFormat has support for setting time zone
        // new LocaleAndSkeletonItem( "en",		"yMMMdhmmssz",  DateFormat.MINUTE_FIELD, exp_en_yMMMdhmmssz ),
           new LocaleAndSkeletonItem( "ja",		"yyMMddHHmm",   DateFormat.MINUTE_FIELD, exp_ja_yyMMddHHmm ),
           new LocaleAndSkeletonItem( "ja",		"yyMMddHHmmss", DateFormat.MINUTE_FIELD, exp_ja_yyMMddHHmmss ),
           new LocaleAndSkeletonItem( "ja",		"yMMMdHHmmss",  DateFormat.MINUTE_FIELD, exp_ja_yMMMdHHmmss )
        };

        //final String zoneGMT = "GMT";
        final long startTimeGMT = 1416474000000L; // 2014 Nov 20 09:00 GMT

        TimeZone localZone = TimeZone.getDefault();
        long startTime = startTimeGMT - localZone.getOffset(startTimeGMT);
        for (LocaleAndSkeletonItem item: locSkelItems) {
            DateIntervalFormat difmt = DateIntervalFormat.getInstance(item.skeleton, new ULocale(item.locale));
            int dIdx, dCount = deltas.length;
            for (dIdx = 0; dIdx < dCount; dIdx++) {
                DateInterval di = new DateInterval(startTime, startTime + deltas[dIdx]);
                StringBuffer actual = new StringBuffer(64);
                FieldPosition pos = new FieldPosition(item.fieldToCheck);
                String actualString = difmt.format(di, actual, pos).toString();
                ExpectPosAndFormat expectPosFmt = item.expected[dIdx];
                if (!actualString.equals(expectPosFmt.format) ||
                        pos.getBeginIndex() != expectPosFmt.posBegin || pos.getEndIndex() != expectPosFmt.posEnd) {
                    errln("For locale " + item.locale + ", skeleton " + item.skeleton + ", delta " + deltas[dIdx] +
                           ": expect " + expectPosFmt.posBegin + "-" + expectPosFmt.posEnd + " \"" + expectPosFmt.format +
                           "\"; get " + pos.getBeginIndex() + "-" + pos.getEndIndex() + " \"" + actualString + "\"");
                }
            }
        }
    }

    // TestTicket11669 - Check the thread safety of DateIntervalFormat.format().
    //                   This test failed with ICU 56.
    @Test
    public void TestTicket11669 () {
        // These final variables are accessed directly by the concurrent threads.
        final DateIntervalFormat formatter = DateIntervalFormat.getInstance(DateFormat.YEAR_MONTH_DAY, ULocale.US);
        final ArrayList<DateInterval> testIntervals = new ArrayList<>();
        final ArrayList<String>expectedResults = new ArrayList<>();

        // Create and save the input test data.
        TimeZone tz = TimeZone.getTimeZone("Americal/Los_Angeles");
        Calendar intervalStart = Calendar.getInstance(tz, ULocale.US);
        Calendar intervalEnd = Calendar.getInstance(tz, ULocale.US);
        intervalStart.set(2009,  6, 1);
        intervalEnd.set(2009, 6, 2);
        testIntervals.add(new DateInterval(intervalStart.getTimeInMillis(), intervalEnd.getTimeInMillis()));
        intervalStart.set(2015, 2, 27);
        intervalEnd.set(2015, 3, 1);
        testIntervals.add(new DateInterval(intervalStart.getTimeInMillis(), intervalEnd.getTimeInMillis()));

        // Run the formatter single-threaded to create and save the expected results.
        for (DateInterval interval: testIntervals) {
            FieldPosition pos = new FieldPosition(0);
            StringBuffer result = new StringBuffer();
            formatter.format(interval, result, pos);
            expectedResults.add(result.toString());
        }

        class TestThread extends Thread {
            public String errorMessage;
            @Override
            public void run() {
                for (int loop=0; loop < 2000; ++loop) {
                    ListIterator<String> expectedItr = expectedResults.listIterator();
                    for (DateInterval interval: testIntervals) {
                        String expected = expectedItr.next();
                        FieldPosition pos = new FieldPosition(0);
                        StringBuffer result = new StringBuffer();
                        formatter.format(interval, result, pos);
                        if (!expected.equals(result.toString())) {
                            // Note: The ICU test framework doesn't support reporting failures from within a sub-thread.
                            //       Save the failure for the main thread to pick up later.
                            errorMessage = String.format("Expected \"%s\", actual \"%s\"", expected, result);
                            return;
                        }
                    }
                }
            }
        }

        List<TestThread> threads = new ArrayList<>();
        for (int i=0; i<4; ++i) {
            threads.add(new TestThread());
        }
        for (Thread t: threads) {
            t.start();
        }
        for (TestThread t: threads) {
            try {
                t.join();
            } catch (InterruptedException e) {
                fail("Unexpected exception: " + e.toString());
            }
            if (t.errorMessage != null) {
                fail(t.errorMessage);
            }
        }
    }

    @Test
    public void testFormattedDateInterval() {
        DateIntervalFormat fmt = DateIntervalFormat.getInstance("dMMMMy", ULocale.US);

        {
            String message = "FormattedDateInterval test 1";
            String expectedString = "July 20 \u2013 25, 2018";
            Calendar input1 = Calendar.getInstance(ULocale.UK);
            Calendar input2 = Calendar.getInstance(ULocale.UK);
            input1.set(2018, 6, 20);
            input2.set(2018, 6, 25);
            FormattedDateInterval result = fmt.formatToValue(input1, input2);
            Object[][] expectedFieldPositions = new Object[][] {
                // field, begin index, end index
                {DateFormat.Field.MONTH, 0, 4},
                {DateIntervalFormat.SpanField.DATE_INTERVAL_SPAN, 5, 7, 0},
                {DateFormat.Field.DAY_OF_MONTH, 5, 7},
                {DateIntervalFormat.SpanField.DATE_INTERVAL_SPAN, 10, 12, 1},
                {DateFormat.Field.DAY_OF_MONTH, 10, 12},
                {DateFormat.Field.YEAR, 14, 18}};
            FormattedValueTest.checkFormattedValue(
                message,
                result,
                expectedString,
                expectedFieldPositions);
        }

        // Test sample code
        {
            Calendar input1 = Calendar.getInstance(ULocale.UK);
            Calendar input2 = Calendar.getInstance(ULocale.UK);
            input1.set(2018, 6, 20);
            input2.set(2018, 7, 3);

            // Let fmt be a DateIntervalFormat for locale en-US and skeleton dMMMMy
            // Let input1 be July 20, 2018 and input2 be August 3, 2018:
            FormattedDateInterval result = fmt.formatToValue(input1, input2);
            assertEquals("Expected output from format",
                "July 20 \u2013 August 3, 2018", result.toString());
            ConstrainedFieldPosition cfpos = new ConstrainedFieldPosition();
            cfpos.constrainFieldAndValue(DateIntervalFormat.SpanField.DATE_INTERVAL_SPAN, 0);
            if (result.nextPosition(cfpos)) {
                assertEquals("Expect start index", 0, cfpos.getStart());
                assertEquals("Expect end index", 7, cfpos.getLimit());
            } else {
                // No such span: can happen if input dates are equal.
            }
            assertFalse("No more than one occurrence of the field",
                result.nextPosition(cfpos));
        }

        fmt = DateIntervalFormat.getInstance("dMMMha", ULocale.US);

        {
            String message = "FormattedDateInterval test 2";
            String expectedString = "Feb 15, 11 AM \u2013 3 PM";
            Calendar input1 = Calendar.getInstance(ULocale.US);
            Calendar input2 = Calendar.getInstance(ULocale.US);
            input1.set(2019, 1, 15, 11, 0, 0);
            input2.set(2019, 1, 15, 15, 0, 0);
            FormattedDateInterval result = fmt.formatToValue(input1, input2);
            Object[][] expectedFieldPositions = new Object[][] {
                // field, begin index, end index
                {DateFormat.Field.MONTH, 0, 3},
                {DateFormat.Field.DAY_OF_MONTH, 4, 6},
                {DateIntervalFormat.SpanField.DATE_INTERVAL_SPAN, 8, 13, 0},
                {DateFormat.Field.HOUR1, 8, 10},
                {DateFormat.Field.AM_PM, 11, 13},
                {DateIntervalFormat.SpanField.DATE_INTERVAL_SPAN, 16, 20, 1},
                {DateFormat.Field.HOUR1, 16, 17},
                {DateFormat.Field.AM_PM, 18, 20}};
            FormattedValueTest.checkFormattedValue(
                message,
                result,
                expectedString,
                expectedFieldPositions);
        }

        // To test the fallback pattern behavior, make a custom DateIntervalInfo.
        DateIntervalInfo dtitvinf = new DateIntervalInfo();
        dtitvinf.setFallbackIntervalPattern("<< {1} --- {0} >>");
        fmt = DateIntervalFormat.getInstance("dMMMMy", ULocale.US, dtitvinf);

        {
            String message = "FormattedDateInterval with fallback format test 1";
            String expectedString = "<< July 25, 2018 --- July 20, 2018 >>";
            Date input1 = new Date(2018 - 1900, 6, 20);
            Date input2 = new Date(2018 - 1900, 6, 25);
            DateInterval dtiv = new DateInterval(input1.getTime(), input2.getTime());
            FormattedDateInterval result = fmt.formatToValue(dtiv);
            Object[][] expectedFieldPositions = new Object[][] {
                {DateIntervalFormat.SpanField.DATE_INTERVAL_SPAN, 3, 16, 1},
                {DateFormat.Field.MONTH, 3, 7},
                {DateFormat.Field.DAY_OF_MONTH, 8, 10},
                {DateFormat.Field.YEAR, 12, 16},
                {DateIntervalFormat.SpanField.DATE_INTERVAL_SPAN, 21, 34, 0},
                {DateFormat.Field.MONTH, 21, 25},
                {DateFormat.Field.DAY_OF_MONTH, 26, 28},
                {DateFormat.Field.YEAR, 30, 34}};
            FormattedValueTest.checkFormattedValue(
                message,
                result,
                expectedString,
                expectedFieldPositions);
        }
    }
}
