ICU-10637 Format/parse using 'r', C part 2 (add tests, clean up islamic delta calculation)

X-SVN-Rev: 35355
This commit is contained in:
Peter Edberg 2014-03-06 09:47:25 +00:00
parent 7202567040
commit 5241507312
3 changed files with 132 additions and 68 deletions

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

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

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