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);
+ }
}