Skip to content

Commit d805423

Browse files
committed
ICU-23197 rework J DateFormatSymbols eraNames loading as in C (#3634)
- Also remove related logKnownIssue test skips, update tests for Meiji era start
1 parent 500123b commit d805423

File tree

5 files changed

+79
-68
lines changed

5 files changed

+79
-68
lines changed

icu4j/main/core/src/main/java/com/ibm/icu/impl/EraRules.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,14 @@ private EraRules(int[] startDates, int minEra, int numEras) {
4040
}
4141

4242
public static EraRules getInstance(CalType calType, boolean includeTentativeEra) {
43+
return getInstance(calType.getId(), includeTentativeEra);
44+
}
45+
46+
public static EraRules getInstance(String calId, boolean includeTentativeEra) {
4347
UResourceBundle supplementalDataRes = UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME,
4448
"supplementalData", ICUResourceBundle.ICU_DATA_CLASS_LOADER);
4549
UResourceBundle calendarDataRes = supplementalDataRes.get("calendarData");
46-
UResourceBundle calendarTypeRes = calendarDataRes.get(calType.getId());
50+
UResourceBundle calendarTypeRes = calendarDataRes.get(calId);
4751
UResourceBundle erasRes = calendarTypeRes.get("eras");
4852

4953
int numEras = erasRes.getSize();
@@ -58,10 +62,10 @@ public static EraRules getInstance(CalType calType, boolean includeTentativeEra)
5862
try {
5963
eraIdx = Integer.parseInt(eraIdxStr);
6064
} catch (NumberFormatException e) {
61-
throw new ICUException("Invalid era rule key:" + eraIdxStr + " in era rule data for " + calType.getId());
65+
throw new ICUException("Invalid era rule key:" + eraIdxStr + " in era rule data for " + calId);
6266
}
6367
if (eraIdx < 0) {
64-
throw new ICUException("Era rule key:" + eraIdxStr + " in era rule data for " + calType.getId()
68+
throw new ICUException("Era rule key:" + eraIdxStr + " in era rule data for " + calId
6569
+ " must be >= 0");
6670
}
6771
if (eraIdx + 1 > eraStartDates.size()) {
@@ -74,7 +78,7 @@ public static EraRules getInstance(CalType calType, boolean includeTentativeEra)
7478
// Now set the startDate that we just read
7579
if (isSet(eraStartDates.get(eraIdx).intValue())) {
7680
throw new ICUException(
77-
"Duplicated era rule for rule key:" + eraIdxStr + " in era rule data for " + calType.getId());
81+
"Duplicated era rule for rule key:" + eraIdxStr + " in era rule data for " + calId);
7882
}
7983

8084
boolean hasName = true;
@@ -88,7 +92,7 @@ public static EraRules getInstance(CalType calType, boolean includeTentativeEra)
8892
if (fields.length != 3 || !isValidRuleStartDate(fields[0], fields[1], fields[2])) {
8993
throw new ICUException(
9094
"Invalid era rule date data:" + Arrays.toString(fields) + " in era rule data for "
91-
+ calType.getId());
95+
+ calId);
9296
}
9397
eraStartDates.set(eraIdx, encodeDate(fields[0], fields[1], fields[2]));
9498
} else if (key.equals("named")) {
@@ -112,7 +116,7 @@ public static EraRules getInstance(CalType calType, boolean includeTentativeEra)
112116
eraStartDates.set(eraIdx, MIN_ENCODED_START);
113117
} else {
114118
throw new ICUException("Missing era start/end rule date for key:" + eraIdxStr + " in era rule data for "
115-
+ calType.getId());
119+
+ calId);
116120
}
117121
}
118122

icu4j/main/core/src/main/java/com/ibm/icu/text/DateFormatSymbols.java

