]> granicus.if.org Git - icu/commitdiff
ICU-10637 Format/parse using 'r', C part 2 (add tests, clean up islamic delta calcula...
authorPeter Edberg <pedberg@unicode.org>
Thu, 6 Mar 2014 09:47:25 +0000 (09:47 +0000)
committerPeter Edberg <pedberg@unicode.org>
Thu, 6 Mar 2014 09:47:25 +0000 (09:47 +0000)
X-SVN-Rev: 35355

icu4c/source/i18n/calendar.cpp
icu4c/source/test/intltest/dtfmrgts.cpp
icu4c/source/test/intltest/dtfmttst.cpp

index 0a240e504b4012d56cbc22de94403152c4c22de2..3931570e14b4f00458f99fcbb6348b0f523684ca 100644 (file)
@@ -106,7 +106,7 @@ U_CDECL_END
 */
 
 const char* fldName(UCalendarDateFields f) {
-       return udbg_enumName(UDBG_UCalendarDateFields, (int32_t)f);
+    return udbg_enumName(UDBG_UCalendarDateFields, (int32_t)f);
 }
 
 #if UCAL_DEBUG_DUMP
@@ -740,7 +740,7 @@ fSkippedWallTime(UCAL_WALLTIME_LAST)
     clear();
     fZone = zone.clone();
     if (fZone == NULL) {
-       success = U_MEMORY_ALLOCATION_ERROR;
+        success = U_MEMORY_ALLOCATION_ERROR;
     }
     setWeekData(aLocale, NULL, success);
 }
