]> granicus.if.org Git - icu/commitdiff
ICU-13183 for compatibility, get(Base)Skeleton should not include 'a' added by DateTi...
authorPeter Edberg <pedberg@unicode.org>
Wed, 24 May 2017 06:57:45 +0000 (06:57 +0000)
committerPeter Edberg <pedberg@unicode.org>
Wed, 24 May 2017 06:57:45 +0000 (06:57 +0000)
X-SVN-Rev: 40133

icu4c/source/i18n/dtptngen.cpp
icu4c/source/i18n/dtptngen_impl.h
icu4c/source/test/intltest/dtptngts.cpp
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 c91fbbe6f232e335961f480f76e3a3b9c46e5e90..187342e4af2efce910a38a3a2d869273e3bc985a 100644 (file)
@@ -1917,6 +1917,10 @@ DateTimeMatcher::set(const UnicodeString& pattern, FormatParser* fp, PtnSkeleton
     for (i=0; i<UDATPG_FIELD_COUNT; ++i) {
         skeletonResult.type[i] = NONE;
     }
+    skeletonResult.original.clear();
+    skeletonResult.baseOriginal.clear();
+    skeletonResult.addedDefaultDayPeriod = FALSE;
+
     fp->set(pattern);
     for (i=0; i < fp->itemNumber; i++) {
         const UnicodeString& value = fp->items[i];
@@ -1955,6 +1959,7 @@ DateTimeMatcher::set(const UnicodeString& pattern, FormatParser* fp, PtnSkeleton
                         skeletonResult.original.populate(UDATPG_DAYPERIOD_FIELD, dtTypes[i].patternChar, dtTypes[i].minLen);
                         skeletonResult.baseOriginal.populate(UDATPG_DAYPERIOD_FIELD, dtTypes[i].patternChar, dtTypes[i].minLen);
                         skeletonResult.type[UDATPG_DAYPERIOD_FIELD] = dtTypes[i].type;
+                        skeletonResult.addedDefaultDayPeriod = TRUE;
                         break;
                     }
                 }
@@ -2387,13 +2392,27 @@ PtnSkeleton::equals(const PtnSkeleton& other) const  {
 UnicodeString
 PtnSkeleton::getSkeleton() const {
     UnicodeString result;
-    return original.appendTo(result);
+    result = original.appendTo(result);
+    int32_t pos;
+    if (addedDefaultDayPeriod && (pos = result.indexOf(LOW_A)) >= 0) {
+        // for backward compatibility: if DateTimeMatcher.set added a single 'a' that
+        // was not in the provided skeleton, remove it here before returning skeleton.
+        result.remove(pos, 1);
+    }
+    return result;
 }
 
 UnicodeString
 PtnSkeleton::getBaseSkeleton() const {
     UnicodeString result;
-    return baseOriginal.appendTo(result);
+    result = baseOriginal.appendTo(result);
+    int32_t pos;
+    if (addedDefaultDayPeriod && (pos = result.indexOf(LOW_A)) >= 0) {
+        // for backward compatibility: if DateTimeMatcher.set added a single 'a' that
+        // was not in the provided skeleton, remove it here before returning skeleton.
+        result.remove(pos, 1);
+    }
+    return result;
 }
 
 UChar
index 4fbadbb93311c5eab3677a7455eb27f3c372b49e..2ea31a75c488fa55f744d9794c5ee6c626791fc8 100644 (file)
@@ -156,6 +156,7 @@ public:
     int32_t type[UDATPG_FIELD_COUNT];
     SkeletonFields original;
     SkeletonFields baseOriginal;
+    UBool addedDefaultDayPeriod;
 
     PtnSkeleton();
     PtnSkeleton(const PtnSkeleton& other);
index 714ee2e19b8e497fd3704a85db25d4b328961c39..3e21df8aec8996ae42accb06b0192954891f3d33 100644 (file)
@@ -356,6 +356,16 @@ void IntlTestDateTimePatternGeneratorAPI::testAPI(/*char *par*/)
         UnicodeString("MMMMMd"),
     };
 
+    const char* testGetSkeletonAndBase[][3] = {
+        // pattern       skeleton    baseSkeleton
+        { "dd-MMM",     "MMMdd",    "MMMd" },
+        { "dd/MMMM/yy", "yyMMMMdd", "yMMMMd" },
+        { "h",          "h",        "h" },
+        { "ah",         "ah",       "ah" },
+        { "aaaah",      "aaaah",    "aaaah" },
+        { "Bh",         "Bh",       "Bh" }
+    };
+
     UnicodeString newDecimal(" "); // space
     UnicodeString newAppendItemName("hrs.");
     UnicodeString newAppendItemFormat("{1} {0}");
@@ -511,34 +521,25 @@ void IntlTestDateTimePatternGeneratorAPI::testAPI(/*char *par*/)
     }
 
     // ======== Test getSkeleton and getBaseSkeleton
