ICU-21222 Fix Era in Interval format

See #1373
diff --git a/icu4c/source/i18n/dtitvfmt.cpp b/icu4c/source/i18n/dtitvfmt.cpp
index 3411a96..44a8eee 100644
--- a/icu4c/source/i18n/dtitvfmt.cpp
+++ b/icu4c/source/i18n/dtitvfmt.cpp
@@ -863,6 +863,14 @@
                 setPatternInfo(UCAL_DATE, nullptr, &pattern, fInfo->getDefaultOrder());
                 setPatternInfo(UCAL_MONTH, nullptr, &pattern, fInfo->getDefaultOrder());
                 setPatternInfo(UCAL_YEAR, nullptr, &pattern, fInfo->getDefaultOrder());
+
+                timeSkeleton.insert(0, CAP_G);
+                pattern = DateFormat::getBestPattern(
+                        locale, timeSkeleton, status);
+                if ( U_FAILURE(status) ) {
+                    return;
+                }
+                setPatternInfo(UCAL_ERA, nullptr, &pattern, fInfo->getDefaultOrder());
             } else {
                 // TODO: fall back
             }
@@ -889,15 +897,23 @@
         setPatternInfo(UCAL_DATE, nullptr, &pattern, fInfo->getDefaultOrder());
         setPatternInfo(UCAL_MONTH, nullptr, &pattern, fInfo->getDefaultOrder());
         setPatternInfo(UCAL_YEAR, nullptr, &pattern, fInfo->getDefaultOrder());
+
+        timeSkeleton.insert(0, CAP_G);
+        pattern = DateFormat::getBestPattern(
+                locale, timeSkeleton, status);
+        if ( U_FAILURE(status) ) {
+            return;
+        }
+        setPatternInfo(UCAL_ERA, nullptr, &pattern, fInfo->getDefaultOrder());
     } else {
         /* if both present,
-         * 1) when the year, month, or day differs,
+         * 1) when the era, year, month, or day differs,
          * concatenate the two original expressions with a separator between,
          * 2) otherwise, present the date followed by the
          * range expression for the time.
          */
         /*
-         * 1) when the year, month, or day differs,
+         * 1) when the era, year, month, or day differs,
          * concatenate the two original expressions with a separator between,
          */
         // if field exists, use fall back
@@ -917,6 +933,11 @@
             skeleton.insert(0, LOW_Y);
             setFallbackPattern(UCAL_YEAR, skeleton, status);
         }
