ICU-22226 Fix Calendar.getFirstDayOfWeek to honor -u-fw
diff --git a/icu4c/source/i18n/calendar.cpp b/icu4c/source/i18n/calendar.cpp
index 8fd7781..c675251 100644
--- a/icu4c/source/i18n/calendar.cpp
+++ b/icu4c/source/i18n/calendar.cpp
@@ -3948,6 +3948,29 @@
} else {
status = U_INVALID_FORMAT_ERROR;
}
+
+ // Check if the locale has a "fw" u extension and we honor it if present.
+ // And we don't change the overal status, as the presence / lack of "fw" is not an error.
+ UErrorCode fwStatus = U_ZERO_ERROR;
+ char fwExt[ULOC_FULLNAME_CAPACITY] = "";
+ desiredLocale.getKeywordValue("fw", fwExt, ULOC_FULLNAME_CAPACITY, fwStatus);
+ if (U_SUCCESS(fwStatus)) {
+ if (uprv_strcmp(fwExt, "sun") == 0) {
+ fFirstDayOfWeek = UCAL_SUNDAY;
+ } else if (uprv_strcmp(fwExt, "mon") == 0) {
+ fFirstDayOfWeek = UCAL_MONDAY;
+ } else if (uprv_strcmp(fwExt, "tue") == 0) {
+ fFirstDayOfWeek = UCAL_TUESDAY;
+ } else if (uprv_strcmp(fwExt, "wed") == 0) {
+ fFirstDayOfWeek = UCAL_WEDNESDAY;
+ } else if (uprv_strcmp(fwExt, "thu") == 0) {
+ fFirstDayOfWeek = UCAL_THURSDAY;
+ } else if (uprv_strcmp(fwExt, "fri") == 0) {
+ fFirstDayOfWeek = UCAL_FRIDAY;
+ } else if (uprv_strcmp(fwExt, "sat") == 0) {
+ fFirstDayOfWeek = UCAL_SATURDAY;
+ }
+ }
}
ures_close(weekData);
ures_close(rb);
diff --git a/icu4c/source/test/intltest/calregts.cpp b/icu4c/source/test/intltest/calregts.cpp
index 7fff12b..6acf7a4 100644
--- a/icu4c/source/test/intltest/calregts.cpp
+++ b/icu4c/source/test/intltest/calregts.cpp
@@ -99,6 +99,7 @@
CASE(55,Test13745);
CASE(56,TestUTCWrongAMPM22023);
CASE(57,TestAsiaManilaAfterSetGregorianChange22043);
+ CASE(58,TestRespectUExtensionFw);
default: name = ""; break;
}
}
@@ -3240,4 +3241,40 @@
}
}
+void CalendarRegressionTest::TestRespectUExtensionFw(void) { // ICU-22226
+ static const char* LOCALE_IDS[] = {
+ "en-US",
+ "en-US-u-fw-xyz",
+ "en-US-u-fw-sun",
+ "en-US-u-fw-mon",
+ "en-US-u-fw-thu",
+ "en-US-u-fw-sat"
+ };
+ static const UCalendarDaysOfWeek EXPECTED_VAL[] = {
+ UCAL_SUNDAY,
+ UCAL_SUNDAY,
+ UCAL_SUNDAY,
+ UCAL_MONDAY,
+ UCAL_THURSDAY,
+ UCAL_SATURDAY
+ };
+
+ int32_t EXPECTED_VAL_count = UPRV_LENGTHOF(EXPECTED_VAL);
+ assertEquals("The number of locales should be equal to the number of expected results.",
+ EXPECTED_VAL_count, UPRV_LENGTHOF(LOCALE_IDS));
+
+ for (int32_t i=0; i<EXPECTED_VAL_count; ++i) {
+ UErrorCode status = U_ZERO_ERROR;
+ const char * localeId = LOCALE_IDS[i];
+ UCalendarDaysOfWeek expected = EXPECTED_VAL[i];
+
+ Locale locale = Locale::forLanguageTag(localeId, status);
+ LocalPointer<Calendar> cal(Calendar::createInstance(locale, status));
+ UCalendarDaysOfWeek actual = cal->getFirstDayOfWeek(status);
+ failure(status, "Calendar::getFirstDayOfWeek(status)");
+
+ assertEquals((UnicodeString)"Calendar.getFirstDayOfWeek() ignores the 'fw' extension u in '"
+ + localeId + "' locale", expected, actual);
+ }
+}
#endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/icu4c/source/test/intltest/calregts.h b/icu4c/source/test/intltest/calregts.h
index da815fb..174c10c 100644
--- a/icu4c/source/test/intltest/calregts.h
+++ b/icu4c/source/test/intltest/calregts.h
@@ -85,6 +85,7 @@
void TestAsiaManilaAfterSetGregorianChange22043(void);
void Test13745(void);
+ void TestRespectUExtensionFw(void);
void printdate(GregorianCalendar *cal, const char *string);
void dowTest(UBool lenient) ;
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/util/Calendar.java b/icu4j/main/classes/core/src/com/ibm/icu/util/Calendar.java
index 3d9275a..1aaef8c 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/util/Calendar.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/util/Calendar.java
@@ -1595,6 +1595,25 @@
// week data
setWeekData(getRegionForCalendar(locale));
+ // Check if the locale has a "fw" u extension and we honor it if present.
+ String fw = locale.getKeywordValue("fw");
+ if (fw != null) {
+ int fwOverride;
+ switch (fw) {
+ case "sun": fwOverride = SUNDAY; break;
+ case "mon": fwOverride = MONDAY; break;
+ case "tue": fwOverride = TUESDAY; break;
+ case "wed": fwOverride = WEDNESDAY; break;
+ case "thu": fwOverride = THURSDAY; break;
+ case "fri": fwOverride = FRIDAY; break;
+ case "sat": fwOverride = SATURDAY; break;
+ default: fwOverride = -1;
+ }
+ if (fwOverride != -1) {
+ setFirstDayOfWeek(fwOverride);
+ }
+ }
+
// set valid/actual locale
setCalendarLocale(locale);
diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/calendar/CalendarRegressionTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/calendar/CalendarRegressionTest.java
index 936ebe4..9eabd41 100644
--- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/calendar/CalendarRegressionTest.java
+++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/calendar/CalendarRegressionTest.java
@@ -2640,5 +2640,36 @@
}
}
+ @Test
+ public void TestRespectUExtensionFw() { // ICU-22226
+ String[] localeIds = {
+ "en-US",
+ "en-US-u-fw-xyz",
+ "en-US-u-fw-sun",
+ "en-US-u-fw-mon",
+ "en-US-u-fw-thu",
+ "en-US-u-fw-sat"
+ };
+ int[] expectedValues = {
+ Calendar.SUNDAY,
+ Calendar.SUNDAY,
+ Calendar.SUNDAY,
+ Calendar.MONDAY,
+ Calendar.THURSDAY,
+ Calendar.SATURDAY
+ };
+
+ assertEquals(
+ "The localeIds count matches the expectedValues count",
+ localeIds.length,
+ expectedValues.length);
+
+ for (int i = 0; i < localeIds.length; i++) {
+ assertEquals(
+ "Calendar.getFirstDayOfWeek() does not seem to respect fw extension u in locale id",
+ expectedValues[i],
+ Calendar.getInstance(Locale.forLanguageTag(localeIds[i])).getFirstDayOfWeek());
+ }
+ }
}
//eof