@@ -1168,18 +1168,35 @@ Calendar::set(int32_t year, int32_t month, int32_t date, int32_t hour, int32_t m
 // per #10752 move the non-default implementation to subclasses
 // (default implementation will do no year adjustment)
 
+static int32_t gregoYearFromIslamicStart(int32_t year) {
+    // ad hoc conversion, improve under #10752
+    // rough est for now, ok for grego 1846-2138,
+    // otherwise occasionally wrong (for 3% of years)
+    int cycle, offset, shift = 0;
+    if (year >= 1397) {
+        cycle = (year - 1397) / 67;
+        offset = (year - 1397) % 67;
+        shift = 2*cycle + ((offset >= 33)? 1: 0);
+    } else {
+        cycle = (year - 1396) / 67 - 1;
+        offset = -(year - 1396) % 67;
+        shift = 2*cycle + ((offset <= 33)? 1: 0);
+    }
+    return year + 579 - shift;
+}
+
 int32_t Calendar::getRelatedYear(UErrorCode &status) const
 {
     if (U_FAILURE(status)) {
         return 0;
     }
-       int32_t year = get(UCAL_EXTENDED_YEAR, status);
+    int32_t year = get(UCAL_EXTENDED_YEAR, status);
     if (U_FAILURE(status)) {
         return 0;
     }
     // modify for calendar type
-       ECalType type = getCalendarType(getType());
-       switch (type) {
+    ECalType type = getCalendarType(getType());
+    switch (type) {
         case CALTYPE_PERSIAN:
             year += 622; break;
         case CALTYPE_HEBREW:
@@ -1201,21 +1218,7 @@ int32_t Calendar::getRelatedYear(UErrorCode &status) const
         case CALTYPE_ISLAMIC_UMALQURA:
         case CALTYPE_ISLAMIC_TBLA:
         case CALTYPE_ISLAMIC_RGSA:
-            // ad hoc conversion, improve under #10752
-            {
-                           int cycle, offset, shift = 0;
-                           if (year >= 1397) {
-                                   cycle = (year - 1397) / 67;
-                                   offset = (year - 1397) % 67;
-                                   shift = 2*cycle + ((offset >= 33)? 1: 0);
-                           } else {
-                                   cycle = (year - 1396) / 67 - 1;
-                                   offset = -(year - 1396) % 67;
-                                   shift = 2*cycle + ((offset <= 33)? 1: 0);
-                           }
-                           year += 579 - shift;
-                       }
-            break;
+            year = gregoYearFromIslamicStart(year); break;
         default:
             // CALTYPE_GREGORIAN
             // CALTYPE_JAPANESE
@@ -1224,8 +1227,8 @@ int32_t Calendar::getRelatedYear(UErrorCode &status) const
             // CALTYPE_ISO8601
             // do nothing, EXTENDED_YEAR same as Gregorian
             break;
-       }
-       return year;
+    }
+    return year;
 }
 
 // -------------------------------------
@@ -1233,11 +1236,27 @@ int32_t Calendar::getRelatedYear(UErrorCode &status) const
 // per #10752 move the non-default implementation to subclasses
 // (default implementation will do no year adjustment)
 
+static int32_t firstIslamicStartYearFromGrego(int32_t year) {
+    // ad hoc conversion, improve under #10752
+    // rough est for now, ok for grego 1846-2138,
+    // otherwise occasionally wrong (for 3% of years)
+    int cycle, offset, shift = 0;
+    if (year >= 1977) {
+        cycle = (year - 1977) / 65;
+        offset = (year - 1977) % 65;
+        shift = 2*cycle + ((offset >= 32)? 1: 0);
+    } else {
+        cycle = (year - 1976) / 65 - 1;
+        offset = -(year - 1976) % 65;
+        shift = 2*cycle + ((offset <= 32)? 1: 0);
+    }
+    return year - 579 + shift;
+}
 void Calendar::setRelatedYear(int32_t year)
 {
     // modify for calendar type
-       ECalType type = getCalendarType(getType());
-       switch (type) {
+    ECalType type = getCalendarType(getType());
+    switch (type) {
         case CALTYPE_PERSIAN:
             year -= 622; break;
         case CALTYPE_HEBREW:
@@ -1259,9 +1278,7 @@ void Calendar::setRelatedYear(int32_t year)
         case CALTYPE_ISLAMIC_UMALQURA:
         case CALTYPE_ISLAMIC_TBLA:
         case CALTYPE_ISLAMIC_RGSA:
-            // needs adjustment, will do under #10752
-            year -= 578; // handles current year +/- a few
-            break;
+            year = firstIslamicStartYearFromGrego(year); break;
         default:
             // CALTYPE_GREGORIAN
             // CALTYPE_JAPANESE
@@ -1270,9 +1287,9 @@ void Calendar::setRelatedYear(int32_t year)
             // CALTYPE_ISO8601
             // do nothing, EXTENDED_YEAR same as Gregorian
             break;
-       }
-       // set extended year
-       set(UCAL_EXTENDED_YEAR, year);
+    }
+    // set extended year
+    set(UCAL_EXTENDED_YEAR, year);
 }
 
 // -------------------------------------
@@ -2438,11 +2455,11 @@ Calendar::getDayOfWeekType(UCalendarDaysOfWeek dayOfWeek, UErrorCode &status) co
         status = U_ILLEGAL_ARGUMENT_ERROR;
         return UCAL_WEEKDAY;
     }
