Patch-Source: https://github.com/unicode-org/icu/commit/1b15a4e9db345b67ad284b92801f3fd99fe56e69
--
From 1b15a4e9db345b67ad284b92801f3fd99fe56e69 Mon Sep 17 00:00:00 2001
From: Frank Tang <ftang@chromium.org>
Date: Thu, 29 Jun 2023 14:55:05 -0700
Subject: [PATCH] ICU-22424 Fix Calendar::clear(UCAL_MONTH)

Make the calling of clear(UCAL_MONTH or UCAL_ORDINAL_MONTH) clear both fields.
---
 icu4c/source/i18n/calendar.cpp         | 11 +++++++++-
 icu4c/source/i18n/unicode/calendar.h   |  3 ++-
 icu4c/source/test/intltest/caltest.cpp | 28 ++++++++++++++++++++++++++
 icu4c/source/test/intltest/caltest.h   |  2 ++
 4 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/icu4c/source/i18n/calendar.cpp b/icu4c/source/i18n/calendar.cpp
index 72d5d10ed5f..d8d544581ea 100644
--- a/i18n/calendar.cpp
+++ b/i18n/calendar.cpp
@@ -1305,7 +1305,16 @@ Calendar::clear(UCalendarDateFields field)
     }
     fFields[field]         = 0;
     fStamp[field]         = kUnset;
-    fIsSet[field]         = false; // Remove later
+    if (field == UCAL_MONTH) {
+        fFields[UCAL_ORDINAL_MONTH]         = 0;
+        fStamp[UCAL_ORDINAL_MONTH]         = kUnset;
+        fIsSet[UCAL_ORDINAL_MONTH]         = false; // Remove later
+    }
+    if (field == UCAL_ORDINAL_MONTH) {
+        fFields[UCAL_MONTH]         = 0;
+        fStamp[UCAL_MONTH]         = kUnset;
+        fIsSet[UCAL_MONTH]         = false; // Remove later
+    }
     fIsTimeSet = fAreFieldsSet = fAreAllFieldsSet = fAreFieldsVirtuallySet = false;
 }
 
diff --git a/icu4c/source/i18n/unicode/calendar.h b/icu4c/source/i18n/unicode/calendar.h
index aa83866ac9c..26781f8a056 100644
--- a/i18n/unicode/calendar.h
+++ b/i18n/unicode/calendar.h
@@ -1237,7 +1237,8 @@ class U_I18N_API Calendar : public UObject {
     /**
      * Clears the value in the given time field, both making it unset and assigning it a
      * value of zero. This field value will be determined during the next resolving of
-     * time into time fields.
+     * time into time fields. Clearing UCAL_ORDINAL_MONTH or UCAL_MONTH will
+     * clear both fields.
      *
      * @param field  The time field to be cleared.
      * @stable ICU 2.6.
diff --git a/icu4c/source/test/intltest/caltest.cpp b/icu4c/source/test/intltest/caltest.cpp
index 7518f1123a7..217fc692fed 100644
--- a/test/intltest/caltest.cpp
+++ b/test/intltest/caltest.cpp
@@ -184,6 +184,7 @@ void CalendarTest::runIndexedTest( int32_t index, UBool exec, const char* &name,
     TESTCASE_AUTO(TestLimitsOrdinalMonth);
     TESTCASE_AUTO(TestActualLimitsOrdinalMonth);
     TESTCASE_AUTO(TestChineseCalendarMonthInSpecialYear);
+    TESTCASE_AUTO(TestClearMonth);
   
     TESTCASE_AUTO_END;
 }
@@ -3887,6 +3888,33 @@ void CalendarTest::TestChineseCalendarMapping() {
     }
 }
 
+void CalendarTest::TestClearMonth() {
+    UErrorCode status = U_ZERO_ERROR;
+    LocalPointer<Calendar> cal(Calendar::createInstance(Locale::getRoot(), status));
+    if (failure(status, "construct Calendar")) return;
+    cal->set(2023, UCAL_JUNE, 29);
+    assertEquals("Calendar::get(UCAL_MONTH)", UCAL_JUNE, cal->get(UCAL_MONTH, status));
+    if (failure(status, "Calendar::get(UCAL_MONTH)")) return;
+    cal->clear(UCAL_MONTH);
+    assertEquals("Calendar::isSet(UCAL_MONTH) after clear(UCAL_MONTH)", false, !!cal->isSet(UCAL_MONTH));
+    assertEquals("Calendar::get(UCAL_MONTH after clear(UCAL_MONTH))", UCAL_JANUARY, !!cal->get(UCAL_MONTH, status));
+    if (failure(status, "Calendar::get(UCAL_MONTH)")) return;
+
+    cal->set(UCAL_ORDINAL_MONTH, 7);
+    assertEquals("Calendar::get(UCAL_MONTH) after set(UCAL_ORDINAL_MONTH, 7)", UCAL_AUGUST, cal->get(UCAL_MONTH, status));
+    if (failure(status, "Calendar::get(UCAL_MONTH) after set(UCAL_ORDINAL_MONTH, 7)")) return;
+    assertEquals("Calendar::get(UCAL_ORDINAL_MONTH) after set(UCAL_ORDINAL_MONTH, 7)", 7, cal->get(UCAL_ORDINAL_MONTH, status));
+    if (failure(status, "Calendar::get(UCAL_ORDINAL_MONTH) after set(UCAL_ORDINAL_MONTH, 7)")) return;
+
+    cal->clear(UCAL_ORDINAL_MONTH);
+    assertEquals("Calendar::isSet(UCAL_ORDINAL_MONTH) after clear(UCAL_ORDINAL_MONTH)", false, !!cal->isSet(UCAL_ORDINAL_MONTH));
+    assertEquals("Calendar::get(UCAL_MONTH) after clear(UCAL_ORDINAL_MONTH)", UCAL_JANUARY, cal->get(UCAL_MONTH, status));
+    if (failure(status, "Calendar::get(UCAL_MONTH) after clear(UCAL_ORDINAL_MONTH)")) return;
+    assertEquals("Calendar::get(UCAL_ORDINAL_MONTH) after clear(UCAL_ORDINAL_MONTH)", 0, cal->get(UCAL_ORDINAL_MONTH, status));
+    if (failure(status, "Calendar::get(UCAL_ORDINAL_MONTH) after clear(UCAL_ORDINAL_MONTH)")) return;
+
+}
+
 void CalendarTest::TestGregorianCalendarInTemporalLeapYear() {
     // test from year 1800 to 2500
     UErrorCode status = U_ZERO_ERROR;
diff --git a/icu4c/source/test/intltest/caltest.h b/icu4c/source/test/intltest/caltest.h
index ee062b2e0ed..bc23702dc91 100644
--- a/test/intltest/caltest.h
+++ b/test/intltest/caltest.h
@@ -56,6 +56,8 @@ class CalendarTest: public CalendarTimeZoneTest {
 
     virtual void TestDebug();
 
+    virtual void TestClearMonth();
+
 public: // package
     /**
      * test subroutine used by TestDisambiguation765
