]> granicus.if.org Git - icu/commitdiff
ICU-9256 For he@calendar=hebrew, offset the years within the current millenium down...
authorPeter Edberg <pedberg@unicode.org>
Mon, 27 Aug 2012 05:58:17 +0000 (05:58 +0000)
committerPeter Edberg <pedberg@unicode.org>
Mon, 27 Aug 2012 05:58:17 +0000 (05:58 +0000)
X-SVN-Rev: 32236

icu4c/source/i18n/smpdtfmt.cpp
icu4c/source/test/intltest/dtfmttst.cpp
icu4c/source/test/intltest/dtfmttst.h

index 01b819d22779c564ee9460936881c3b76564b4ea..985c95215b9adbf4be919dc62c3f429522f4e874 100644 (file)
@@ -204,6 +204,12 @@ static const int32_t gFieldRangeBias[] = {
     -1,  // 'U' - UDAT_YEAR_NAME_FIELD
 };
 
+// When calendar uses hebr numbering (i.e. he@calendar=hebrew),
+// offset the years within the current millenium down to 1-999
+static const int32_t HEBREW_CAL_CUR_MILLENIUM_START_YEAR = 5000;
+static const int32_t HEBREW_CAL_CUR_MILLENIUM_END_YEAR = 6000;
+
+
 static UMTX LOCK;
 
 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SimpleDateFormat)
@@ -1223,6 +1229,8 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
     }
 
     currentNumberFormat = getNumberFormatByIndex(patternCharIndex);