-       if (fWeekendOnset == fWeekendCease) {
-               if (dayOfWeek != fWeekendOnset)
-                       return UCAL_WEEKDAY;
-               return (fWeekendOnsetMillis == 0) ? UCAL_WEEKEND : UCAL_WEEKEND_ONSET;
-       }
+    if (fWeekendOnset == fWeekendCease) {
+        if (dayOfWeek != fWeekendOnset)
+            return UCAL_WEEKDAY;
+        return (fWeekendOnsetMillis == 0) ? UCAL_WEEKEND : UCAL_WEEKEND_ONSET;
+    }
     if (fWeekendOnset < fWeekendCease) {
         if (dayOfWeek < fWeekendOnset || dayOfWeek > fWeekendCease) {
             return UCAL_WEEKDAY;
index 2f482e2000dc8a70d6081e5f2052149281a67231..992fd3d8ab8f94486db4afd5322a970b98808031 100644 (file)
@@ -1630,26 +1630,28 @@ void DateFormatRegressionTest::TestT10619(void) {
         const TestDateFormatLeniencyItem * itemPtr;
         for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
                                             
-           Locale locale = Locale::createFromName(itemPtr->locale);
-           status = U_ZERO_ERROR;
-           ParsePosition pos(0);
-           SimpleDateFormat * sdmft = new SimpleDateFormat(itemPtr->pattern, locale, status);
-           if (U_FAILURE(status)) {
-               dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
-               continue;
-           }
-           sdmft->setLenient(itemPtr->leniency);
-           sdmft->setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, itemPtr->leniency, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, itemPtr->leniency, status);
-           /*UDate d = */sdmft->parse(itemPtr->parseString, pos);
-
-           delete sdmft;
-           if(pos.getErrorIndex() > -1)
-               if(itemPtr->expectedResult.length() != 0) {
-                 errln("error: unexpected error - " + itemPtr->parseString + " - error index " + pos.getErrorIndex() + " - leniency " + itemPtr->leniency);
-                 continue;
-               } else {
-                 continue;
-               }
+            Locale locale = Locale::createFromName(itemPtr->locale);
+            status = U_ZERO_ERROR;
+            ParsePosition pos(0);
+            SimpleDateFormat * sdmft = new SimpleDateFormat(itemPtr->pattern, locale, status);
+            if (U_FAILURE(status)) {
+                dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
+                continue;
+            }
+            sdmft->setLenient(itemPtr->leniency);
+            sdmft->setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, itemPtr->leniency, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, itemPtr->leniency, status);
+            /*UDate d = */sdmft->parse(itemPtr->parseString, pos);
+
+            delete sdmft;
+            if(pos.getErrorIndex() > -1) {
+                if(itemPtr->expectedResult.length() != 0) {
+                   errln("error: unexpected error - " + itemPtr->parseString + " - error index " + pos.getErrorIndex() +
+                           " - leniency " + itemPtr->leniency);
+                   continue;
+                } else {
+                   continue;
+                }
+            }
         }
     }
     delete cal;
