]> granicus.if.org Git - icu/commitdiff
ICU-22071 Fixed DateTimePatternGenerator to respect the locale's "rg" subtag (when...
authorRich Gillam <62772518+richgillam@users.noreply.github.com>
Tue, 12 Jul 2022 01:41:10 +0000 (18:41 -0700)
committerRich Gillam <62772518+richgillam@users.noreply.github.com>
Tue, 12 Jul 2022 17:55:03 +0000 (10:55 -0700)
icu4c/source/i18n/dtptngen.cpp
icu4c/source/test/cintltst/udatpg_test.c
icu4c/source/test/intltest/dtptngts.cpp
icu4c/source/test/intltest/dtptngts.h
icu4j/main/classes/core/src/com/ibm/icu/text/DateTimePatternGenerator.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/DateTimeGeneratorTest.java

index 3171dfd5c3dc825b3b150ef8880ecb9cb7cb1c1a..87eae8c7245459d70b630f1927a379caf78063cd 100644 (file)
@@ -656,6 +656,17 @@ void DateTimePatternGenerator::getAllowedHourFormats(const Locale &locale, UErro
 
     const char *language = locale.getLanguage();
     const char *country = locale.getCountry();
+    
+    char regionOverride[8];
+    int32_t regionOverrideLength = locale.getKeywordValue("rg", regionOverride, sizeof(regionOverride), status);
+    if (U_SUCCESS(status) && regionOverrideLength > 0) {
+        country = regionOverride;
+        if (regionOverrideLength > 2) {
+            // chop off any subdivision codes that may have been included
+            regionOverride[2] = '\0';
+        }
+    }
+    
     Locale maxLocale;  // must be here for correct lifetime
     if (*language == '\0' || *country == '\0') {
         maxLocale = locale;
index 9a70ce1eae0b4437aeaf02d12622f1cf8bb5fdc8..c9bd0942a64a6ccd15ff50d003168c6c6c2f0321 100644 (file)
@@ -47,6 +47,7 @@ static void TestGetDefaultHourCycle(void);
 static void TestGetDefaultHourCycleOnEmptyInstance(void);
 static void TestEras(void);
 static void TestDateTimePatterns(void);
+static void TestRegionOverride(void);
 
 void addDateTimePatternGeneratorTest(TestNode** root) {
     TESTCASE(TestOpenClose);
@@ -58,6 +59,7 @@ void addDateTimePatternGeneratorTest(TestNode** root) {
     TESTCASE(TestGetDefaultHourCycleOnEmptyInstance);
     TESTCASE(TestEras);
     TESTCASE(TestDateTimePatterns);
+    TESTCASE(TestRegionOverride);
 }
 
 /*
@@ -790,4 +792,35 @@ static void doDTPatternTest(UDateTimePatternGenerator* udtpg,
     }
 }
 
+static void TestRegionOverride(void) {
+    typedef struct RegionOverrideTest {
+        const char* locale;
+        const UChar* expectedPattern;
+        UDateFormatHourCycle expectedHourCycle;
+    } RegionOverrideTest;
+
+    const RegionOverrideTest testCases[] = {
+        { "en_US",           u"h:mm\u202fa", UDAT_HOUR_CYCLE_12 },
+        { "en_GB",           u"HH:mm",  UDAT_HOUR_CYCLE_23 },
+        { "en_US@rg=GBZZZZ", u"HH:mm",  UDAT_HOUR_CYCLE_23 },
+        { "en_US@hours=h23", u"HH:mm",  UDAT_HOUR_CYCLE_23 },
+    };
+
+    for (int32_t i = 0; i < UPRV_LENGTHOF(testCases); i++) {
+        UErrorCode err = U_ZERO_ERROR;
+        UChar actualPattern[200];
+        UDateTimePatternGenerator* dtpg = udatpg_open(testCases[i].locale, &err);
+
+        if (assertSuccess("Error creating dtpg", &err)) {
+            UDateFormatHourCycle actualHourCycle = udatpg_getDefaultHourCycle(dtpg, &err);
+            udatpg_getBestPattern(dtpg, u"jmm", -1, actualPattern, 200, &err);
+
+            if (assertSuccess("Error using dtpg", &err)) {
+                assertIntEquals("Wrong hour cycle", testCases[i].expectedHourCycle, actualHourCycle);
+                assertUEquals("Wrong pattern", testCases[i].expectedPattern, actualPattern);
+            }
+        }
+        udatpg_close(dtpg);
+    }
+}
 #endif
index 63611d05789278dc1dc9a3a595504902139426ed..2b270fcc2bb156f4673c8fdd8a6f2681a8487da8 100644 (file)
@@ -47,6 +47,7 @@ void IntlTestDateTimePatternGeneratorAPI::runIndexedTest( int32_t index, UBool e
         TESTCASE(11, test_jConsistencyOddLocales);
         TESTCASE(12, testBestPattern);
         TESTCASE(13, testDateTimePatterns);
+        TESTCASE(14, testRegionOverride);
         default: name = ""; break;
     }
 }
@@ -1760,6 +1761,34 @@ void IntlTestDateTimePatternGeneratorAPI::testDateTimePatterns() {
     }
 }
 
+void IntlTestDateTimePatternGeneratorAPI::testRegionOverride() {
+    const struct TestCase {
+        const char* locale;
+        const UChar* expectedPattern;
+        UDateFormatHourCycle expectedHourCycle;
+    } testCases[] = {
+        { "en_US",           u"h:mm\u202fa", UDAT_HOUR_CYCLE_12 },
+        { "en_GB",           u"HH:mm",       UDAT_HOUR_CYCLE_23 },
+        { "en_US@rg=GBZZZZ", u"HH:mm",       UDAT_HOUR_CYCLE_23 },
+        { "en_US@hours=h23", u"HH:mm",       UDAT_HOUR_CYCLE_23 },
+    };
+
+    for (int32_t i = 0; i < UPRV_LENGTHOF(testCases); i++) {
+        UErrorCode err = U_ZERO_ERROR;
+        LocalPointer<DateTimePatternGenerator> dtpg(DateTimePatternGenerator::createInstance(testCases[i].locale, err));
+        
+        if (assertSuccess("Error creating dtpg", err)) {
+            UDateFormatHourCycle actualHourCycle = dtpg->getDefaultHourCycle(err);
+            UnicodeString actualPattern = dtpg->getBestPattern(u"jmm", err);
+            
+            if (assertSuccess("Error using dtpg", err)) {
+                assertEquals("Wrong hour cycle", testCases[i].expectedHourCycle, actualHourCycle);
+                assertEquals("Wrong pattern", testCases[i].expectedPattern, actualPattern);
+            }
+        }
+    }
+}
+
 void IntlTestDateTimePatternGeneratorAPI::doDTPatternTest(DateTimePatternGenerator* dtpg, UnicodeString* skeletons, DTPLocaleAndResults* localeAndResultsPtr) {
     for (int32_t patStyle = 0; patStyle < kNumDateTimePatterns; patStyle++) {
         UErrorCode status = U_ZERO_ERROR;
index ec700603eb13e5a4349b890e84c9935dded951ac..30083f1b8b50b523cf08857929b69da2a83901e3 100644 (file)
@@ -41,6 +41,7 @@ private:
     void test_jConsistencyOddLocales();
     void testBestPattern();
     void testDateTimePatterns();
+    void testRegionOverride();
 
     enum { kNumDateTimePatterns = 4 };
     typedef struct {
index af88dbd19ccc11fd3abab54be73151c8fbdee61a..3792850a8b2dc442ce9187de65a661a33b2ff04b 100644 (file)
@@ -358,6 +358,7 @@ public class DateTimePatternGenerator implements Freezable<DateTimePatternGenera
 
         String language = uLocale.getLanguage();
         String country = uLocale.getCountry();
+        
         if (language.isEmpty() || country.isEmpty()) {
             // Note: addLikelySubtags is documented not to throw in Java,
             // unlike in C++.
@@ -366,6 +367,15 @@ public class DateTimePatternGenerator implements Freezable<DateTimePatternGenera
             country = max.getCountry();
         }
 
+        String regionOverride = uLocale.getKeywordValue("rg");
+        if (regionOverride != null && !regionOverride.isEmpty()) {
+            // chop off any subdivision codes that may have been included
+            if (regionOverride.length() > 2) {
+                regionOverride = regionOverride.substring(0, 2);
+            }
+            country = regionOverride;
+        }
+        
         if (language.isEmpty()) {
             // Unexpected, but fail gracefully
             language = "und";
index e17615cb3907e25915a662d8efb874740feb1a67..988ebf65c8ada68fd6d45a9256f02b74fb8282b0 100644 (file)
@@ -2030,4 +2030,27 @@ public class DateTimeGeneratorTest extends TestFmwk {
             }
         }
     }
+    
+    @Test
+    public void testRegionOverride() {
+        String[][] testCases = {
+            { "en_US",           "h:mm\u202fa", "HOUR_CYCLE_12" },
+            { "en_GB",           "HH:mm",       "HOUR_CYCLE_23" },
+            { "en_US@rg=GBZZZZ", "HH:mm",       "HOUR_CYCLE_23" },
+            { "en_US@hours=h23", "HH:mm",       "HOUR_CYCLE_23" },
+        };
+
+        for (String[] testCase : testCases) {
+            String localeID = testCase[0];
+            String expectedPattern = testCase[1];
+            String expectedHourCycle = testCase[2];
+        
+            DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance(new ULocale(localeID));
+            String actualHourCycle = dtpg.getDefaultHourCycle().toString();
+            String actualPattern = dtpg.getBestPattern("jmm");
+            
+            assertEquals("Wrong hour cycle", expectedHourCycle, actualHourCycle);
+            assertEquals("Wrong pattern", expectedPattern, actualPattern);
+        }
+    }
 }