diff --git a/icu4c/source/i18n/calendar.cpp b/icu4c/source/i18n/calendar.cpp index 8fd7781b7922..c67525140abb 100644 --- a/icu4c/source/i18n/calendar.cpp +++ b/icu4c/source/i18n/calendar.cpp @@ -3948,6 +3948,29 @@ Calendar::setWeekData(const Locale& desiredLocale, const char *type, UErrorCode& } 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 7fff12b72712..6acf7a4b95f8 100644 --- a/icu4c/source/test/intltest/calregts.cpp +++ b/icu4c/source/test/intltest/calregts.cpp @@ -99,6 +99,7 @@ CalendarRegressionTest::runIndexedTest( int32_t index, UBool exec, const char* & CASE(55,Test13745); CASE(56,TestUTCWrongAMPM22023); CASE(57,TestAsiaManilaAfterSetGregorianChange22043); + CASE(58,TestRespectUExtensionFw); default: name = ""; break; } } @@ -3240,4 +3241,40 @@ void CalendarRegressionTest::TestWeekOfYear13548(void) { } } +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 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 da815fb448e0..174c10c006c9 100644 --- a/icu4c/source/test/intltest/calregts.h +++ b/icu4c/source/test/intltest/calregts.h @@ -85,6 +85,7 @@ class CalendarRegressionTest: public IntlTest { 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 3d9275adfd8b..1aaef8c54f63 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 @@ protected Calendar(TimeZone zone, ULocale locale) // 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 936ebe4a6210..9eabd4182f04 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 @@ public void TestAsiaManilaAfterSetGregorianChange22043() { } } + @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