ICU-22041 Fix "Africa/Casablanca" show strange LONG displayName

See #2096
diff --git a/icu4c/source/i18n/olsontz.cpp b/icu4c/source/i18n/olsontz.cpp
index cae471a..0f06db5 100644
--- a/icu4c/source/i18n/olsontz.cpp
+++ b/icu4c/source/i18n/olsontz.cpp
@@ -430,8 +430,7 @@
 int32_t OlsonTimeZone::getRawOffset() const {
     UErrorCode ec = U_ZERO_ERROR;
     int32_t raw, dst;
-    getOffset((double) uprv_getUTCtime() * U_MILLIS_PER_SECOND,
-              FALSE, raw, dst, ec);
+    getOffset(uprv_getUTCtime(), FALSE, raw, dst, ec);
     return raw;
 }
 
diff --git a/icu4c/source/i18n/rbtz.cpp b/icu4c/source/i18n/rbtz.cpp
index 495d831..7eba471 100644
--- a/icu4c/source/i18n/rbtz.cpp
+++ b/icu4c/source/i18n/rbtz.cpp
@@ -479,8 +479,7 @@
     // as of current time.
     UErrorCode status = U_ZERO_ERROR;
     int32_t raw, dst;
-    getOffset(uprv_getUTCtime() * U_MILLIS_PER_SECOND,
-        FALSE, raw, dst, status);
+    getOffset(uprv_getUTCtime(), FALSE, raw, dst, status);
     return raw;
 }
 
@@ -490,7 +489,7 @@
     // daylight saving time is used as of now or
     // after the next transition.
     UErrorCode status = U_ZERO_ERROR;
-    UDate now = uprv_getUTCtime() * U_MILLIS_PER_SECOND;
+    UDate now = uprv_getUTCtime();
     int32_t raw, dst;
     getOffset(now, FALSE, raw, dst, status);
     if (dst != 0) {
diff --git a/icu4c/source/test/intltest/tztest.cpp b/icu4c/source/test/intltest/tztest.cpp
index 5ae9ae7..d949276 100644
--- a/icu4c/source/test/intltest/tztest.cpp
+++ b/icu4c/source/test/intltest/tztest.cpp
@@ -76,6 +76,8 @@
     TESTCASE_AUTO(TestGetGMT);
     TESTCASE_AUTO(TestGetWindowsID);
     TESTCASE_AUTO(TestGetIDForWindowsID);
+    TESTCASE_AUTO(TestCasablancaNameAndOffset22041);
+    TESTCASE_AUTO(TestRawOffsetAndOffsetConsistency22041);
     TESTCASE_AUTO_END;
 }
 
@@ -2544,4 +2546,41 @@
     }
 }
 
+void TimeZoneTest::TestCasablancaNameAndOffset22041(void) {
+    std::unique_ptr<TimeZone> zone(TimeZone::createTimeZone("Africa/Casablanca"));
+    UnicodeString standardName, summerName;
+    zone->getDisplayName(false, TimeZone::LONG, Locale::getEnglish(), standardName);
+    zone->getDisplayName(true, TimeZone::LONG, Locale::getEnglish(), summerName);
+    int32_t raw, dst;
+    UErrorCode status = U_ZERO_ERROR;
+    zone->getOffset(Calendar::getNow(), false, raw, dst, status);
+    assertEquals(u"TimeZone name for Africa/Casablanca should not contain '+02' since it is located in UTC, but got "
+                 + standardName, -1, standardName.indexOf("+02"));
+    assertEquals(u"TimeZone name for Africa/Casablanca should not contain '+02' since it is located in UTC, but got "
+                 + summerName, -1, summerName.indexOf("+02"));
+    assertEquals("getRawOffset() and the raw from getOffset(now, false, raw, dst, status) should not be different but got",
+                 zone->getRawOffset(), raw);
+}
+
+void TimeZoneTest::TestRawOffsetAndOffsetConsistency22041(void) {
+    UErrorCode status = U_ZERO_ERROR;
+    LocalPointer<StringEnumeration> s(TimeZone::createEnumeration(status));
+    if (U_FAILURE(status)) {
+        dataerrln("Unable to create TimeZone enumeration");
+        return;
+    }
+    const char* tz;
+    UDate now = Calendar::getNow();
+    while ((tz = s->next(nullptr, status)) != nullptr && U_SUCCESS(status)) {
+        std::unique_ptr<TimeZone> zone(TimeZone::createTimeZone(tz));
+        int32_t raw, dst;
+        zone->getOffset(now, false, raw, dst, status);
+        if (U_FAILURE(status)) {
+           errln("TimeZone '%s' getOffset() return error", tz);
+        }
+        assertEquals(u"TimeZone '" + UnicodeString(tz) +
+                     u"' getRawOffset() and the raw from getOffset(now, false, raw, dst, status) should not be different but got",
+                     zone->getRawOffset(), raw);
+    }
+}
 #endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/icu4c/source/test/intltest/tztest.h b/icu4c/source/test/intltest/tztest.h
index 8e0a29f..893aad6 100644
--- a/icu4c/source/test/intltest/tztest.h
+++ b/icu4c/source/test/intltest/tztest.h
@@ -103,6 +103,8 @@
 
     void TestGetWindowsID(void);
     void TestGetIDForWindowsID(void);
+    void TestCasablancaNameAndOffset22041(void);
+    void TestRawOffsetAndOffsetConsistency22041(void);
 
     static const UDate INTERVAL;
 
diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/timezone/TimeZoneTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/timezone/TimeZoneTest.java
index 48cf764..a69f7ce 100644
--- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/timezone/TimeZoneTest.java
+++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/timezone/TimeZoneTest.java
@@ -2323,6 +2323,36 @@
         assertFalse("Compare TimeZoneAdapter with TimeZone", icuChicagoWrapped.equals(icuChicago));
         assertTrue("Compare two TimeZoneAdapters", icuChicagoWrapped.equals(icuChicagoWrapped2));
     }
+
+    @Test
+    public void TestCasablancaNameAndOffset22041() {
+        String id = "Africa/Casablanca";
+        TimeZone zone = TimeZone.getTimeZone(id);
+        String standardName = zone.getDisplayName(false, TimeZone.LONG, Locale.ENGLISH);
+        String summerName = zone.getDisplayName(true, TimeZone.LONG, Locale.ENGLISH);
+        assertEquals("TimeZone name for Africa/Casablanca should not contain '+02' since it is located in UTC, but got "
+                     + standardName, -1, standardName.indexOf("+02"));
+        assertEquals("TimeZone name for Africa/Casablanca should not contain '+02' since it is located in UTC, but got "
+                     + summerName, -1, summerName.indexOf("+02"));
+        int[] offsets = new int[2]; // raw = offsets[0], dst = offsets[1]
+        zone.getOffset((new Date()).getTime(), false, offsets);
+        int raw = offsets[0];
+        assertEquals("getRawOffset() and the raw from getOffset(now, false, offset) should not be different but got",
+                     zone.getRawOffset(), raw);
+    }
+
+    @Test
+    public void TestRawOffsetAndOffsetConsistency22041() {
+        long now = (new Date()).getTime();
+        int[] offsets = new int[2]; // raw = offsets[0], dst = offsets[1]
+        for (String id : TimeZone.getAvailableIDs()) {
+            TimeZone zone = TimeZone.getTimeZone(id);
+            zone.getOffset((new Date()).getTime(), false, offsets);
+            int raw = offsets[0];
+            assertEquals("getRawOffset() and the raw from getOffset(now, false, offset) should not be different but got",
+                         zone.getRawOffset(), raw);
+        }
+    }
 }
 
 //eof