+        if ( !fieldExistsInSkeleton(UCAL_ERA, dateSkeleton) ) {
+            // then prefix skeleton with 'G'
+            skeleton.insert(0, CAP_G);
+            setFallbackPattern(UCAL_ERA, skeleton, status);
+        }
 
         /*
          * 2) otherwise, present the date followed by the
diff --git a/icu4c/source/test/intltest/dtifmtts.cpp b/icu4c/source/test/intltest/dtifmtts.cpp
index f939c38..5b2d812 100644
--- a/icu4c/source/test/intltest/dtifmtts.cpp
+++ b/icu4c/source/test/intltest/dtifmtts.cpp
@@ -45,25 +45,27 @@
 
 void DateIntervalFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) {
     if (exec) logln("TestSuite DateIntervalFormat");
-    switch (index) {
-        TESTCASE(0, testAPI);
-        TESTCASE(1, testFormat);
-        TESTCASE(2, testFormatUserDII);
-        TESTCASE(3, testSetIntervalPatternNoSideEffect);
-        TESTCASE(4, testYearFormats);
-        TESTCASE(5, testStress);
-        TESTCASE(6, testTicket11583_2);
-        TESTCASE(7, testTicket11985);
-        TESTCASE(8, testTicket11669);
-        TESTCASE(9, testTicket12065);
-        TESTCASE(10, testFormattedDateInterval);
-        TESTCASE(11, testCreateInstanceForAllLocales);
-        TESTCASE(12, testTicket20707);
-        TESTCASE(13, testFormatMillisecond);
-        TESTCASE(14, testHourMetacharacters);
-        TESTCASE(15, testContext);
-        default: name = ""; break;
-    }
+    TESTCASE_AUTO_BEGIN;
+    TESTCASE_AUTO(testAPI);
+    TESTCASE_AUTO(testFormat);
+    TESTCASE_AUTO(testFormatUserDII);
+    TESTCASE_AUTO(testSetIntervalPatternNoSideEffect);
+    TESTCASE_AUTO(testYearFormats);
+    TESTCASE_AUTO(testStress);
+    TESTCASE_AUTO(testTicket11583_2);
+    TESTCASE_AUTO(testTicket11985);
+    TESTCASE_AUTO(testTicket11669);
+    TESTCASE_AUTO(testTicket12065);
+    TESTCASE_AUTO(testFormattedDateInterval);
+    TESTCASE_AUTO(testCreateInstanceForAllLocales);
+    TESTCASE_AUTO(testTicket20707);
+    TESTCASE_AUTO(testFormatMillisecond);
+    TESTCASE_AUTO(testHourMetacharacters);
+    TESTCASE_AUTO(testContext);
+    TESTCASE_AUTO(testTicket21222GregorianEraDiff);
+    TESTCASE_AUTO(testTicket21222ROCEraDiff);
+    TESTCASE_AUTO(testTicket21222JapaneseEraDiff);
+    TESTCASE_AUTO_END;
 }
 
 /**
@@ -2135,4 +2137,212 @@
     }
 }
 
+void DateIntervalFormatTest::getCategoryAndField(
+        const FormattedDateInterval& formatted,
+        std::vector<int32_t>& categories,
+        std::vector<int32_t>& fields,
+        IcuTestErrorCode& status) {
+    categories.clear();
+    fields.clear();
+    ConstrainedFieldPosition cfpos;
+    while (formatted.nextPosition(cfpos, status)) {
+        categories.push_back(cfpos.getCategory());
+        fields.push_back(cfpos.getField());
+    }
+}
+
+void DateIntervalFormatTest::verifyCategoryAndField(
+        const FormattedDateInterval& formatted,
+        const std::vector<int32_t>& categories,
+        const std::vector<int32_t>& fields,
+        IcuTestErrorCode& status) {
+    ConstrainedFieldPosition cfpos;
+    int32_t i = 0;
+    while (formatted.nextPosition(cfpos, status)) {
+        assertEquals("Category", cfpos.getCategory(), categories[i]);
+        assertEquals("Field", cfpos.getField(), fields[i]);
+        i++;
+    }
+}
+
+void DateIntervalFormatTest::testTicket21222GregorianEraDiff() {
+    IcuTestErrorCode status(*this, "testTicket21222GregorianEraDiff");
+
+    LocalPointer<Calendar> cal(Calendar::createInstance(*TimeZone::getGMT(), status));
+    if (U_FAILURE(status)) {
+        errln("Failure encountered: %s", u_errorName(status));
+        return;
+    }
+    std::vector<int32_t> expectedCategory;
+    std::vector<int32_t> expectedField;
+
+    // Test Gregorian calendar
+    LocalPointer<DateIntervalFormat> g(
+        DateIntervalFormat::createInstance(
+            u"h", Locale("en"), status));
+    if (U_FAILURE(status)) {
+        errln("Failure encountered: %s", u_errorName(status));
+        return;
+    }
+    g->setTimeZone(*(TimeZone::getGMT()));
+    cal->setTime(Calendar::getNow(), status);
+    cal->set(123, UCAL_APRIL, 5, 6, 0);
+    FormattedDateInterval formatted;
+
+    UDate date0123Apr5AD = cal->getTime(status);
+
+    cal->set(UCAL_YEAR, 124);
+    UDate date0124Apr5AD = cal->getTime(status);
+
+    cal->set(UCAL_ERA, 0);
+    UDate date0124Apr5BC = cal->getTime(status);
+
+    cal->set(UCAL_YEAR, 123);
+    UDate date0123Apr5BC = cal->getTime(status);
+
+    DateInterval bothAD(date0123Apr5AD, date0124Apr5AD);
+    DateInterval bothBC(date0124Apr5BC, date0123Apr5BC);
+    DateInterval BCtoAD(date0123Apr5BC, date0124Apr5AD);
+
+    formatted = g->formatToValue(bothAD, status);
+    assertEquals("Gregorian - calendar both dates in AD",
+                 u"4/5/123, 6 AM \u2013 4/5/124, 6 AM",
+                 formatted.toString(status));
+
+    formatted = g->formatToValue(bothBC, status);
+    assertEquals("Gregorian - calendar both dates in BC",
+                 u"4/5/124, 6 AM \u2013 4/5/123, 6 AM",
+                 formatted.toString(status));
+
+    formatted = g->formatToValue(BCtoAD, status);
+    assertEquals("Gregorian - BC to AD",
+                 u"4 5, 123 BC, 6 AM \u2013 4 5, 124 AD, 6 AM",
+                 formatted.toString(status));
+}
+
+void DateIntervalFormatTest::testTicket21222ROCEraDiff() {
+    IcuTestErrorCode status(*this, "testTicket21222ROCEraDiff");
+
+    LocalPointer<Calendar> cal(Calendar::createInstance(*TimeZone::getGMT(), status));
+    if (U_FAILURE(status)) {
+        errln("Failure encountered: %s", u_errorName(status));
+        return;
+    }
+    std::vector<int32_t> expectedCategory;
+    std::vector<int32_t> expectedField;
+
+    // Test roc calendar
+    LocalPointer<DateIntervalFormat> roc(
+        DateIntervalFormat::createInstance(
+            u"h", Locale("zh-Hant-TW@calendar=roc"), status));
+    if (U_FAILURE(status)) {
+        errln("Failure encountered: %s", u_errorName(status));
+        return;
+    }
+    roc->setTimeZone(*(TimeZone::getGMT()));
+
+    FormattedDateInterval formatted;
+    // set date1910Jan2 to 1910/1/2 AD which is prior to MG
+    cal->set(1910, UCAL_JANUARY, 2, 6, 0);
+    UDate date1910Jan2 = cal->getTime(status);
+
+    // set date1911Jan2 to 1911/1/2 AD which is also prior to MG
+    cal->set(UCAL_YEAR, 1911);
+    UDate date1911Jan2 = cal->getTime(status);
+
+    // set date1912Jan2 to 1912/1/2 AD which is after MG
+    cal->set(UCAL_YEAR, 1912);
+    UDate date1912Jan2 = cal->getTime(status);
+
+    // set date1913Jan2 to 1913/1/2 AD which is also after MG
+    cal->set(UCAL_YEAR, 1913);
+    UDate date1913Jan2 = cal->getTime(status);
+
+    DateInterval bothBeforeMG(date1910Jan2, date1911Jan2);
+    DateInterval beforeAfterMG(date1911Jan2, date1913Jan2);
+    DateInterval bothAfterMG(date1912Jan2, date1913Jan2);
+
+    formatted = roc->formatToValue(bothAfterMG, status);
+    assertEquals("roc calendar - both dates in MG Era",
+                 u"民國1/1/2 6 上午 – 民國2/1/2 6 上午",
+                 formatted.toString(status));
+    getCategoryAndField(formatted, expectedCategory,
+                        expectedField, status);
+
+    formatted = roc->formatToValue(beforeAfterMG, status);
+    assertEquals("roc calendar - prior MG Era and in MG Era",
+                 u"民國前1年1月2日 6 上午 – 民國2年1月2日 6 上午",
+                 formatted.toString(status));
+    verifyCategoryAndField(formatted, expectedCategory, expectedField, status);
+
+    formatted = roc->formatToValue(bothBeforeMG, status);
+    assertEquals("roc calendar - both dates prior MG Era",
+                 u"民國前2/1/2 6 上午 – 民國前1/1/2 6 上午",
+                 formatted.toString(status));
+    verifyCategoryAndField(formatted, expectedCategory, expectedField, status);
+}
+
+void DateIntervalFormatTest::testTicket21222JapaneseEraDiff() {
+    IcuTestErrorCode status(*this, "testTicket21222JapaneseEraDiff");
+
+    LocalPointer<Calendar> cal(Calendar::createInstance(*TimeZone::getGMT(), status));
+    if (U_FAILURE(status)) {
+        errln("Failure encountered: %s", u_errorName(status));
+        return;
+    }
+    std::vector<int32_t> expectedCategory;
+    std::vector<int32_t> expectedField;
+
+    // Test roc calendar
+    // Test Japanese calendar
+    LocalPointer<DateIntervalFormat> japanese(
+        DateIntervalFormat::createInstance(
+            u"h", Locale("ja@calendar=japanese"), status));
+    if (U_FAILURE(status)) {
+        errln("Failure encountered: %s", u_errorName(status));
+        return;
+    }
+    japanese->setTimeZone(*(TimeZone::getGMT()));
+
+    FormattedDateInterval formatted;
+
+    cal->set(2019, UCAL_MARCH, 2, 6, 0);
+    UDate date2019Mar2 = cal->getTime(status);
+
+    cal->set(UCAL_MONTH, UCAL_APRIL);
+    cal->set(UCAL_DAY_OF_MONTH, 3);
+    UDate date2019Apr3 = cal->getTime(status);
+
+    cal->set(UCAL_MONTH, UCAL_MAY);
+    cal->set(UCAL_DAY_OF_MONTH, 4);
+    UDate date2019May4 = cal->getTime(status);
+
+    cal->set(UCAL_MONTH, UCAL_JUNE);
+    cal->set(UCAL_DAY_OF_MONTH, 5);
+    UDate date2019Jun5 = cal->getTime(status);
+
+    DateInterval bothBeforeReiwa(date2019Mar2, date2019Apr3);
+    DateInterval beforeAfterReiwa(date2019Mar2, date2019May4);
+    DateInterval bothAfterReiwa(date2019May4, date2019Jun5);
+
+    formatted = japanese->formatToValue(bothAfterReiwa, status);
+    assertEquals("japanese calendar - both dates in Reiwa",
+                 u"R1/5/4 午前6時~R1/6/5 午前6時",
+                 formatted.toString(status));
+    getCategoryAndField(formatted, expectedCategory,
+                        expectedField, status);
+
+    formatted = japanese->formatToValue(bothBeforeReiwa, status);
+    assertEquals("japanese calendar - both dates before Reiwa",
+                 u"H31/3/2 午前6時~H31/4/3 午前6時",
+                 formatted.toString(status));
+    verifyCategoryAndField(formatted, expectedCategory, expectedField, status);
+
+    formatted = japanese->formatToValue(beforeAfterReiwa, status);
+    assertEquals("japanese calendar - date before and in Reiwa",
+                 u"平成31年3月2日 午前6時~令和元年5月4日 午前6時",
+                 formatted.toString(status));
+    verifyCategoryAndField(formatted, expectedCategory, expectedField, status);
+}
+
 #endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/icu4c/source/test/intltest/dtifmtts.h b/icu4c/source/test/intltest/dtifmtts.h
index 700eb4f..f381bc8 100644
--- a/icu4c/source/test/intltest/dtifmtts.h
+++ b/icu4c/source/test/intltest/dtifmtts.h
@@ -17,6 +17,10 @@
 #include "intltest.h"
 #include "itformat.h"
 
+U_NAMESPACE_BEGIN
+class FormattedDateInterval;
+U_NAMESPACE_END
+
 /**
  * Test basic functionality of various API functions
  **/