-    status = U_ZERO_ERROR;
-    pattern = UnicodeString("dd-MMM");
-    UnicodeString expectedSkeleton = UnicodeString("MMMdd");
-    UnicodeString expectedBaseSkeleton = UnicodeString("MMMd");
-    UnicodeString retSkeleton = gen->getSkeleton(pattern, status);
-    if(U_FAILURE(status) || retSkeleton != expectedSkeleton ) {
-         errln("ERROR: Unexpected result from getSkeleton().\n");
-         errln(UnicodeString(" Got: ") + retSkeleton + UnicodeString(" Expected: ") + expectedSkeleton );
-    }
-    retSkeleton = gen->getBaseSkeleton(pattern, status);
-    if(U_FAILURE(status) || retSkeleton !=  expectedBaseSkeleton) {
-         errln("ERROR: Unexpected result from getBaseSkeleton().\n");
-         errln(UnicodeString(" Got: ") + retSkeleton + UnicodeString(" Expected:")+ expectedBaseSkeleton);
+    
+    int32_t i, count = UPRV_LENGTHOF(testGetSkeletonAndBase);
+    for (i = 0; i < count; i++) {
+        status = U_ZERO_ERROR;
+        pattern                            = UnicodeString(testGetSkeletonAndBase[i][0]);
+        UnicodeString expectedSkeleton     = UnicodeString(testGetSkeletonAndBase[i][1]);
+        UnicodeString expectedBaseSkeleton = UnicodeString(testGetSkeletonAndBase[i][2]);
+        UnicodeString retSkeleton = gen->getSkeleton(pattern, status);
+               if(U_FAILURE(status) || retSkeleton != expectedSkeleton ) {
+                        errln("ERROR: Unexpected result from getSkeleton().\n");
+                        errln(UnicodeString(" Got: ") + retSkeleton + UnicodeString(" Expected: ") + expectedSkeleton );
+               }
+               retSkeleton = gen->getBaseSkeleton(pattern, status);
+               if(U_FAILURE(status) || retSkeleton !=  expectedBaseSkeleton) {
+                        errln("ERROR: Unexpected result from getBaseSkeleton().\n");
+                        errln(UnicodeString(" Got: ") + retSkeleton + UnicodeString(" Expected:")+ expectedBaseSkeleton);
+               }
     }
 
-    pattern = UnicodeString("dd/MMMM/yy");
-    expectedSkeleton = UnicodeString("yyMMMMdd");
-    expectedBaseSkeleton = UnicodeString("yMMMMd");
-    retSkeleton = gen->getSkeleton(pattern, status);
-    if(U_FAILURE(status) || retSkeleton != expectedSkeleton ) {
-         errln("ERROR: Unexpected result from getSkeleton().\n");
-         errln(UnicodeString(" Got: ") + retSkeleton + UnicodeString(" Expected: ") + expectedSkeleton );
-    }
-    retSkeleton = gen->getBaseSkeleton(pattern, status);
-    if(U_FAILURE(status) || retSkeleton !=  expectedBaseSkeleton) {
-         errln("ERROR: Unexpected result from getBaseSkeleton().\n");
-         errln(UnicodeString(" Got: ") + retSkeleton + UnicodeString(" Expected:")+ expectedBaseSkeleton);
-    }
     delete format;
     delete zone;
     delete gen;
@@ -711,7 +712,6 @@ void IntlTestDateTimePatternGeneratorAPI::testAPI(/*char *par*/)
         return;
     }
     UChar newChar;
