ICU-6104 fixed the inconsistent behavior of DateTimePatternGen between ICU4C and ICU4J.

X-SVN-Rev: 23156
This commit is contained in:
Claire Ho 2008-01-03 01:40:16 +00:00
parent 7490278152
commit 307a3f8307
3 changed files with 103 additions and 8 deletions

View File

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 2007, International Business Machines Corporation and
* Copyright (C) 2008, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*
@ -119,6 +119,8 @@ static const char* Resource_Fields[] = {
"day", "dayperiod", "era", "hour", "minute", "month", "second", "week",
"weekday", "year", "zone", "quarter" };
static const char* CJKLangName[] = { "zh", "ja", "ko" }; // for ChineseMonthHack
// For appendItems
static const UChar UDATPG_ItemFormat[]= {0x7B, 0x30, 0x7D, 0x20, 0x251C, 0x7B, 0x32, 0x7D, 0x3A,
0x20, 0x7B, 0x31, 0x7D, 0x2524, 0}; // {0} \u251C{2}: {1}\u2524
@ -157,6 +159,7 @@ DateTimePatternGenerator::DateTimePatternGenerator(UErrorCode &status) : UObject
fStatus = U_ZERO_ERROR;
skipMatcher = NULL;
fAvailableFormatKeyHash=NULL;
chineseMonthHack = FALSE;
fp = new FormatParser();
dtMatcher = new DateTimeMatcher();
distanceInfo = new DistanceInfo();
@ -201,6 +204,7 @@ DateTimePatternGenerator::operator=(const DateTimePatternGenerator& other) {
*distanceInfo = *(other.distanceInfo);
dateTimeFormat = other.dateTimeFormat;
decimal = other.decimal;
chineseMonthHack = other.chineseMonthHack;
// NUL-terminate for the C API.
dateTimeFormat.getTerminatedBuffer();
decimal.getTerminatedBuffer();
@ -230,7 +234,8 @@ DateTimePatternGenerator::operator==(const DateTimePatternGenerator& other) cons
return TRUE;
}
if ((pLocale==other.pLocale) && (patternMap->equals(*other.patternMap)) &&
(dateTimeFormat==other.dateTimeFormat) && (decimal==other.decimal)) {
(dateTimeFormat==other.dateTimeFormat) && (decimal==other.decimal) &&
(chineseMonthHack == other.chineseMonthHack)) {
for ( int32_t i=0 ; i<UDATPG_FIELD_COUNT; ++i ) {
if ((appendItemFormats[i] != other.appendItemFormats[i]) ||
(appendItemNames[i] != other.appendItemNames[i]) ) {
@ -264,10 +269,17 @@ DateTimePatternGenerator::~DateTimePatternGenerator() {
void
DateTimePatternGenerator::initData(const Locale& locale) {
const char *baseLangName = locale.getBaseName();
chineseMonthHack = FALSE;
for (int32_t i=0; i<3; i++) {
if ( uprv_memcmp(baseLangName, CJKLangName[i], 2 ) == 0 ) {
chineseMonthHack = TRUE;
}
}
fStatus = U_ZERO_ERROR;
skipMatcher = NULL;
fAvailableFormatKeyHash=NULL;
addCanonicalItems();
addICUPatterns(locale, fStatus);
if (U_FAILURE(fStatus)) {
@ -564,7 +576,12 @@ DateTimePatternGenerator::getBestPattern(const UnicodeString& patternForm, UErro
int32_t timeMask=(1<<UDATPG_FIELD_COUNT) - 1 - dateMask;
resultPattern.remove();
dtMatcher->set(patternForm, fp);
if ( chineseMonthHack ) {
dtMatcher->set(getCJKPattern(patternForm), fp);
}
else {
dtMatcher->set(patternForm, fp);
}
bestPattern=getBestRaw(*dtMatcher, -1, distanceInfo);
if ( distanceInfo->missingFieldMask==0 && distanceInfo->extraFieldMask==0 ) {
resultPattern = adjustFieldTypes(*bestPattern, FALSE);
@ -981,6 +998,31 @@ DateTimePatternGenerator::clone() const {
return new DateTimePatternGenerator(*this);
}
// If the pattern contains more than 3 'M', replace with "MM"
UnicodeString
DateTimePatternGenerator::getCJKPattern(const UnicodeString& origPattern) {
UnicodeString result = UnicodeString(origPattern);
int32_t start, count;
start=0;
if ((start < result.length()) &&
((start = result.indexOf(CAP_M, start)) >=0 )) {
count=1;
while ( result.charAt(start+count) == CAP_M ) {
if ( start+count++ >= result.length() ) {
break;
}
}
if ( count >=3 ) {
UChar sMM[3] = { CAP_M, CAP_M, 0 };
UnicodeString shortMM = UnicodeString(sMM);
result = result.replace(start, count, shortMM);
}
start+=count;
}
return result;
}
PatternMap::PatternMap() {
for (int32_t i=0; i < MAX_PATTERN_ENTRIES; ++i ) {
boot[i]=NULL;

View File

@ -387,6 +387,7 @@ private:
UnicodeString hackPattern;
UErrorCode fStatus;
UnicodeString emptyString;
UBool chineseMonthHack;
void initData(const Locale &locale);
void addCanonicalItems();
@ -396,6 +397,7 @@ private:
void initHashtable(UErrorCode& status);
void setDateTimeFromCalendar(const Locale& locale, UErrorCode& status);
void setDecimalSymbols(const Locale& locale, UErrorCode& status);
UnicodeString getCJKPattern(const UnicodeString& patternForm);
UDateTimePatternField getAppendFormatNumber(const char* field) const;
UDateTimePatternField getAppendNameNumber(const char* field) const;
void getAppendName(UDateTimePatternField field, UnicodeString& value);

View File

@ -1,6 +1,6 @@
/********************************************************************
* COPYRIGHT:
* Copyright (c) 2007, International Business Machines Corporation and
* Copyright (c) 2008, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
@ -72,11 +72,11 @@ void IntlTestDateTimePatternGeneratorAPI::testAPI(/*char *par*/)
UnicodeString("23:58"),
UnicodeString("58:59"),
UnicodeString("1999-1"), // zh_Hans_CN
UnicodeString("1999 1"),
CharsToUnicodeString("1999\\u5E741\\u670813\\u65E5"),
UnicodeString("1999-01"),
CharsToUnicodeString("1999\\u5E741\\u670813\\u65E5"),
CharsToUnicodeString("1999\\u5E7401\\u670813\\u65E5"),
UnicodeString("1-13"),
UnicodeString("1 13"),
UnicodeString("01-13"),
CharsToUnicodeString("1999 Q1"),
CharsToUnicodeString("\\u4E0B\\u534811:58"),
CharsToUnicodeString("23:58"),
@ -340,6 +340,57 @@ void IntlTestDateTimePatternGeneratorAPI::testAPI(/*char *par*/)
delete zone;
delete gen;
{
// Trac# 6104
status = U_ZERO_ERROR;
pattern = UnicodeString("YYYYMMM");
UnicodeString expR = UnicodeString("1999-01");
Locale loc("ja");
UDate testDate1= LocaleTest::date(99, 0, 13, 23, 58, 59);
DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(loc, status);
if(U_FAILURE(status)) {
dataerrln("ERROR: Could not create DateTimePatternGenerator");
return;
}
UnicodeString bPattern = patGen->getBestPattern(pattern, status);
UnicodeString rDate;
SimpleDateFormat sdf(bPattern, loc, status);
rDate.remove();
rDate = sdf.format(testDate1, rDate);
logln(UnicodeString(" ja locale with skeleton: YYYYMMM Best Pattern:") + bPattern);
logln(UnicodeString(" Formatted date:") + rDate);
if ( expR!= rDate ) {
errln(UnicodeString("\nERROR: Test Japanese month hack Got: ") + rDate +
UnicodeString(" Expected: ") + expR );
}
delete patGen;
}
{ // Trac# 6104
Locale loc("zh");
UnicodeString expR = UnicodeString("1999-01");
UDate testDate1= LocaleTest::date(99, 0, 13, 23, 58, 59);
DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(loc, status);
if(U_FAILURE(status)) {
dataerrln("ERROR: Could not create DateTimePatternGenerator");
return;
}
UnicodeString bPattern = patGen->getBestPattern(pattern, status);
UnicodeString rDate;
SimpleDateFormat sdf(bPattern, loc, status);
rDate.remove();
rDate = sdf.format(testDate1, rDate);
logln(UnicodeString(" zh locale with skeleton: YYYYMMM Best Pattern:") + bPattern);
logln(UnicodeString(" Formatted date:") + rDate);
if ( expR!= rDate ) {
errln(UnicodeString("\nERROR: Test Chinese month hack Got: ") + rDate +
UnicodeString(" Expected: ") + expR );
}
delete patGen;
}
// ======= Test various skeletons.
logln("Testing DateTimePatternGenerator with various skeleton");