ICU-6072 Add DateFormatSymbols support for NarrowEras, use it to format & parse with GGGGG

X-SVN-Rev: 24709
This commit is contained in:
Peter Edberg 2008-10-03 07:47:57 +00:00
parent 3f1ae1d226
commit 1e9adc5dc1
6 changed files with 151 additions and 14 deletions

View file

@ -177,7 +177,6 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateFormatSymbols)
* with a locale and calendar
*/
static const char gErasTag[]="eras";
static const char gAbbreviatedTag[] = "abbreviated";
static const char gMonthNamesTag[]="monthNames";
static const char gDayNamesTag[]="dayNames";
static const char gNamesWideTag[]="wide";
@ -310,6 +309,7 @@ void
DateFormatSymbols::copyData(const DateFormatSymbols& other) {
assignArray(fEras, fErasCount, other.fEras, other.fErasCount);
assignArray(fEraNames, fEraNamesCount, other.fEraNames, other.fEraNamesCount);
assignArray(fNarrowEras, fNarrowErasCount, other.fNarrowEras, other.fNarrowErasCount);
assignArray(fMonths, fMonthsCount, other.fMonths, other.fMonthsCount);
assignArray(fShortMonths, fShortMonthsCount, other.fShortMonths, other.fShortMonthsCount);
assignArray(fNarrowMonths, fNarrowMonthsCount, other.fNarrowMonths, other.fNarrowMonthsCount);
@ -371,6 +371,7 @@ void DateFormatSymbols::dispose()
{
if (fEras) delete[] fEras;
if (fEraNames) delete[] fEraNames;
if (fNarrowEras) delete[] fNarrowEras;
if (fMonths) delete[] fMonths;
if (fShortMonths) delete[] fShortMonths;
if (fNarrowMonths) delete[] fNarrowMonths;
@ -447,6 +448,7 @@ DateFormatSymbols::operator==(const DateFormatSymbols& other) const
}
if (fErasCount == other.fErasCount &&
fEraNamesCount == other.fEraNamesCount &&
fNarrowErasCount == other.fNarrowErasCount &&
fMonthsCount == other.fMonthsCount &&
fShortMonthsCount == other.fShortMonthsCount &&
fNarrowMonthsCount == other.fNarrowMonthsCount &&
@ -470,6 +472,7 @@ DateFormatSymbols::operator==(const DateFormatSymbols& other) const
// Now compare the arrays themselves
if (arrayCompare(fEras, other.fEras, fErasCount) &&
arrayCompare(fEraNames, other.fEraNames, fEraNamesCount) &&
arrayCompare(fNarrowEras, other.fNarrowEras, fNarrowErasCount) &&
arrayCompare(fMonths, other.fMonths, fMonthsCount) &&
arrayCompare(fShortMonths, other.fShortMonths, fShortMonthsCount) &&
arrayCompare(fNarrowMonths, other.fNarrowMonths, fNarrowMonthsCount) &&
@ -526,6 +529,13 @@ DateFormatSymbols::getEraNames(int32_t &count) const
return fEraNames;
}
const UnicodeString*
DateFormatSymbols::getNarrowEras(int32_t &count) const
{
count = fNarrowErasCount;
return fNarrowEras;
}
const UnicodeString*
DateFormatSymbols::getMonths(int32_t &count) const
{
@ -734,6 +744,20 @@ DateFormatSymbols::setEraNames(const UnicodeString* eraNamesArray, int32_t count
fEraNamesCount = count;
}
void
DateFormatSymbols::setNarrowEras(const UnicodeString* narrowErasArray, int32_t count)
{
// delete the old list if we own it
if (fNarrowEras)
delete[] fNarrowEras;
// we always own the new list, which we create here (we duplicate rather
// than adopting the list passed in)
fNarrowEras = newUnicodeStringArray(count);
uprv_arrayCopy(narrowErasArray,fNarrowEras, count);
fNarrowErasCount = count;
}
void
DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count)
{
@ -1167,6 +1191,8 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError
fErasCount = 0;
fEraNames = NULL;
fEraNamesCount = 0;
fNarrowEras = NULL;
fNarrowErasCount = 0;
fMonths = NULL;
fMonthsCount=0;
fShortMonths = NULL;
@ -1235,12 +1261,19 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError
// load the first data item
UResourceBundle *erasMain = calData.getByKey(gErasTag, status);
UResourceBundle *eras = ures_getByKeyWithFallback(erasMain, gAbbreviatedTag, NULL, &status);
UResourceBundle *eras = ures_getByKeyWithFallback(erasMain, gNamesAbbrTag, NULL, &status);
UErrorCode oldStatus = status;
UResourceBundle *eraNames = ures_getByKeyWithFallback(erasMain, gNamesWideTag, NULL, &status);
if ( status == U_MISSING_RESOURCE_ERROR ) { // Workaround because eras/wide was omitted from CLDR 1.3
status = oldStatus;
eraNames = ures_getByKeyWithFallback(erasMain, gAbbreviatedTag, NULL, &status);
eraNames = ures_getByKeyWithFallback(erasMain, gNamesAbbrTag, NULL, &status);
}
// current ICU4J falls back to abbreviated if narrow eras are missing, so we will too
oldStatus = status;
UResourceBundle *narrowEras = ures_getByKeyWithFallback(erasMain, gNamesNarrowTag, NULL, &status);
if ( status == U_MISSING_RESOURCE_ERROR ) {
status = oldStatus;
narrowEras = ures_getByKeyWithFallback(erasMain, gNamesAbbrTag, NULL, &status);
}
UResourceBundle *lsweekdaysData = NULL; // Data closed by calData
@ -1264,6 +1297,7 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError
initField(&fEras, fErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
initField(&fEraNames, fEraNamesCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
initField(&fNarrowEras, fNarrowErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
initField(&fMonths, fMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
initField(&fShortMonths, fShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
initField(&fNarrowMonths, fNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
@ -1296,6 +1330,7 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError
initField(&fEras, fErasCount, eras, status);
initField(&fEraNames, fEraNamesCount, eraNames, status);
initField(&fNarrowEras, fNarrowErasCount, narrowEras, status);
initField(&fMonths, fMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesWideTag, status), status);
initField(&fShortMonths, fShortMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status);
@ -1521,6 +1556,7 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError
cleanup:
ures_close(eras);
ures_close(eraNames);
ures_close(narrowEras);
ures_close(zoneStringsArray);
ures_close(localeBundle);
}

View file

@ -1046,9 +1046,11 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
switch (patternCharIndex) {
// for any "G" symbol, write out the appropriate era string
// "GGGG" is wide era name, anything else is abbreviated name
// "GGGG" is wide era name, "GGGGG" is narrow era name, anything else is abbreviated name
case UDAT_ERA_FIELD:
if (count >= 4)
if (count == 5)
_appendSymbol(appendTo, value, fSymbols->fNarrowEras, fSymbols->fNarrowErasCount);
else if (count == 4)
_appendSymbol(appendTo, value, fSymbols->fEraNames, fSymbols->fEraNamesCount);
else
_appendSymbol(appendTo, value, fSymbols->fEras, fSymbols->fErasCount);
@ -1925,6 +1927,9 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
switch (patternCharIndex) {
case UDAT_ERA_FIELD:
if (count == 5) {
return matchString(text, start, UCAL_ERA, fSymbols->fNarrowEras, fSymbols->fNarrowErasCount, cal);
}
if (count == 4) {
return matchString(text, start, UCAL_ERA, fSymbols->fEraNames, fSymbols->fEraNamesCount, cal);
}

View file

@ -1,6 +1,6 @@
/*
********************************************************************************
* Copyright (C) 1997-2007, International Business Machines
* Copyright (C) 1997-2008, International Business Machines
* Corporation and others. All Rights Reserved.
********************************************************************************
*
@ -180,7 +180,7 @@ public:
UBool operator!=(const DateFormatSymbols& other) const { return !operator==(other); }
/**
* Gets era strings. For example: "AD" and "BC".
* Gets abbreviated era strings. For example: "AD" and "BC".
*
* @param count Filled in with length of the array.
* @return the era strings.
@ -189,7 +189,7 @@ public:
const UnicodeString* getEras(int32_t& count) const;
/**
* Sets era strings. For example: "AD" and "BC".
* Sets abbreviated era strings. For example: "AD" and "BC".
* @param eras Array of era strings (DateFormatSymbols retains ownership.)
* @param count Filled in with length of the array.
* @stable ICU 2.0
@ -213,6 +213,23 @@ public:
*/
void setEraNames(const UnicodeString* eraNames, int32_t count);
/**
* Gets narrow era strings. For example: A" and "D".
*
* @param count Filled in with length of the array.
* @return the narrow era strings.
* @draft ICU 4.2
*/
const UnicodeString* getNarrowEras(int32_t& count) const;
/**
* Sets narrow era strings. For example: "A" and "B".
* @param narrowEras Array of narrow era strings (DateFormatSymbols retains ownership.)
* @param count Filled in with length of the array.
* @draft ICU 4.2
*/
void setNarrowEras(const UnicodeString* narrowEras, int32_t count);
/**
* Gets month strings. For example: "January", "February", etc.
* @param count Filled in with length of the array.
@ -453,7 +470,7 @@ private:
friend class DateFormatSymbolsSingleSetter; // see udat.cpp
/**
* Era strings. For example: "AD" and "BC".
* Abbreviated era strings. For example: "AD" and "BC".
*/
UnicodeString* fEras;
int32_t fErasCount;
@ -464,6 +481,12 @@ private:
UnicodeString* fEraNames;
int32_t fEraNamesCount;
/**
* Narrow era strings. For example: "A" and "B".
*/
UnicodeString* fNarrowEras;
int32_t fNarrowErasCount;
/**
* Month strings. For example: "January", "February", etc.
*/

View file

@ -39,7 +39,8 @@ void addDateForRgrTest(TestNode** root)
addTest(root, &Test4061287, "tsformat/cdtrgtst/Test4061287");
addTest(root, &Test4073003, "tsformat/cdtrgtst/Test4073003");
addTest(root, &Test4162071, "tsformat/cdtrgtst/Test4162071");
addTest(root, &Test714, "tsformat/cdtrgtst/Test714");
addTest(root, &Test714, "tsformat/cdtrgtst/Test714");
addTest(root, &TestJ6072, "tsformat/cdtrgtst/TestJ6072");
}
/**
@ -499,6 +500,61 @@ void Test714(void)
ctest_resetTimeZone();
}
static const UDate july022008 = 1.215e+12; /* 02 July 2008 5:00 AM PDT (approx ICU 4.0 release date :-) */
static const UChar zonePST[] = { 'P','S','T',0 };
static const UChar dmyGGGPattern[] = { 'd','d',' ','M','M','M',' ','y','y','y','y',' ','G','G','G',0 };
static const UChar dmyGGGGGPattern[] = { 'd','d',' ','M','M','M',' ','y','y','y','y',' ','G','G','G','G','G',0 };
static const UChar dmyGGGText[] = { '0','2',' ','J','u','l',' ','2','0','0','8',' ','A','D',0 };
static const UChar dmyGGGGGText[] = { '0','2',' ','J','u','l',' ','2','0','0','8',' ','A',0 };
static const double dayMillisec = 8.64e+07;
enum { kdmyGnTextMaxChars = 64 };
void TestJ6072(void)
{
UErrorCode status = U_ZERO_ERROR;
UDateFormat * dtfmt = udat_open(UDAT_LONG, UDAT_LONG, "en", zonePST, -1, NULL, 0, &status);
if ( U_SUCCESS(status) ) {
UChar dmyGnText[kdmyGnTextMaxChars];
int32_t dmyGnTextLen;
UDate dateResult;
udat_applyPattern(dtfmt, FALSE, dmyGGGPattern, -1);
dmyGnTextLen = udat_format(dtfmt, july022008, dmyGnText, kdmyGnTextMaxChars, NULL, &status);
if ( U_FAILURE(status) ) {
log_err("FAIL: udat_format with GGG: %s\n", myErrorName(status) );
status = U_ZERO_ERROR;
} else if ( u_strcmp(dmyGnText, dmyGGGText) != 0 ) {
log_err("FAIL: udat_format with GGG: wrong UChar[] result\n" );
}
dateResult = udat_parse(dtfmt, dmyGGGText, -1, NULL, &status); /* no time, dateResult != july022008 by some hours */
if ( U_FAILURE(status) ) {
log_err("FAIL: udat_parse with GGG: %s\n", myErrorName(status) );
status = U_ZERO_ERROR;
} else if ( july022008 - dateResult > dayMillisec ) {
log_err("FAIL: udat_parse with GGG: wrong UDate result\n" );
}
udat_applyPattern(dtfmt, FALSE, dmyGGGGGPattern, -1);
dmyGnTextLen = udat_format(dtfmt, july022008, dmyGnText, kdmyGnTextMaxChars, NULL, &status);
if ( U_FAILURE(status) ) {
log_err("FAIL: udat_format with GGGGG: %s\n", myErrorName(status) );
status = U_ZERO_ERROR;
} else if ( u_strcmp(dmyGnText, dmyGGGGGText) != 0 ) {
log_err("FAIL: udat_format with GGGGG: wrong UChar[] result\n" );
}
dateResult = udat_parse(dtfmt, dmyGGGGGText, -1, NULL, &status); /* no time, dateResult != july022008 by some hours */
if ( U_FAILURE(status) ) {
log_err("FAIL: udat_parse with GGGGG: %s\n", myErrorName(status) );
status = U_ZERO_ERROR;
} else if ( july022008 - dateResult > dayMillisec ) {
log_err("FAIL: udat_parse with GGGGG: wrong UDate result\n" );
}
udat_close(dtfmt);
} else {
log_err("FAIL: udat_open fails: %s\n", myErrorName(status));
}
}
/*INTERNAL FUNCTION USED */
UChar* myFormatit(UDateFormat* datdef, UDate d1)

View file

@ -1,6 +1,6 @@
/********************************************************************
* COPYRIGHT:
* Copyright (c) 1997-2001, International Business Machines Corporation and
* Copyright (c) 1997-2002,2008, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
/********************************************************************************
@ -23,7 +23,7 @@
#include "cintltst.h"
/**
* DateFormat Regresstion tests
* DateFormat Regression tests
**/
void Test4029195(void);
@ -34,6 +34,7 @@
void Test4073003(void);
void Test4162071(void);
void Test714(void);
void TestJ6072(void);
/**
* test subroutine

View file

@ -1,5 +1,5 @@
/********************************************************************
* Copyright (c) 1997-2007, International Business Machines
* Copyright (c) 1997-2008, International Business Machines
* Corporation and others. All Rights Reserved.
********************************************************************/
@ -159,9 +159,25 @@ void IntlTestDateFormatSymbols::TestSymbols(/* char *par */)
int32_t count = 0;
const UnicodeString *eras = en.getEras(count);
if(count == 0) {
errln("ERROR: 0 english eras.. exitting..\n");
errln("ERROR: 0 english eras.. exiting..\n");
return;
}
int32_t eraNamesCount = 0;
const UnicodeString *eraNames = en.getEraNames(eraNamesCount);
if(eraNamesCount == 0) {
errln("ERROR: 0 english eraNames\n");
} else if ( eraNames[0].length() <= eras[0].length() ) {
// At least for English we know a wide eraName should be longer than an abbrev era
errln("ERROR: english eraNames[0] not longer than eras[0]\n");
}
int32_t narrowErasCount = 0;
const UnicodeString *narrowEras = en.getNarrowEras(narrowErasCount);
if(narrowErasCount == 0) {
errln("ERROR: 0 english narrowEras\n");
} else if ( narrowEras[0].length() >= eras[0].length() ) {
// At least for English we know a narrowEra should be shorter than an abbrev era
errln("ERROR: english narrowEras[0] not shorter than eras[0]\n");
}
fr.setEras(eras, count);
if( *en.getEras(count) != *fr.getEras(count)) {