-    int32_t i;
     for (i=0; i<10; ++i) {
         UnicodeString randomSkeleton;
         int32_t len = rand() % 20;
@@ -771,7 +771,7 @@ void IntlTestDateTimePatternGeneratorAPI::testAPI(/*char *par*/)
     }
     UnicodeString returnPattern, *ptrSkeleton;
     ptrSkeletonEnum->reset(status);
-    int32_t count=ptrSkeletonEnum->count(status);
+    count=ptrSkeletonEnum->count(status);
     for (i=0; i<count; ++i) {
         ptrSkeleton = (UnicodeString *)ptrSkeletonEnum->snext(status);
         returnPattern = test->getPatternForSkeleton(*ptrSkeleton);
@@ -1137,14 +1137,14 @@ enum { kCharBufMax = 31 };
 void IntlTestDateTimePatternGeneratorAPI::testSkeletonsWithDayPeriods() {
     const char * patterns[] = {
         // since icu4c getEmptyInstance does not call addCanonicalItems (unlike J), set these here:
-        "a",    // should get skeleton a
-        "H",    // should get skeleton H
-        "m",    // should get skeleton m
-        "s",    // should get skeleton s
+        "a",    // should get internal skeleton a
+        "H",    // should get internalskeleton H
+        "m",    // should get internalskeleton m
+        "s",    // should get internalskeleton s
         // patterns from which to construct sample data for a locale
-        //"H",    // should get skeleton H
-        "h a",  // should get skeleton ah
-        "B h",  // should get skeleton Bh
+        //"H",  // should get internalskeleton H
+        "h a",  // should get internalskeleton ah
+        "B h",  // should get internalskeleton Bh
     };
     const char* testItems[][2] = {
         // sample requested skeletons and results
index 21bf7615eb0e9857ff17db7c14f2ed9a86d733d0..1b87e5fbf3246abe9e72abce5ccf359b5e1b4e0e 100644 (file)
@@ -2353,19 +2353,30 @@ public class DateTimePatternGenerator implements Freezable<DateTimePatternGenera
 
         @Override
         public String toString() {
-            return appendTo(new StringBuilder()).toString();
+            return appendTo(new StringBuilder(), false, false).toString();
+        }
+
+        public String toString(boolean skipDayPeriod) {
+            return appendTo(new StringBuilder(), false, skipDayPeriod).toString();
         }
 
         public String toCanonicalString() {
-            return appendTo(new StringBuilder(), true).toString();
+            return appendTo(new StringBuilder(), true, false).toString();
+        }
+
+        public String toCanonicalString(boolean skipDayPeriod) {
+            return appendTo(new StringBuilder(), true, skipDayPeriod).toString();
         }
 
         public StringBuilder appendTo(StringBuilder sb) {
-            return appendTo(sb, false);
+            return appendTo(sb, false, false);
         }
 
-        private StringBuilder appendTo(StringBuilder sb, boolean canonical) {
+        private StringBuilder appendTo(StringBuilder sb, boolean canonical, boolean skipDayPeriod) {
             for (int i=0; i<TYPE_LIMIT; ++i) {
+                if (skipDayPeriod && i == DAYPERIOD) {
+                    continue;
+                }
                 appendFieldTo(i, sb, canonical);
             }
             return sb;
@@ -2421,6 +2432,7 @@ public class DateTimePatternGenerator implements Freezable<DateTimePatternGenera
         private int[] type = new int[TYPE_LIMIT];
         private SkeletonFields original = new SkeletonFields();
         private SkeletonFields baseOriginal = new SkeletonFields();
+        private boolean addedDefaultDayPeriod = false;
 
         // just for testing; fix to make multi-threaded later
         // private static FormatParser fp = new FormatParser();
@@ -2431,18 +2443,27 @@ public class DateTimePatternGenerator implements Freezable<DateTimePatternGenera
 
         @Override
         public String toString() {
-            return original.toString();
+            // for backward compatibility: addedDefaultDayPeriod true => DateTimeMatcher.set
+            // added a single 'a' that was not in the provided skeleton, and it will be
+            // removed when generating the skeleton to return.
+            return original.toString(addedDefaultDayPeriod);
         }
 
         // returns a string like toString but using the canonical character for most types,
         // e.g. M for M or L, E for E or c, y for y or U, etc. The hour field is canonicalized
         // to 'H' (for 24-hour types) or 'h' (for 12-hour types)
         public String toCanonicalString() {
-            return original.toCanonicalString();
+            // for backward compatibility: addedDefaultDayPeriod true => DateTimeMatcher.set
+            // added a single 'a' that was not in the provided skeleton, and it will be
+            // removed when generating the skeleton to return.
+            return original.toCanonicalString(addedDefaultDayPeriod);
         }
 
         String getBasePattern() {
-            return baseOriginal.toString();
+            // for backward compatibility: addedDefaultDayPeriod true => DateTimeMatcher.set
+            // added a single 'a' that was not in the provided skeleton, and it will be
+            // removed when generating the skeleton to return.
+            return baseOriginal.toString(addedDefaultDayPeriod);
         }
 
         DateTimeMatcher set(String pattern, FormatParser fp, boolean allowDuplicateFields) {
@@ -2450,6 +2471,7 @@ public class DateTimePatternGenerator implements Freezable<DateTimePatternGenera
             Arrays.fill(type, NONE);
             original.clear();
             baseOriginal.clear();
+            addedDefaultDayPeriod = false;
 
             fp.set(pattern);
             for (Object obj : fp.getItems()) {
@@ -2499,6 +2521,7 @@ public class DateTimePatternGenerator implements Freezable<DateTimePatternGenera
                                 original.populate(DAYPERIOD, (char)row[0], row[3]);
                                 baseOriginal.populate(DAYPERIOD, (char)row[0], row[3]);
                                 type[DAYPERIOD] = row[2];
+                                addedDefaultDayPeriod = true;
                                 break;
                             }
                         }
index fb8c5126c47ed077202c154cec6d7b9ffc4970c9..d3c9e73f004b962f9e43a6bf7bfef5f95458b083 100644 (file)
@@ -91,7 +91,7 @@ public class DateTimeGeneratorTest extends TestFmwk {
                 // sample data in a locale (base is not in locale, just here for test)
                 // skel (base) pattern
                 { "aH", "H",  "H"  }, // should ignore a
-                { "h",  "ah", "h a"},
+                { "h",  "h",  "h a"},
                 { "Bh", "Bh", "B h"},
         };
         String[][] testItems = {
@@ -871,8 +871,8 @@ public class DateTimeGeneratorTest extends TestFmwk {
     @Test
     public void TestGetSkeleton(){
         DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance();
-        String[] cases = {"MMDD","MMMDD","MMM-DD","DD/MMM","ddM","MMMMd"};
-        String[] results = {"MMDD","MMMDD","MMMDD","MMMDD","Mdd","MMMMd"};
+        String[] cases = {"MMDD","MMMDD","MMM-DD","DD/MMM","ddM","MMMMd","h","ah","aaaah","Bh"};
+        String[] results = {"MMDD","MMMDD","MMMDD","MMMDD","Mdd","MMMMd","h","ah","aaaah","Bh"};
         for(int i=0; i<cases.length; i++){
             if(!dtpg.getSkeleton(cases[i]).equals(results[i])){
                 errln("DateTimePatternGenerator.getSkeleton(String) did " +