ICU-21154 Fixed handling of hour characters in date-interval-format skeletons to match the way they're handled in

DateTimePatternGenerator skeletons.
This commit is contained in:
Rich Gillam 2022-02-24 16:48:38 -08:00
parent 475703cd40
commit 6bdcd6d30f
4 changed files with 94 additions and 34 deletions

View file

@ -965,16 +965,22 @@ DateIntervalFormat::normalizeHourMetacharacters(const UnicodeString& skeleton) c
UnicodeString result = skeleton;
UChar hourMetachar = u'\0';
UChar dayPeriodChar = u'\0';
int32_t metacharStart = 0;
int32_t metacharCount = 0;
for (int32_t i = 0; i < result.length(); i++) {
UChar c = result[i];
if (c == LOW_J || c == CAP_J || c == CAP_C) {
if (c == LOW_J || c == CAP_J || c == CAP_C || c == LOW_H || c == CAP_H || c == LOW_K || c == CAP_K) {
if (hourMetachar == u'\0') {
hourMetachar = c;
metacharStart = i;
}
++metacharCount;
} else if (c == LOW_A || c == LOW_B || c == CAP_B) {
if (dayPeriodChar == u'\0') {
dayPeriodChar = c;
}
++metacharCount;
} else {
if (hourMetachar != u'\0') {
break;
@ -985,7 +991,6 @@ DateIntervalFormat::normalizeHourMetacharacters(const UnicodeString& skeleton) c
if (hourMetachar != u'\0') {
UErrorCode err = U_ZERO_ERROR;
UChar hourChar = CAP_H;
UChar dayPeriodChar = LOW_A;
UnicodeString convertedPattern = DateFormat::getBestPattern(fLocale, UnicodeString(hourMetachar), err);
if (U_SUCCESS(err)) {
@ -1012,6 +1017,8 @@ DateIntervalFormat::normalizeHourMetacharacters(const UnicodeString& skeleton) c
dayPeriodChar = LOW_B;
} else if (convertedPattern.indexOf(CAP_B) != -1) {
dayPeriodChar = CAP_B;
} else if (dayPeriodChar == u'\0') {
dayPeriodChar = LOW_A;
}
}

View file

@ -1107,8 +1107,23 @@ void DateIntervalFormatTest::testHourMetacharacters() {
"de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "HH", "00\\u201301 Uhr",
// k and K (ICU-21154 and ICU-21156)
"en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "0 \\u2013 1 AM",
"de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "24\\u201301 Uhr",
// (should behave the same as h and H if not overridden in locale ID)
"en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "12 \\u2013 1 AM",
"de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "00\\u201301 Uhr",
// (overriding hour cycle in locale ID should affect both h and K [or both H and k])
"en-u-hc-h11", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hh", "0 \\u2013 1 AM",
"en-u-hc-h11", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "0 \\u2013 1 AM",
"de-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "HH", "24\\u201301 Uhr",
"de-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "24\\u201301 Uhr",
// (overriding hour cycle to h11 should NOT affect H and k; overriding to h24 should NOT affect h and K)
"en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "HH", "00 \\u2013 01",
"en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "00 \\u2013 01",
"en-u-hc-h11", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "HH", "00 \\u2013 01",
"en-u-hc-h11", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "00 \\u2013 01",
"de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hh", "12 \\u2013 1 Uhr AM",
"de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "12 \\u2013 1 Uhr AM",
"de-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hh", "12 \\u2013 1 Uhr AM",
"de-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "12 \\u2013 1 Uhr AM",
// different lengths of the 'a' field
"en", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "ha", "10 AM \\u2013 1 PM",
@ -1163,14 +1178,22 @@ void DateIntervalFormatTest::testHourMetacharacters() {
"hi_IN", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "CC", "\\u0938\\u0941\\u092C\\u0939 10 \\u2013 \\u0926\\u094B\\u092A\\u0939\\u0930 1",
"hi_IN", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "CC", "\\u0930\\u093E\\u0924 12\\u20131",
// regression test for ICU-21342
"en_GB", "CE 2010 09 27 00:00:00", "CE 2010 09 27 10:00:00", "kk", "24\\u201310",
"en_GB", "CE 2010 09 27 00:00:00", "CE 2010 09 27 11:00:00", "kk", "24\\u201311",
"en_GB", "CE 2010 09 27 00:00:00", "CE 2010 09 27 12:00:00", "kk", "24\\u201312",
"en_GB", "CE 2010 09 27 00:00:00", "CE 2010 09 27 13:00:00", "kk", "24\\u201313",
// regression test for ICU-21342
"en-gb-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 10:00:00", "kk", "24\\u201310",
"en-gb-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 11:00:00", "kk", "24\\u201311",
"en-gb-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 12:00:00", "kk", "24\\u201312",
"en-gb-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 13:00:00", "kk", "24\\u201313",
// regression test for ICU-21343
"de", "CE 2010 09 27 01:00:00", "CE 2010 09 27 10:00:00", "KK", "1 \\u2013 10 Uhr AM",
// regression test for ICU-21343
"de", "CE 2010 09 27 01:00:00", "CE 2010 09 27 10:00:00", "KK", "1 \\u2013 10 Uhr AM",
// regression test for ICU-21154 (single-date ranges should use the same hour cycle as multi-date ranges)
"en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 00:00:00", "hh", "12 AM",
"en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hh", "12 \\u2013 1 AM",
"en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 00:00:00", "KK", "12 AM",
"en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "12 \\u2013 1 AM", // (this was producing "0 - 1 AM" before)
"en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 00:00:00", "jj", "12 AM",
"en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "jj", "12 \\u2013 1 AM",
};
expect(DATA, UPRV_LENGTHOF(DATA));
}

View file

@ -1615,16 +1615,22 @@ public class DateIntervalFormat extends UFormat {
StringBuilder result = new StringBuilder(skeleton);
char hourMetachar = '\0';
char dayPeriodChar = '\0';
int metacharStart = 0;
int metacharCount = 0;
for (int i = 0; i < result.length(); i++) {
char c = result.charAt(i);
if (c == 'j' || c == 'J' || c == 'C') {
if (c == 'j' || c == 'J' || c == 'C' || c == 'h' || c == 'H' || c == 'k' || c == 'K') {
if (hourMetachar == '\0') {
hourMetachar = c;
metacharStart = i;
}
++metacharCount;
} else if (c == 'a' || c == 'b' || c == 'B') {
if (dayPeriodChar == '\0') {
dayPeriodChar = c;
}
++metacharCount;
} else {
if (hourMetachar != '\0') {
break;
@ -1634,7 +1640,6 @@ public class DateIntervalFormat extends UFormat {
if (hourMetachar != '\0') {
char hourChar = 'H';
char dayPeriodChar = 'a';
DateTimePatternGenerator dtptng = DateTimePatternGenerator.getInstance(locale);
String convertedPattern = dtptng.getBestPattern(String.valueOf(hourMetachar));
@ -1662,6 +1667,8 @@ public class DateIntervalFormat extends UFormat {
dayPeriodChar = 'b';
} else if (convertedPattern.indexOf('B') != -1) {
dayPeriodChar = 'B';
} else if (dayPeriodChar == '\0') {
dayPeriodChar = 'a';
}
if (hourChar == 'H' || hourChar == 'k') {

View file

@ -752,8 +752,23 @@ public class DateIntervalFormatTest extends TestFmwk {
"de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "HH", "00\\u201301 Uhr",
// k and K (ICU-21154 and ICU-21156)
"en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "0 \\u2013 1 AM",
"de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "24\\u201301 Uhr",
// (should behave the same as h and H if not overridden in locale ID)
"en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "12 \\u2013 1 AM",
"de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "00\\u201301 Uhr",
// (overriding hour cycle in locale ID should affect both h and K [or both H and k])
"en-u-hc-h11", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hh", "0 \\u2013 1 AM",
"en-u-hc-h11", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "0 \\u2013 1 AM",
"de-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "HH", "24\\u201301 Uhr",
"de-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "24\\u201301 Uhr",
// (overriding hour cycle to h11 should NOT affect H and k; overriding to h24 should NOT affect h and K)
"en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "HH", "00 \\u2013 01",
"en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "00 \\u2013 01",
"en-u-hc-h11", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "HH", "00 \\u2013 01",
"en-u-hc-h11", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "00 \\u2013 01",
"de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hh", "12 \\u2013 1 Uhr AM",
"de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "12 \\u2013 1 Uhr AM",
"de-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hh", "12 \\u2013 1 Uhr AM",
"de-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "12 \\u2013 1 Uhr AM",
// different lengths of the 'a' field
"en", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "ha", "10 AM \\u2013 1 PM",
@ -795,27 +810,35 @@ public class DateIntervalFormatTest extends TestFmwk {
"de", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "CCCCC", "10\\u201313 Uhr",
"de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "CCCCC", "00\\u201301 Uhr",
// (for zh_HK and hi_IN, j maps to ha, but C maps to hB)
"zh_HK", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "jj", "\\u4E0A\\u534810\\u6642\\u81F3\\u4E0B\\u53481\\u6642",
"zh_HK", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "jj", "\\u4E0A\\u534812\\u6642\\u81F31\\u6642",
"zh_HK", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "hB", "\\u4E0A\\u534810\\u6642 \\u2013 \\u4E0B\\u53481\\u6642",
"zh_HK", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hB", "\\u51CC\\u666812\\u20131\\u6642",
"zh_HK", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "CC", "\\u4E0A\\u534810\\u6642\\u81F3\\u4E0B\\u53481\\u6642",
"zh_HK", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "CC", "\\u4E0A\\u534812\\u6642\\u81F31\\u6642",
"hi_IN", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "jj", "10 am \\u2013 1 pm",
"hi_IN", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "jj", "12\\u20131 am",
"hi_IN", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "hB", "\\u0938\\u0941\\u092C\\u0939 10 \\u2013 \\u0926\\u094B\\u092A\\u0939\\u0930 1",
"hi_IN", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hB", "\\u0930\\u093E\\u0924 12\\u20131",
"hi_IN", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "CC", "\\u0938\\u0941\\u092C\\u0939 10 \\u2013 \\u0926\\u094B\\u092A\\u0939\\u0930 1",
"hi_IN", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "CC", "\\u0930\\u093E\\u0924 12\\u20131",
"zh_HK", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "jj", "\\u4E0A\\u534810\\u6642\\u81F3\\u4E0B\\u53481\\u6642",
"zh_HK", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "jj", "\\u4E0A\\u534812\\u6642\\u81F31\\u6642",
"zh_HK", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "hB", "\\u4E0A\\u534810\\u6642 \\u2013 \\u4E0B\\u53481\\u6642",
"zh_HK", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hB", "\\u51CC\\u666812\\u20131\\u6642",
"zh_HK", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "CC", "\\u4E0A\\u534810\\u6642\\u81F3\\u4E0B\\u53481\\u6642",
"zh_HK", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "CC", "\\u4E0A\\u534812\\u6642\\u81F31\\u6642",
"hi_IN", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "jj", "10 am \\u2013 1 pm",
"hi_IN", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "jj", "12\\u20131 am",
"hi_IN", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "hB", "\\u0938\\u0941\\u092C\\u0939 10 \\u2013 \\u0926\\u094B\\u092A\\u0939\\u0930 1",
"hi_IN", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hB", "\\u0930\\u093E\\u0924 12\\u20131",
"hi_IN", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "CC", "\\u0938\\u0941\\u092C\\u0939 10 \\u2013 \\u0926\\u094B\\u092A\\u0939\\u0930 1",
"hi_IN", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "CC", "\\u0930\\u093E\\u0924 12\\u20131",
// regression test for ICU-21342
"en_GB", "CE 2010 09 27 00:00:00", "CE 2010 09 27 10:00:00", "kk", "24\\u201310",
"en_GB", "CE 2010 09 27 00:00:00", "CE 2010 09 27 11:00:00", "kk", "24\\u201311",
"en_GB", "CE 2010 09 27 00:00:00", "CE 2010 09 27 12:00:00", "kk", "24\\u201312",
"en_GB", "CE 2010 09 27 00:00:00", "CE 2010 09 27 13:00:00", "kk", "24\\u201313",
// regression test for ICU-21342
"en-gb-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 10:00:00", "kk", "24\\u201310",
"en-gb-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 11:00:00", "kk", "24\\u201311",
"en-gb-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 12:00:00", "kk", "24\\u201312",
"en-gb-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 13:00:00", "kk", "24\\u201313",
// regression test for ICU-21343
"de", "CE 2010 09 27 01:00:00", "CE 2010 09 27 10:00:00", "KK", "1 \\u2013 10 Uhr AM",
// regression test for ICU-21343
"de", "CE 2010 09 27 01:00:00", "CE 2010 09 27 10:00:00", "KK", "1 \\u2013 10 Uhr AM",
// regression test for ICU-21154 (single-date ranges should use the same hour cycle as multi-date ranges)
"en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 00:00:00", "hh", "12 AM",
"en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hh", "12 \\u2013 1 AM",
"en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 00:00:00", "KK", "12 AM",
"en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "12 \\u2013 1 AM", // (this was producing "0 - 1 AM" before)
"en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 00:00:00", "jj", "12 AM",
"en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "jj", "12 \\u2013 1 AM",
};
expect(DATA, DATA.length);
}