@@ -81,6 +85,9 @@
     void testCreateInstanceForAllLocales();
 
     void testTicket20707();
+    void testTicket21222GregorianEraDiff();
+    void testTicket21222ROCEraDiff();
+    void testTicket21222JapaneseEraDiff();
 
 private:
     /**
@@ -99,6 +106,19 @@
      */
     void stress(const char** data, int32_t data_length, const Locale& loc,
                 const char* locName);
+
+    void getCategoryAndField(
+        const FormattedDateInterval& formatted,
+        std::vector<int32_t>& categories,
+        std::vector<int32_t>& fields,
+        IcuTestErrorCode& status);
+
+    void verifyCategoryAndField(
+        const FormattedDateInterval& formatted,
+        const std::vector<int32_t>& categories,
+        const std::vector<int32_t>& fields,
+        IcuTestErrorCode& status);
+
 };
 
 #endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/DateIntervalFormat.java b/icu4j/main/classes/core/src/com/ibm/icu/text/DateIntervalFormat.java
index 4a59b01..de437a5 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/text/DateIntervalFormat.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/text/DateIntervalFormat.java
@@ -1450,6 +1450,12 @@
                     // share interval pattern
                     intervalPatterns.put(DateIntervalInfo.
                         CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.YEAR], ptn);