index c38e8a766cb5e724c2fd0e453f001547450a1f13..b04087b97971b37e2ac4aee62b4d3a4acf5e589e 100644 (file)
@@ -4052,6 +4052,7 @@ void DateFormatTest::TestContext()
 
 // test item for a particular locale + calendar and date format
 typedef struct {
+    int32_t era;
     int32_t year;
     int32_t month;
     int32_t day;
@@ -4064,6 +4065,7 @@ typedef struct {
 typedef struct {
     const char * locale; // with calendar
     DateFormat::EStyle style;
+    UnicodeString pattern; // ignored unless style == DateFormat::kNone
     const CalAndFmtTestItem *caftItems;
 } TestNonGregoItem;
 
@@ -4071,23 +4073,62 @@ void DateFormatTest::TestNonGregoFmtParse()
 {
     // test items for he@calendar=hebrew, long date format
     const CalAndFmtTestItem cafti_he_hebrew_long[] = {
-        { 4999, 12, 29, 12, 0, CharsToUnicodeString("\\u05DB\\u05F4\\u05D8 \\u05D1\\u05D0\\u05DC\\u05D5\\u05DC \\u05D3\\u05F3\\u05EA\\u05EA\\u05E7\\u05E6\\u05F4\\u05D8") },
-        { 5100,  0,  1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05EA\\u05E9\\u05E8\\u05D9 \\u05E7\\u05F3") },
-        { 5774,  5,  1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05D0\\u05D3\\u05E8 \\u05D0\\u05F3 \\u05EA\\u05E9\\u05E2\\u05F4\\u05D3") },
-        { 5999, 12, 29, 12, 0, CharsToUnicodeString("\\u05DB\\u05F4\\u05D8 \\u05D1\\u05D0\\u05DC\\u05D5\\u05DC \\u05EA\\u05EA\\u05E7\\u05E6\\u05F4\\u05D8") },
-        { 6100,  0,  1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05EA\\u05E9\\u05E8\\u05D9 \\u05D5\\u05F3\\u05E7\\u05F3") },
-        {    0,  0,  0,  0, 0, UnicodeString("") } // terminator
+        {  0, 4999, 12, 29, 12, 0, CharsToUnicodeString("\\u05DB\\u05F4\\u05D8 \\u05D1\\u05D0\\u05DC\\u05D5\\u05DC \\u05D3\\u05F3\\u05EA\\u05EA\\u05E7\\u05E6\\u05F4\\u05D8") },
+        {  0, 5100,  0,  1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05EA\\u05E9\\u05E8\\u05D9 \\u05E7\\u05F3") },
+        {  0, 5774,  5,  1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05D0\\u05D3\\u05E8 \\u05D0\\u05F3 \\u05EA\\u05E9\\u05E2\\u05F4\\u05D3") },
+        {  0, 5999, 12, 29, 12, 0, CharsToUnicodeString("\\u05DB\\u05F4\\u05D8 \\u05D1\\u05D0\\u05DC\\u05D5\\u05DC \\u05EA\\u05EA\\u05E7\\u05E6\\u05F4\\u05D8") },
+        {  0, 6100,  0,  1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05EA\\u05E9\\u05E8\\u05D9 \\u05D5\\u05F3\\u05E7\\u05F3") },
+        {  0,    0,  0,  0,  0, 0, UnicodeString("") } // terminator
+    };
+    const CalAndFmtTestItem cafti_zh_chinese_custU[] = {
+        { 78,   31,  0,  1, 12, 0, CharsToUnicodeString("2014\\u7532\\u5348\\u5E74\\u6B63\\u67081") },
+        { 77,   31,  0,  1, 12, 0, CharsToUnicodeString("1954\\u7532\\u5348\\u5E74\\u6B63\\u67081") },
+        {  0,    0,  0,  0,  0, 0, UnicodeString("") } // terminator
+    };
+    const CalAndFmtTestItem cafti_zh_chinese_custNoU[] = {
+        { 78,   31,  0,  1, 12, 0, CharsToUnicodeString("2014\\u5E74\\u6B63\\u67081") },
+        { 77,   31,  0,  1, 12, 0, CharsToUnicodeString("1954\\u5E74\\u6B63\\u67081") },
+        {  0,    0,  0,  0,  0, 0, UnicodeString("") } // terminator
+    };
+    const CalAndFmtTestItem cafti_ja_japanese_custGy[] = {
+        {235,   26,  2,  5, 12, 0, CharsToUnicodeString("2014(\\u5E73\\u621026)\\u5E743\\u67085\\u65E5") },
+        {234,   60,  2,  5, 12, 0, CharsToUnicodeString("1985(\\u662D\\u548C60)\\u5E743\\u67085\\u65E5") },
+        {  0,    0,  0,  0,  0, 0, UnicodeString("") } // terminator
+    };
+    const CalAndFmtTestItem cafti_ja_japanese_custNoGy[] = {
+        {235,   26,  2,  5, 12, 0, CharsToUnicodeString("2014\\u5E743\\u67085\\u65E5") },
+        {234,   60,  2,  5, 12, 0, CharsToUnicodeString("1985\\u5E743\\u67085\\u65E5") },
+        {  0,    0,  0,  0,  0, 0, UnicodeString("") } // terminator
+    };
+    const CalAndFmtTestItem cafti_en_islamic_cust[] = {
+        {  0, 1384,  0,  1, 12, 0, UnicodeString("1 Muh. 1384 AH, 1964") },
+        {  0, 1436,  0,  1, 12, 0, UnicodeString("1 Muh. 1436 AH, 2014") },
+        {  0, 1487,  0,  1, 12, 0, UnicodeString("1 Muh. 1487 AH, 2064") },
+        {  0,    0,  0,  0,  0, 0, UnicodeString("") } // terminator
     };
     // overal test items
     const TestNonGregoItem items[] = {
-        { "he@calendar=hebrew", DateFormat::kLong, cafti_he_hebrew_long },
-        { NULL, DateFormat::kNone, NULL } // terminator
+        { "he@calendar=hebrew",   DateFormat::kLong, UnicodeString(""),                 cafti_he_hebrew_long },
+        { "zh@calendar=chinese",  DateFormat::kNone, CharsToUnicodeString("rU\\u5E74MMMd"),                cafti_zh_chinese_custU },
+        { "zh@calendar=chinese",  DateFormat::kNone, CharsToUnicodeString("r\\u5E74MMMd"),                 cafti_zh_chinese_custNoU },
+        { "ja@calendar=japanese", DateFormat::kNone, CharsToUnicodeString("r(Gy)\\u5E74M\\u6708d\\u65E5"), cafti_ja_japanese_custGy },
+        { "ja@calendar=japanese", DateFormat::kNone, CharsToUnicodeString("r\\u5E74M\\u6708d\\u65E5"),     cafti_ja_japanese_custNoGy },
+        { "en@calendar=islamic",  DateFormat::kNone, UnicodeString("d MMM y G, r"),     cafti_en_islamic_cust },
+        { NULL, DateFormat::kNone, UnicodeString(""), NULL } // terminator
     };
     const TestNonGregoItem * itemPtr;
     for (itemPtr = items; itemPtr->locale != NULL; itemPtr++) {
         Locale locale = Locale::createFromName(itemPtr->locale);
-        DateFormat * dfmt = DateFormat::createDateInstance(itemPtr->style, locale);
-        if (dfmt == NULL) {
+        DateFormat * dfmt = NULL;
+        UErrorCode status = U_ZERO_ERROR;
+        if (itemPtr->style != DateFormat::kNone) {
+            dfmt = DateFormat::createDateInstance(itemPtr->style, locale);
+        } else {
+            dfmt = new SimpleDateFormat(itemPtr->pattern, locale, status);
+        }
+        if (U_FAILURE(status)) {
+            dataerrln("new SimpleDateFormat fails for locale %s", itemPtr->locale);
+        } else  if (dfmt == NULL) {
             dataerrln("DateFormat::createDateInstance fails for locale %s", itemPtr->locale);
         } else {
             Calendar * cal = (dfmt->getCalendar())->clone();
@@ -4097,6 +4138,7 @@ void DateFormatTest::TestNonGregoFmtParse()
                 const CalAndFmtTestItem * caftItemPtr;
                 for (caftItemPtr = itemPtr->caftItems; caftItemPtr->year != 0; caftItemPtr++) {
                     cal->clear();
+                    cal->set(UCAL_ERA,    caftItemPtr->era);
                     cal->set(UCAL_YEAR,   caftItemPtr->year);
                     cal->set(UCAL_MONTH,  caftItemPtr->month);
                     cal->set(UCAL_DATE,   caftItemPtr->day);
@@ -4112,13 +4154,16 @@ void DateFormatTest::TestNonGregoFmtParse()
                         // formatted OK, try parse
                         ParsePosition ppos(0);
                         dfmt->parse(result, *cal, ppos);
-                        UErrorCode status = U_ZERO_ERROR;
+                        status = U_ZERO_ERROR;
+                        int32_t era = cal->get(UCAL_ERA, status);
                         int32_t year = cal->get(UCAL_YEAR, status);
                         int32_t month = cal->get(UCAL_MONTH, status);
                         int32_t day = cal->get(UCAL_DATE, status);
-                        if ( U_FAILURE(status) || ppos.getIndex() < result.length() || year != caftItemPtr->year || month != caftItemPtr->month || day != caftItemPtr->day ) {
-                            errln( UnicodeString("FAIL: date parse for locale ") + UnicodeString(itemPtr->locale) + ", style " + itemPtr->style +
-                                ", string \"" + result + "\", expected " + caftItemPtr->year +"-"+caftItemPtr->month+"-"+caftItemPtr->day + ", got pos " +
+                        if ( U_FAILURE(status) || ppos.getIndex() < result.length() || era != caftItemPtr->era ||
+                                year != caftItemPtr->year || month != caftItemPtr->month || day != caftItemPtr->day ) {
+                            errln( UnicodeString("FAIL: date parse for locale ") + UnicodeString(itemPtr->locale) +
+                                ", style " + itemPtr->style + ", string \"" + result + "\", expected " +
+                                caftItemPtr->era +":"+caftItemPtr->year +"-"+caftItemPtr->month+"-"+caftItemPtr->day + ", got pos " +
                                 ppos.getIndex() + " " + year +"-"+month+"-"+day + " status " + UnicodeString(u_errorName(status)) );
                         }
                     }