]> granicus.if.org Git - icu/commitdiff
ICU-10065 In DateTimePatternGenerator, add support for pattern chars K,O,X,x, adjust...
authorPeter Edberg <pedberg@unicode.org>
Tue, 10 Sep 2013 07:51:38 +0000 (07:51 +0000)
committerPeter Edberg <pedberg@unicode.org>
Tue, 10 Sep 2013 07:51:38 +0000 (07:51 +0000)
X-SVN-Rev: 34256

icu4c/source/i18n/dtptngen.cpp
icu4c/source/i18n/dtptngen_impl.h
icu4c/source/test/intltest/dtptngts.cpp
icu4c/source/test/intltest/dtptngts.h

index ddb553272d183b7a1d3199d1907b3254576b4293..023ad7e1bbd2f10dbb14764bd1db91865ec58613 100644 (file)
@@ -181,8 +181,9 @@ static const dtTypeElem dtTypes[] = {
     {LOW_G, UDATPG_DAY_FIELD, DT_NUMERIC + 3*DT_DELTA, 1, 20}, // really internal use, so we don't care
     {LOW_A, UDATPG_DAYPERIOD_FIELD, DT_SHORT, 1, 0},
     {CAP_H, UDATPG_HOUR_FIELD, DT_NUMERIC + 10*DT_DELTA, 1, 2}, // 24 hour
-    {LOW_K, UDATPG_HOUR_FIELD, DT_NUMERIC + 11*DT_DELTA, 1, 2},
+    {LOW_K, UDATPG_HOUR_FIELD, DT_NUMERIC + 11*DT_DELTA, 1, 2}, // 24 hour
     {LOW_H, UDATPG_HOUR_FIELD, DT_NUMERIC, 1, 2}, // 12 hour
+    {CAP_K, UDATPG_HOUR_FIELD, DT_NUMERIC + DT_DELTA, 1, 2}, // 12 hour
     {LOW_K, UDATPG_HOUR_FIELD, DT_NUMERIC + DT_DELTA, 1, 2},
     {LOW_M, UDATPG_MINUTE_FIELD, DT_NUMERIC, 1, 2},
     {LOW_S, UDATPG_SECOND_FIELD, DT_NUMERIC, 1, 2},
@@ -192,10 +193,19 @@ static const dtTypeElem dtTypes[] = {
     {LOW_V, UDATPG_ZONE_FIELD, DT_LONG - 2*DT_DELTA, 4, 0},
     {LOW_Z, UDATPG_ZONE_FIELD, DT_SHORT, 1, 3},
     {LOW_Z, UDATPG_ZONE_FIELD, DT_LONG, 4, 0},
-    {CAP_Z, UDATPG_ZONE_FIELD, DT_SHORT - DT_DELTA, 1, 3},
+    {CAP_Z, UDATPG_ZONE_FIELD, DT_NARROW - DT_DELTA, 1, 3},
     {CAP_Z, UDATPG_ZONE_FIELD, DT_LONG - DT_DELTA, 4, 0},
-    {CAP_V, UDATPG_ZONE_FIELD, DT_SHORT - DT_DELTA, 1, 3},
-    {CAP_V, UDATPG_ZONE_FIELD, DT_LONG - DT_DELTA, 4, 0},
+    {CAP_Z, UDATPG_ZONE_FIELD, DT_SHORT - DT_DELTA, 5, 0},
+    {CAP_O, UDATPG_ZONE_FIELD, DT_SHORT - DT_DELTA, 1, 0},
+    {CAP_O, UDATPG_ZONE_FIELD, DT_LONG - DT_DELTA, 4, 0},
+    {CAP_V, UDATPG_ZONE_FIELD, DT_SHORT - DT_DELTA, 1, 0},
+    {CAP_V, UDATPG_ZONE_FIELD, DT_LONG - DT_DELTA, 2, 0},
+    {CAP_X, UDATPG_ZONE_FIELD, DT_NARROW - DT_DELTA, 1, 0},
+    {CAP_X, UDATPG_ZONE_FIELD, DT_SHORT - DT_DELTA, 2, 0},
+    {CAP_X, UDATPG_ZONE_FIELD, DT_LONG - DT_DELTA, 4, 0},
+    {LOW_X, UDATPG_ZONE_FIELD, DT_NARROW - DT_DELTA, 1, 0},
+    {LOW_X, UDATPG_ZONE_FIELD, DT_SHORT - DT_DELTA, 2, 0},
+    {LOW_X, UDATPG_ZONE_FIELD, DT_LONG - DT_DELTA, 4, 0},
     {0, UDATPG_FIELD_COUNT, 0, 0, 0} , // last row of dtTypes[]
  };
 
index f76f003d490cc248130f217ed4e5dfda600ca9ac..7f29bab226a99784e008e6a7f9b40dba89834337 100644 (file)
@@ -1,6 +1,6 @@
 /*
 *******************************************************************************
-* Copyright (C) 2007-2012, International Business Machines Corporation and
+* Copyright (C) 2007-2013, International Business Machines Corporation and
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 *
@@ -54,6 +54,7 @@
 #define CAP_U             ((UChar)0x0055)
 #define CAP_V             ((UChar)0x0056)
 #define CAP_W             ((UChar)0x0057)
+#define CAP_X             ((UChar)0x0058)
 #define CAP_Y             ((UChar)0x0059)
 #define CAP_Z             ((UChar)0x005A)
 #define LOWLINE           ((UChar)0x005F)
@@ -79,6 +80,7 @@
 #define LOW_U             ((UChar)0x0075)
 #define LOW_V             ((UChar)0x0076)
 #define LOW_W             ((UChar)0x0077)
+#define LOW_X             ((UChar)0x0078)
 #define LOW_Y             ((UChar)0x0079)
 #define LOW_Z             ((UChar)0x007A)
 #define DT_SHORT          -0x102
index f5e2e1d7a25d5202530163726beadfa05bd855f4..1e2cecf0e93dd2a1d2b9597d6e29f4ccd4dc2d59 100644 (file)
@@ -29,6 +29,7 @@ void IntlTestDateTimePatternGeneratorAPI::runIndexedTest( int32_t index, UBool e
     switch (index) {
         TESTCASE(0, testAPI);
         TESTCASE(1, testOptions);
+        TESTCASE(2, testAllFieldPatterns);
         default: name = ""; break;
     }
 }
@@ -890,4 +891,139 @@ void IntlTestDateTimePatternGeneratorAPI::testOptions(/*char *par*/)
     }
 }
 