+
+                    pattern =dtpng.getBestPattern(timeSkeleton + "G");
+                    ptn = new PatternInfo(null, pattern, fInfo.getDefaultOrder());
+                    // share interval pattern
+                    intervalPatterns.put(DateIntervalInfo.
+                        CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.ERA], ptn);
                 } else {
                     //genFallbackForNotFound(Calendar.DATE, skeleton);
                     //genFallbackForNotFound(Calendar.MONTH, skeleton);
@@ -1492,6 +1498,11 @@
                 CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.MONTH], ptn);
             intervalPatterns.put(DateIntervalInfo.
                 CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.YEAR], ptn);
+
+            pattern =dtpng.getBestPattern(timeSkeleton + "G");
+            ptn = new PatternInfo(null, pattern, fInfo.getDefaultOrder());
+            intervalPatterns.put(DateIntervalInfo.
+                CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.ERA], ptn);
         } else {
             /* if both present,
              * 1) when the year, month, or day differs,
@@ -1500,7 +1511,7 @@
              * range expression for the time.
              */
             /*
-             * 1) when the year, month, or day differs,
+             * 1) when the era, year, month, or day differs,
              * concatenate the two original expressions with a separator between,
              */
             // if field exists, use fall back
@@ -1522,6 +1533,12 @@
                     CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.YEAR] + skeleton;
                 genFallbackPattern(Calendar.YEAR, skeleton, intervalPatterns, dtpng);
             }
