ICU-9256 For he@calendar=hebrew, offset the years within the current millenium down to 1-999

X-SVN-Rev: 32236
This commit is contained in:
Peter Edberg 2012-08-27 05:58:17 +00:00
parent 2f41905b0b
commit 00b9ba863a
3 changed files with 103 additions and 4 deletions

View 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 )

View 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

View File

@ -179,6 +179,8 @@ public: // package
void TestContext(void);
void TestNonGregoFmtParse(void);
public:
/**
* Test host-specific formatting.