+/**
+ * Test that DTPG can handle all valid pattern character / length combinations
+ *
+ */
+#define FIELD_LENGTHS_COUNT 6
+#define FIELD_LENGTH_MAX 8
+#define MUST_INCLUDE_COUNT 5
+
+typedef struct AllFieldsTestItem {
+    char patternChar;
+    int8_t fieldLengths[FIELD_LENGTHS_COUNT+1]; // up to FIELD_LENGTHS_COUNT lengths to try
+                                                // (length <=FIELD_LENGTH_MAX) plus 0 terminator
+    char mustIncludeOneOf[MUST_INCLUDE_COUNT+1];// resulting pattern must include at least one of
+                                                // these as a pattern char (0-terminated list)
+} AllFieldsTestItem;
+
+void IntlTestDateTimePatternGeneratorAPI::testAllFieldPatterns(/*char *par*/)
+{
+    const char * localeNames[] = {
+        "root",
+        "root@calendar=japanese",
+        "root@calendar=chinese",
+        "en",
+        "en@calendar=japanese",
+        "en@calendar=chinese",
+        NULL // terminator
+    };
+    AllFieldsTestItem testData[] = {
+        //pat   fieldLengths    generated pattern must
+        //chr   to test         include one of these
+        { 'G',  {1,2,3,4,5,0},  "G"    }, // era
+        // year
+        { 'y',  {1,2,3,4,0},    "yU"   }, // year
+        { 'Y',  {1,2,3,4,0},    "Y"    }, // year for week of year
+        { 'u',  {1,2,3,4,5,0},  "yuU"  }, // extended year
+        { 'U',  {1,2,3,4,5,0},  "yU"   }, // cyclic year name
+        // quarter
+        { 'Q',  {1,2,3,4,0},    "Qq"   }, // x
+        { 'q',  {1,2,3,4,0},    "Qq"   }, // standalone
+        // month
+        { 'M',  {1,2,3,4,5,0},  "ML"   }, // x
+        { 'L',  {1,2,3,4,5,0},  "ML"   }, // standalone
+        // week
+        { 'w',  {1,2,0},        "w"    }, // week of year
+        { 'W',  {1,0},          "W"    }, // week of month
+        // day
+        { 'd',  {1,2,0},        "d"    }, // day of month
+        { 'D',  {1,2,3,0},      "D"    }, // day of year
+        { 'F',  {1,0},          "F"    }, // day of week in month
+        { 'g',  {7,0},          "g"    }, // modified julian day
+        // weekday
+        { 'E',  {1,2,3,4,5,6},  "Eec"  }, // day of week
+        { 'e',  {1,2,3,4,5,6},  "Eec"  }, // local day of week
+        { 'c',  {1,2,3,4,5,6},  "Eec"  }, // standalone local day of week
+        // day period
+    //  { 'a',  {1,0},          "a"    }, // am or pm   // not clear this one is supposed to work (it doesn't)
+        // hour
+        { 'h',  {1,2,0},        "hK"   }, // 12 (1-12)
+        { 'H',  {1,2,0},        "Hk"   }, // 24 (0-23)
+        { 'K',  {1,2,0},        "hK"   }, // 12 (0-11)
+        { 'k',  {1,2,0},        "Hk"   }, // 24 (1-24)
+        { 'j',  {1,2,0},        "hHKk" }, // locale default
+        // minute
+        { 'm',  {1,2,0},        "m"    }, // x
+        // second & fractions
+        { 's',  {1,2,0},        "s"    }, // x
+        { 'S',  {1,2,3,4,0},    "S"    }, // fractional second
+        { 'A',  {8,0},          "A"    }, // milliseconds in day
+        // zone
+        { 'z',  {1,2,3,4,0},    "z"    }, // x
+        { 'Z',  {1,2,3,4,5,0},  "Z"    }, // x
+        { 'O',  {1,4,0},        "O"    }, // x
+        { 'v',  {1,4,0},        "v"    }, // x
+        { 'V',  {1,2,3,4,0},    "V"    }, // x
+        { 'X',  {1,2,3,4,5,0},  "X"    }, // x
+        { 'x',  {1,2,3,4,5,0},  "x"    }, // x
+    };
+    
+    const char ** localeNamesPtr = localeNames;
+    const char * localeName;
+    while ( (localeName = *localeNamesPtr++) != NULL) {
+        UErrorCode status = U_ZERO_ERROR;
+        Locale locale = Locale::createFromName(localeName);
+        DateTimePatternGenerator * dtpg = DateTimePatternGenerator::createInstance(locale, status);
+        if (U_SUCCESS(status)) {
+            const AllFieldsTestItem * testDataPtr = testData;
+            int itemCount = sizeof(testData) / sizeof(testData[0]);
+            for (; itemCount-- > 0; ++testDataPtr) {
+                char skelBuf[FIELD_LENGTH_MAX];
+                int32_t chrIndx, lenIndx;
+                for (chrIndx = 0; chrIndx < FIELD_LENGTH_MAX; chrIndx++) {
+                    skelBuf[chrIndx] = testDataPtr->patternChar;
+                }
+                for (lenIndx = 0; lenIndx < FIELD_LENGTHS_COUNT; lenIndx++) {
+                    int32_t skelLen = testDataPtr->fieldLengths[lenIndx];
+                    if (skelLen <= 0) {
+                        break;
+                    }
+                    UnicodeString skeleton(skelBuf, skelLen, US_INV);
+                    UnicodeString pattern = dtpg->getBestPattern(skeleton, status);
+                    if (U_SUCCESS(status)) {
+                        // test that resulting pattern has at least one char in mustIncludeOneOf
+                        UnicodeString mustIncludeOneOf(testDataPtr->mustIncludeOneOf, -1, US_INV);
+                        int32_t patIndx, patLen = pattern.length();
+                        UBool inQuoted = FALSE;
+                        for (patIndx = 0; patIndx < patLen; patIndx++) {
+                            UChar c = pattern.charAt(patIndx);
+                            if (c == 0x27) {
+                                inQuoted = !inQuoted;
+                            } else if (!inQuoted && c <= 0x007A &&c >= 0x0041) {
+                                if (mustIncludeOneOf.indexOf(c) >= 0) {
+                                    break;
+                                }
+                            }
+                        }
+                        if (patIndx >= patLen) {
+                            errln(UnicodeString("DateTimePatternGenerator getBestPattern for locale ") +
+                                    UnicodeString(locale.getName(),-1,US_INV) +
+                                    ", skeleton " + skeleton +
+                                    ", produces pattern without required chars: " + pattern);
+                        }
+                        
+                    } else {
+                        errln("DateTimePatternGenerator getBestPattern for locale %s, skelChar %c skelLength %d fails: %s",
+                              locale.getName(), testDataPtr->patternChar, skelLen, u_errorName(status));
+                    }
+                }
+            }
+            delete dtpg;
+        } else {
+            dataerrln("Create DateTimePatternGenerator instance for locale(%s) fails: %s",
+                      locale.getName(), u_errorName(status));
+        }
+    }
+}
 #endif /* #if !UCONFIG_NO_FORMATTING */
index e81e2c1edf3f6f4a4acc9c0be9e2a85b18eccda8..40c24d7869fb4eff1dee8db174becc4d5a862b82 100644 (file)
@@ -1,6 +1,6 @@
 /********************************************************************
  * COPYRIGHT: 
- * Copyright (c) 1997-2001,2009, International Business Machines Corporation and
+ * Copyright (c) 1997-2001,2009,2013, International Business Machines Corporation and
  * others. All Rights Reserved.
  ********************************************************************/
 
@@ -25,6 +25,7 @@ private:
      **/
     void testAPI(/* char* par */);
     void testOptions(/* char* par */);
+    void testAllFieldPatterns(/* char* par */);
 };
 
 #endif /* #if !UCONFIG_NO_FORMATTING */