+            if ( !fieldExistsInSkeleton(Calendar.ERA, dateSkeleton) ) {
+                // then prefix skeleton with 'G'
+                skeleton = DateIntervalInfo.
+                    CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.ERA] + skeleton;
+                genFallbackPattern(Calendar.ERA, skeleton, intervalPatterns, dtpng);
+            }
 
             /*
              * 2) otherwise, present the date followed by the
diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/DateIntervalFormatTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/DateIntervalFormatTest.java
index 22b9ec8..6fe62a9 100644
--- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/DateIntervalFormatTest.java
+++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/DateIntervalFormatTest.java
@@ -16,6 +16,7 @@
 package com.ibm.icu.dev.test.format;
 
 import java.text.FieldPosition;
+import java.text.Format.Field;
 import java.text.ParseException;
 import java.text.ParsePosition;
 import java.util.ArrayList;
@@ -40,6 +41,7 @@
 import com.ibm.icu.text.SimpleDateFormat;
 import com.ibm.icu.util.Calendar;
 import com.ibm.icu.util.DateInterval;
+import com.ibm.icu.util.GregorianCalendar;
 import com.ibm.icu.util.Output;
 import com.ibm.icu.util.TimeZone;
 import com.ibm.icu.util.ULocale;
@@ -2303,4 +2305,153 @@
             assertEquals("Formate for " + testCase[4], testCase[5], res.toString());
         }
     }
+
+    @Test
+    public void testTicket21222GregorianEraDiff() {
+        Calendar cal = Calendar.getInstance(TimeZone.GMT_ZONE);
+        DateIntervalFormat g = DateIntervalFormat.getInstance("h", Locale.ENGLISH);
+        g.setTimeZone(TimeZone.GMT_ZONE);
+
+        cal.set(123, Calendar.APRIL, 5, 6, 0);
+        Date date0123Apr5AD = cal.getTime();
+
+        cal.set(Calendar.YEAR, 124);
+        Date date0124Apr5AD = cal.getTime();
+
+        cal.set(Calendar.ERA, GregorianCalendar.BC);
+        Date date0124Apr5BC = cal.getTime();
+
+        cal.set(Calendar.YEAR, 123);
+        Date date0123Apr5BC = cal.getTime();
+
+        DateInterval bothAD = new DateInterval(date0123Apr5AD.getTime(), date0124Apr5AD.getTime());
+        DateInterval bothBC = new DateInterval(date0124Apr5BC.getTime(), date0123Apr5BC.getTime());
+        DateInterval BCtoAD = new DateInterval(date0123Apr5BC.getTime(), date0124Apr5AD.getTime());
+
+        FormattedDateInterval formatted = g.formatToValue(bothAD);
+        assertEquals("Gregorian - calendar both dates in AD",
+                     "4/5/123, 6 AM \u2013 4/5/124, 6 AM",
+                     formatted.toString());
+
+        formatted = g.formatToValue(bothBC);
+        assertEquals("Gregorian - calendar both dates in BC",
+                     "4/5/124, 6 AM \u2013 4/5/123, 6 AM",
+                     formatted.toString());
+
+        formatted = g.formatToValue(BCtoAD);
+        assertEquals("Gregorian - BC to AD",
+                     "4 5, 123 BC, 6 AM \u2013 4 5, 124 AD, 6 AM",
+                     formatted.toString());
+    }
+
+    private List<Field>  getFields(FormattedDateInterval formatted) {
+        List<Field> fields = new ArrayList<Field>();
+        ConstrainedFieldPosition cfpos = new ConstrainedFieldPosition();
+        while (formatted.nextPosition(cfpos)) {
+            fields.add(cfpos.getField());
+        }
+        return fields;
+    }
+
+    private void verifyFields(
+            FormattedDateInterval formatted, List<Field> fields) {
+        int i = 0;
+        ConstrainedFieldPosition cfpos = new ConstrainedFieldPosition();
+        while (formatted.nextPosition(cfpos)) {
+            assertEquals("Field", cfpos.getField(), fields.get(i));
+            i++;
+        }
+    }
+
+    @Test
+    public void testTicket21222ROCEraDiff() {
+        Calendar cal = Calendar.getInstance(TimeZone.GMT_ZONE);
+        DateIntervalFormat roc = DateIntervalFormat.getInstance(
+            "h", new ULocale("zh-Hant-TW@calendar=roc"));
+        roc.setTimeZone(TimeZone.GMT_ZONE);
+
+        // set date1910Jan2 to 1910/1/2 AD which is prior to MG
+        cal.set(1910, Calendar.JANUARY, 2, 6, 0);
+        Date date1910Jan2 = cal.getTime();
+
+        // set date1911Jan2 to 1911/1/2 AD which is also prior to MG
+        cal.set(Calendar.YEAR, 1911);
+        Date date1911Jan2 = cal.getTime();
+
+        // set date1912Jan2 to 1912/1/2 AD which is after MG
+        cal.set(Calendar.YEAR, 1912);
+        Date date1912Jan2 = cal.getTime();
+
+        // set date1913Jan2 to 1913/1/2 AD which is also after MG
+        cal.set(Calendar.YEAR, 1913);
+        Date date1913Jan2 = cal.getTime();
+
+        DateInterval bothBeforeMG = new DateInterval(date1910Jan2.getTime(), date1911Jan2.getTime());
+        DateInterval beforeAfterMG = new DateInterval(date1911Jan2.getTime(), date1913Jan2.getTime());
+        DateInterval bothAfterMG = new DateInterval(date1912Jan2.getTime(), date1913Jan2.getTime());
+
+
+        FormattedDateInterval formatted = roc.formatToValue(bothAfterMG);
+        assertEquals("roc calendar - both dates in MG Era",
+                     "民國1/1/2 6 上午 – 民國2/1/2 6 上午",
+                     formatted.toString());
+        List<Field> expectedFields = getFields(formatted);
+
+        formatted = roc.formatToValue(beforeAfterMG);
+        assertEquals("roc calendar - prior MG Era and in MG Era",
+                     "民國前1年1月2日 6 上午 – 民國2年1月2日 6 上午",
+                     formatted.toString());
+        verifyFields(formatted, expectedFields);
+
+        formatted = roc.formatToValue(bothBeforeMG);
+        assertEquals("roc calendar - both dates prior MG Era",
+                     "民國前2/1/2 6 上午 – 民國前1/1/2 6 上午",
+                     formatted.toString());
+        verifyFields(formatted, expectedFields);
+    }
+
+    @Test
+    public void testTicket21222JapaneseEraDiff() {
+        Calendar cal = Calendar.getInstance(TimeZone.GMT_ZONE);
+        DateIntervalFormat japanese = DateIntervalFormat.getInstance(
+            "h", new ULocale("ja@calendar=japanese"));
+        japanese.setTimeZone(TimeZone.GMT_ZONE);
+
+        cal.set(2019, Calendar.MARCH, 2, 6, 0);
+        Date date2019Mar2 = cal.getTime();
+
+        cal.set(Calendar.MONTH, Calendar.APRIL);
+        cal.set(Calendar.DAY_OF_MONTH, 3);
+        Date date2019Apr3 = cal.getTime();
+
+        cal.set(Calendar.MONTH, Calendar.MAY);
+        cal.set(Calendar.DAY_OF_MONTH, 4);
+        Date date2019May4 = cal.getTime();
+
+        cal.set(Calendar.MONTH, Calendar.JUNE);
+        cal.set(Calendar.DAY_OF_MONTH, 5);
+        Date date2019Jun5 = cal.getTime();
+
+        DateInterval bothBeforeReiwa = new DateInterval(date2019Mar2.getTime(), date2019Apr3.getTime());
+        DateInterval beforeAfterReiwa = new DateInterval(date2019Mar2.getTime(), date2019May4.getTime());
+        DateInterval bothAfterReiwa = new DateInterval(date2019May4.getTime(), date2019Jun5.getTime());
+
+        FormattedDateInterval formatted = japanese.formatToValue(bothAfterReiwa);
+        assertEquals("japanese calendar - both dates in Reiwa",
+                     "R1/5/4 午前6時~R1/6/5 午前6時",
+                     formatted.toString());
+        List<Field> expectedFields = getFields(formatted);
+
+        formatted = japanese.formatToValue(bothBeforeReiwa);
+        assertEquals("japanese calendar - both dates before Reiwa",
+                     "H31/3/2 午前6時~H31/4/3 午前6時",
+                     formatted.toString());
+        verifyFields(formatted, expectedFields);
+
+        formatted = japanese.formatToValue(beforeAfterReiwa);
+        assertEquals("japanese calendar - date before and in Reiwa",
+                     "平成31年3月2日 午前6時~令和元年5月4日 午前6時",
+                     formatted.toString());
+        verifyFields(formatted, expectedFields);
+    }
 }