Lines changed: 62 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import com.ibm.icu.impl.CacheBase;
2828
import com.ibm.icu.impl.CalendarUtil;
29+
import com.ibm.icu.impl.EraRules;
2930
import com.ibm.icu.impl.ICUData;
3031
import com.ibm.icu.impl.ICUResourceBundle;
3132
import com.ibm.icu.impl.SoftCache;
@@ -1806,37 +1807,8 @@ protected void processResource(String path, UResource.Key key, UResource.Value v
18061807
String[] dataArray = value.getStringArray();
18071808
arrays.put(currentPath, dataArray);
18081809
} else if (value.getType() == ICUResourceBundle.TABLE) {
1809-
// We might have an eras table that is replacing an eras leaf array
1810-
if (currentPath.startsWith("eras")) {
1811-
// path is one of eras/wide, eras/abbreviated, eras/narrow
1812-
UResource.Table rDataTable = value.getTable();
1813-
int dataTableSize = rDataTable.getSize();
1814-
ArrayList<String> dataList = new ArrayList<>(dataTableSize);
1815-
// Expand the ArrayList as necessary to have index from 0 up to the max
1816-
// eraCode, and fill in the slots for the eras defined in the resource data
1817-
// (other slots get nulls).
1818-
for (int dataTableIndex = 0; dataTableIndex < dataTableSize; dataTableIndex++) {
1819-
rDataTable.getKeyAndValue(dataTableIndex, key, value);
1820-
int listIndex = Integer.parseInt(key.toString());
1821-
if (listIndex + 1 > dataList.size()) {
1822-
dataList.ensureCapacity(listIndex + 1); // needed only to minimize expansions
1823-
// Fill in empty strings for all added slots
1824-
while (dataList.size() < listIndex + 1) {
1825-
dataList.add("");
1826-
}
1827-
}
1828-
// Now set the eraName that we just read
1829-
String eraName = (value.getType() == ICUResourceBundle.STRING) ? value.getString() : "";
1830-
dataList.set(listIndex, eraName);
1831-
}
1832-
// Now convert to array
1833-
String[] dataArray = dataList.toArray(new String[dataList.size()]);
1834-
// Save the array
1835-
arrays.put(currentPath, dataArray);
1836-
} else {
1837-
// We are not on a leaf, recursively process the subtable.
1838-
processResource(currentPath, key, value);
1839-
}
1810+
// We are not on a leaf, recursively process the subtable.
1811+
processResource(currentPath, key, value);
18401812
}
18411813
}
18421814
}
@@ -1898,6 +1870,46 @@ private DateFormatSymbols(ULocale desiredLocale, ICUResourceBundle b, String cal
18981870
initializeData(desiredLocale, b, calendarType);
18991871
}
19001872

