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