+    UnicodeString hebr("hebr", 4, US_INV);
+    
     switch (patternCharIndex) {
 
     // for any "G" symbol, write out the appropriate era string
@@ -1262,6 +1270,9 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
 //AD 12345 12345     45   12345    12345     12345
     case UDAT_YEAR_FIELD:
     case UDAT_YEAR_WOY_FIELD:
+        if (fDateOverride.compare(hebr)==0 && value>HEBREW_CAL_CUR_MILLENIUM_START_YEAR && value<HEBREW_CAL_CUR_MILLENIUM_END_YEAR) {
+            value-=HEBREW_CAL_CUR_MILLENIUM_START_YEAR;
+        }
         if(count == 2)
             zeroPaddingNumber(currentNumberFormat, appendTo, value, 2, 2);
         else
@@ -2343,6 +2354,7 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
     patternCharIndex = (UDateFormatField)(patternCharPtr - DateFormatSymbols::getPatternUChars());
     currentNumberFormat = getNumberFormatByIndex(patternCharIndex);
     UCalendarDateFields field = fgPatternIndexToCalendarField[patternCharIndex];
+    UnicodeString hebr("hebr", 4, US_INV);
 
     if (numericLeapMonthFormatter != NULL) {
         numericLeapMonthFormatter->setFormats((const Format **)&currentNumberFormat, 1);
@@ -2509,7 +2521,9 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
         // we made adjustments to place the 2-digit year in the proper
         // century, for parsed strings from "00" to "99".  Any other string
         // is treated literally:  "2250", "-1", "1", "002".
-        if ((pos.getIndex() - start) == 2 && !isChineseCalendar
+        if (fDateOverride.compare(hebr)==0 && value < 1000) {
+            value += HEBREW_CAL_CUR_MILLENIUM_START_YEAR;
+        } else if ((pos.getIndex() - start) == 2 && !isChineseCalendar
             && u_isdigit(text.charAt(start))
             && u_isdigit(text.charAt(start+1)))
         {
@@ -2544,7 +2558,9 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
 
     case UDAT_YEAR_WOY_FIELD:
         // Comment is the same as for UDAT_Year_FIELDs - look above
-        if ((pos.getIndex() - start) == 2
+        if (fDateOverride.compare(hebr)==0 && value < 1000) {
+            value += HEBREW_CAL_CUR_MILLENIUM_START_YEAR;
+        } else if ((pos.getIndex() - start) == 2
             && u_isdigit(text.charAt(start))
             && u_isdigit(text.charAt(start+1))
             && fHaveDefaultCentury )
index 7832af732c105b143b55717d842c5f948cb6e2fd..15a101a207ade83daeae32defa22437932cec4b0 100644 (file)
@@ -86,9 +86,10 @@ void DateFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &nam
         TESTCASE(46,TestParsePosition);
         TESTCASE(47,TestMonthPatterns);
         TESTCASE(48,TestContext);
+        TESTCASE(49,TestNonGregoFmtParse);
         /*
-        TESTCASE(49,TestRelativeError);
-        TESTCASE(50,TestRelativeOther);
+        TESTCASE(50,TestRelativeError);
+        TESTCASE(51,TestRelativeOther);
         */
         default: name = ""; break;
     }
@@ -3896,6 +3897,86 @@ void DateFormatTest::TestContext()
     }
 }
 
+// test item for a particular locale + calendar and date format
+typedef struct {
+    int32_t year;
+    int32_t month;
+    int32_t day;
+    int32_t hour;
+    int32_t minute;
+    UnicodeString formattedDate;
+} CalAndFmtTestItem;
+
+// test item giving locale + calendar, date format, and CalAndFmtTestItems
+typedef struct {
+    const char * locale; // with calendar
+    DateFormat::EStyle style;
+    const CalAndFmtTestItem *caftItems;
+} TestNonGregoItem;
+
+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
+    };
+    // overal test items
+    const TestNonGregoItem items[] = {
+        { "he@calendar=hebrew", DateFormat::kLong, cafti_he_hebrew_long },
+        { NULL, DateFormat::kNone, 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) {
+            dataerrln("DateFormat::createDateInstance fails for locale %s", itemPtr->locale);
+        } else {
+            Calendar * cal = (dfmt->getCalendar())->clone();
+            if (cal == NULL) {
+                dataerrln("(DateFormat::getCalendar)->clone() fails for locale %s", itemPtr->locale);
+            } else {
+                const CalAndFmtTestItem * caftItemPtr;
+                for (caftItemPtr = itemPtr->caftItems; caftItemPtr->year != 0; caftItemPtr++) {
+                    cal->clear();
+                    cal->set(UCAL_YEAR,   caftItemPtr->year);
+                    cal->set(UCAL_MONTH,  caftItemPtr->month);
+                    cal->set(UCAL_DATE,   caftItemPtr->day);
+                    cal->set(UCAL_HOUR_OF_DAY, caftItemPtr->hour);
+                    cal->set(UCAL_MINUTE, caftItemPtr->minute);
+                    UnicodeString result;
+                    FieldPosition fpos(0);
+                    dfmt->format(*cal, result, fpos);
+                    if ( result.compare(caftItemPtr->formattedDate) != 0 ) {
+                        errln( UnicodeString("FAIL: date format for locale ") + UnicodeString(itemPtr->locale) + ", style " + itemPtr->style +
+                                ", expected \"" + caftItemPtr->formattedDate + "\", got \"" + result + "\"");
+                    } else {
+                        // formatted OK, try parse
+                        ParsePosition ppos(0);
+                        dfmt->parse(result, *cal, ppos);
+                        UErrorCode status = U_ZERO_ERROR;
+                        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 " +
+                                ppos.getIndex() + " " + year +"-"+month+"-"+day + " status " + UnicodeString(u_errorName(status)) );
+                        }
+                    }
+                }
+                delete cal;
+            }
+            delete dfmt;
+        }
+    }
+}
+
 #endif /* #if !UCONFIG_NO_FORMATTING */
 
 //eof
index 84513d46ffaec834346c405aa0a4d9edfaa146cb..204f626431298d75d680b56e789705ab010237d4 100644 (file)
@@ -179,6 +179,8 @@ public: // package
 
     void TestContext(void);
 
+    void TestNonGregoFmtParse(void);
+
 public:
     /**
      * Test host-specific formatting.