1873+
/**
1874+
* Convert era names map from CalendarSink to array, filling in missing values from fallback.
1875+
* @internal
1876+
* @deprecated This API is ICU internal only.
1877+
*/
1878+
protected String[] initEras(String erasKey, Map<String, Map<String, String>> maps,
1879+
ICUResourceBundle calBundle, int maxEra) {
1880+
Map<String, String> eraNamesTable = maps.get(erasKey);
1881+
if (eraNamesTable == null) {
1882+
return null;
1883+
}
1884+
ICUResourceBundle calErasWidthBundle = calBundle.findWithFallback(erasKey);
1885+
String[] eraArray = new String[maxEra + 1];
1886+
if (eraArray != null) {
1887+
for (int eraCode = 0; eraCode <= maxEra; eraCode++) {
1888+
String eraKey = Integer.toString(eraCode);
1889+
String eraName = eraNamesTable.get(eraKey);
1890+
if (eraName != null) {
1891+
eraArray[eraCode] = eraName;
1892+
} else {
1893+
// For a map, the sink does not seem to fill in parent entries for keys
1894+
// that do not exist in the current bundle, that is why we need to explicitly
1895+
// fill these in. Also true in ICU4C. Also pre-set to empty string in case
1896+
// there is no parent entry.
1897+
eraArray[eraCode] = "";
1898+
if (calErasWidthBundle != null) {
1899+
ICUResourceBundle calErasWidthKeyBundle = calErasWidthBundle.findWithFallback(eraKey);
1900+
if (calErasWidthKeyBundle != null) {
1901+
eraName = calErasWidthKeyBundle.getString();
1902+
if (eraName != null) {
1903+
eraArray[eraCode] = eraName;
1904+
}
1905+
}
1906+
}
1907+
}
1908+
}
1909+
}
1910+
return eraArray;
1911+
}
1912+
19011913
/**
19021914
* Initializes format symbols for the locale and calendar type
19031915
* @param desiredLocale The locale whose symbols are desired.
@@ -1916,6 +1928,8 @@ protected void initializeData(ULocale desiredLocale, ICUResourceBundle b, String
19161928
b = (ICUResourceBundle) UResourceBundle
19171929
.getBundleInstance(ICUData.ICU_BASE_NAME, desiredLocale);
19181930
}
1931+
// Save the calendarType (with fallback) for later use with initEras:
1932+
String calTypeForEras = ((calendarType!=null)? calendarType : "gregorian");
19191933

19201934
// Iterate over the resource bundle data following the fallbacks through different calendar types
19211935
while (calendarType != null) {
@@ -1952,9 +1966,23 @@ protected void initializeData(ULocale desiredLocale, ICUResourceBundle b, String
19521966
Map<String, String[]> arrays = calendarSink.arrays;
19531967
Map<String, Map<String, String>> maps = calendarSink.maps;
19541968

1955-
eras = arrays.get("eras/abbreviated");
1956-
eraNames = arrays.get("eras/wide");
1957-
narrowEras = arrays.get("eras/narrow");
1969+
// Era setup: Get maxEra from EraRules, get the calendar's era bundle:
1970+
EraRules eraRules = null;
1971+
try {
1972+
eraRules = EraRules.getInstance(calTypeForEras, false);
1973+
} catch (MissingResourceException e) {
1974+
// call IDs unsupported in supplmental era rules such as
1975+
// "iso8601" or bogus "unknown"; fix for here and for
1976+
// calBundle:
1977+
calTypeForEras = "gregorian";
1978+
eraRules = EraRules.getInstance(calTypeForEras, false);
1979+
}
1980+
int maxEra = (eraRules != null)? eraRules.getMaxEraCode() : 0;
1981+
ICUResourceBundle calBundle = b.findWithFallback("calendar/" + calTypeForEras);
1982+
1983+
eras = initEras("eras/abbreviated", maps, calBundle, maxEra);
1984+
eraNames = initEras("eras/wide", maps, calBundle, maxEra);
1985+
narrowEras = initEras("eras/narrow", maps, calBundle, maxEra);
19581986

19591987
months = arrays.get("monthNames/format/wide");
19601988
shortMonths = arrays.get("monthNames/format/abbreviated");

icu4j/main/core/src/test/java/com/ibm/icu/dev/test/calendar/JapaneseTest.java

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -253,17 +253,13 @@ public void TestForceGannenNumbering() {
253253
}
254254
String testString2 = testFmt2.format(refDate);
255255
if (testString2.length() < 2 || testString2.charAt(1) != '1') {
256-
if (!logKnownIssue("ICU-23182", "Japanese calendar formatting")) {
257-
errln("Formatting year 1 in created numeric style, got " + testString2 + " but expected 2nd char to be 1");
258-
}
256+
errln("Formatting year 1 in created numeric style, got " + testString2 + " but expected 2nd char to be 1");
259257
}
260258
// Now switch the patterns and verify that Gannen use follows the pattern
261259
testFmt1.applyPattern(patNumr);
262260
testString1 = testFmt1.format(refDate);
263261
if (testString1.length() < 2 || testString1.charAt(1) != '1') { //
264-
if (!logKnownIssue("ICU-23182", "Japanese calendar formatting")) {
265-
errln("Formatting year 1 in applied numeric style, got " + testString1 + " but expected 2nd char to be 1");
266-
}
262+
errln("Formatting year 1 in applied numeric style, got " + testString1 + " but expected 2nd char to be 1");
267263
}
268264
testFmt2.applyPattern(patText);
269265
testString2 = testFmt2.format(refDate);
@@ -290,10 +286,10 @@ public void Test5345parse() {
290286
fmt.applyPattern("G y");
291287
logln("fmt's locale = " + fmt.getLocale(ULocale.ACTUAL_LOCALE));
292288
//SimpleDateFormat fmt = new SimpleDateFormat("G y", new ULocale("en_US@calendar=japanese"));
293-
long aDateLong = -3197117222000L; // 1868-09-08 00:00 Pacific Time (GMT-07:52:58)
289+
long aDateLong = -3193229222000L; // 1868-10-23 00:00 Pacific Time (GMT-07:52:58)
294290
if (TimeZone.getDefaultTimeZoneType() == TimeZone.TIMEZONE_JDK) {
295291
// Java time zone implementation does not support LMTs
296-
aDateLong = -3197116800000L; // 1868-09-08 00:00 Pacific Time (GMT-08:00)
292+
aDateLong = -3193228800000L; // 1868-10-23 00:00 Pacific Time (GMT-08:00)
297293
}
298294
Date aDate = new Date(aDateLong);
299295
logln("aDate: " + aDate.toString() +", from " + aDateLong);
@@ -304,9 +300,7 @@ public void Test5345parse() {
304300
logln("as Japanese Calendar: " + str);
305301
String expected = "Meiji 1";
306302
if(!str.equals(expected)) {
307-
if (!logKnownIssue("ICU-23186", "Japanese calendar round trip fails")) {
308-
errln("FAIL: Expected " + expected + " but got " + str);
309-
}
303+
errln("FAIL: Expected " + expected + " but got " + str);
310304
}
311305
Date otherDate;
312306
try {
@@ -319,10 +313,8 @@ public void Test5345parse() {
319313
long oLong = otherDate.getTime();
320314
long aLong = otherDate.getTime();
321315

322-
if (!logKnownIssue("ICU-23186", "Japanese calendar round trip fails")) {
323-
errln("FAIL: Parse incorrect of " + expected + ": wanted " + aDate + " ("+aLong+"), but got " + " " +
324-
otherDate + " ("+oLong+") = " + str3 + " not " + dd.toString() );
325-
}
316+
errln("FAIL: Parse incorrect of " + expected + ": wanted " + aDate + " ("+aLong+"), but got " + " " +
317+
otherDate + " ("+oLong+") = " + str3 + " not " + dd.toString() );
326318
} else {
327319
logln("Parsed OK: " + expected);
328320
}

icu4j/main/core/src/test/java/com/ibm/icu/dev/test/format/DateIntervalFormatTest.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -884,10 +884,6 @@ private void expect(String[] data, int data_length) {
884884
String expected = data[i++];
885885
String formatted = dtitvfmt.format(dtitv);
886886
if ( !formatted.equals(Utility.unescape(expected)) ) {
887-
if (locName.equals("ja-u-ca-japanese") &&
888-
logKnownIssue("ICU-23182", "Japanese calendar formatting")) {
889-
continue;
890-
}
891887
if (locName.equals("de") &&
892888
( oneSkeleton.equals("hv") || oneSkeleton.equals("hz") ) &&
893889
logKnownIssue("ICU-23185", "Date time formatting with hz and hv needs revisiting")) {
@@ -2457,10 +2453,6 @@ public void testTicket21222ROCEraDiff() {
24572453

24582454
@Test
24592455
public void testTicket21222JapaneseEraDiff() {
2460-
if (logKnownIssue("ICU-23182", "Japanese calendar formatting")) {
2461-
return;
2462-
}
2463-
24642456
Calendar cal = Calendar.getInstance(TimeZone.GMT_ZONE);
24652457
DateIntervalFormat japanese = DateIntervalFormat.getInstance(
24662458
"h", new ULocale("ja@calendar=japanese"));

icu4j/main/core/src/test/java/com/ibm/icu/dev/test/format/DateTimeGeneratorTest.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -343,11 +343,6 @@ public void TestBasic() {
343343
if (GENERATE_TEST_DATA) {
344344
logln("new String[] {\"" + testSkeleton + "\", \"" + Utility.escape(formatted) + "\"},");
345345
} else if (!formatted.equals(testFormatted)) {
346-
if (uLocale.getName().equals("ja@calendar=japanese") &&
347-
(testSkeleton.equals("yM") || testSkeleton.equals("yMd")) &&
348-
logKnownIssue("ICU-23182", "Japanese calendar formatting") ) {
349-
continue;
350-
}
351346
errln(uLocale + "\tformatted string doesn't match test case: " + testSkeleton + "\t generated: " + pattern + "\t expected: " + testFormatted + "\t got: " + formatted);
352347
if (true) { // debug
353348
pattern = dtfg.getBestPattern(testSkeleton);

0 commit comments

Comments
 (0)