diff --git a/icu4c/source/i18n/dtfmtsym.cpp b/icu4c/source/i18n/dtfmtsym.cpp index 083c87fc8e9..6dc1d4bcfa6 100644 --- a/icu4c/source/i18n/dtfmtsym.cpp +++ b/icu4c/source/i18n/dtfmtsym.cpp @@ -157,6 +157,7 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateFormatSymbols) static const char gErasTag[]="eras"; static const char gCyclicNameSetsTag[]="cyclicNameSets"; static const char gNameSetYearsTag[]="years"; +static const char gNameSetZodiacsTag[]="zodiacs"; static const char gMonthNamesTag[]="monthNames"; static const char gMonthPatternsTag[]="monthPatterns"; static const char gDayNamesTag[]="dayNames"; @@ -327,6 +328,12 @@ DateFormatSymbols::copyData(const DateFormatSymbols& other) { fShortYearNames = NULL; fShortYearNamesCount = 0; } + if (other.fShortZodiacNames != NULL) { + assignArray(fShortZodiacNames, fShortZodiacNamesCount, other.fShortZodiacNames, other.fShortZodiacNamesCount); + } else { + fShortZodiacNames = NULL; + fShortZodiacNamesCount = 0; + } if (other.fZoneStrings != NULL) { fZoneStringsColCount = other.fZoneStringsColCount; @@ -390,6 +397,7 @@ void DateFormatSymbols::dispose() if (fStandaloneShortQuarters) delete[] fStandaloneShortQuarters; if (fLeapMonthPatterns) delete[] fLeapMonthPatterns; if (fShortYearNames) delete[] fShortYearNames; + if (fShortZodiacNames) delete[] fShortZodiacNames; disposeZoneStrings(); } @@ -460,6 +468,7 @@ DateFormatSymbols::operator==(const DateFormatSymbols& other) const fStandaloneShortQuartersCount == other.fStandaloneShortQuartersCount && fLeapMonthPatternsCount == other.fLeapMonthPatternsCount && fShortYearNamesCount == other.fShortYearNamesCount && + fShortZodiacNamesCount == other.fShortZodiacNamesCount && (uprv_memcmp(fCapitalization, other.fCapitalization, sizeof(fCapitalization))==0)) { // Now compare the arrays themselves @@ -486,7 +495,8 @@ DateFormatSymbols::operator==(const DateFormatSymbols& other) const arrayCompare(fStandaloneQuarters, other.fStandaloneQuarters, fStandaloneQuartersCount) && arrayCompare(fStandaloneShortQuarters, other.fStandaloneShortQuarters, fStandaloneShortQuartersCount) && arrayCompare(fLeapMonthPatterns, other.fLeapMonthPatterns, fLeapMonthPatternsCount) && - arrayCompare(fShortYearNames, other.fShortYearNames, fShortYearNamesCount)) + arrayCompare(fShortYearNames, other.fShortYearNames, fShortYearNamesCount) && + arrayCompare(fShortZodiacNames, other.fShortZodiacNames, fShortZodiacNamesCount)) { // Compare the contents of fZoneStrings if (fZoneStrings == NULL && other.fZoneStrings == NULL) { @@ -729,6 +739,50 @@ DateFormatSymbols::getLeapMonthPatterns(int32_t &count) const return fLeapMonthPatterns; } +const UnicodeString* +DateFormatSymbols::getYearNames(int32_t& count, + DtContextType /*ignored*/, DtWidthType /*ignored*/) const +{ + count = fShortYearNamesCount; + return fShortYearNames; +} + +void +DateFormatSymbols::setYearNames(const UnicodeString* yearNames, int32_t count, + DtContextType context, DtWidthType width) +{ + if (context == FORMAT && width == ABBREVIATED) { + if (fShortYearNames) { + delete[] fShortYearNames; + } + fShortYearNames = newUnicodeStringArray(count); + uprv_arrayCopy(yearNames, fShortYearNames, count); + fShortYearNamesCount = count; + } +} + +const UnicodeString* +DateFormatSymbols::getZodiacNames(int32_t& count, + DtContextType /*ignored*/, DtWidthType /*ignored*/) const +{ + count = fShortZodiacNamesCount; + return fShortZodiacNames; +} + +void +DateFormatSymbols::setZodiacNames(const UnicodeString* zodiacNames, int32_t count, + DtContextType context, DtWidthType width) +{ + if (context == FORMAT && width == ABBREVIATED) { + if (fShortZodiacNames) { + delete[] fShortZodiacNames; + } + fShortZodiacNames = newUnicodeStringArray(count); + uprv_arrayCopy(zodiacNames, fShortZodiacNames, count); + fShortZodiacNamesCount = count; + } +} + //------------------------------------------------------ void @@ -1388,6 +1442,8 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError fLeapMonthPatternsCount = 0; fShortYearNames = NULL; fShortYearNamesCount = 0; + fShortZodiacNames = NULL; + fShortZodiacNamesCount = 0; fZoneStringsRowCount = 0; fZoneStringsColCount = 0; fZoneStrings = NULL; @@ -1478,6 +1534,19 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError } ures_close(nameSetYears); } + UResourceBundle *nameSetZodiacs = ures_getByKeyWithFallback(cyclicNameSets, gNameSetZodiacsTag, NULL, &tempStatus); + if (U_SUCCESS(tempStatus)) { + UResourceBundle *nameSetZodiacsFmt = ures_getByKeyWithFallback(nameSetZodiacs, gNamesFormatTag, NULL, &tempStatus); + if (U_SUCCESS(tempStatus)) { + UResourceBundle *nameSetZodiacsFmtAbbrev = ures_getByKeyWithFallback(nameSetZodiacsFmt, gNamesAbbrTag, NULL, &tempStatus); + if (U_SUCCESS(tempStatus)) { + initField(&fShortZodiacNames, fShortZodiacNamesCount, nameSetZodiacsFmtAbbrev, tempStatus); + ures_close(nameSetZodiacsFmtAbbrev); + } + ures_close(nameSetZodiacsFmt); + } + ures_close(nameSetZodiacs); + } } tempStatus = U_ZERO_ERROR; diff --git a/icu4c/source/i18n/udat.cpp b/icu4c/source/i18n/udat.cpp index 67764819601..116eb9b0bea 100644 --- a/icu4c/source/i18n/udat.cpp +++ b/icu4c/source/i18n/udat.cpp @@ -592,6 +592,30 @@ udat_getSymbols(const UDateFormat *fmt, res = syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED); break; + case UDAT_CYCLIC_YEARS_WIDE: + res = syms->getYearNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE); + break; + + case UDAT_CYCLIC_YEARS_ABBREVIATED: + res = syms->getYearNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED); + break; + + case UDAT_CYCLIC_YEARS_NARROW: + res = syms->getYearNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW); + break; + + case UDAT_ZODIAC_NAMES_WIDE: + res = syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE); + break; + + case UDAT_ZODIAC_NAMES_ABBREVIATED: + res = syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED); + break; + + case UDAT_ZODIAC_NAMES_NARROW: + res = syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW); + break; + } if(index < count) { @@ -706,6 +730,30 @@ udat_countSymbols( const UDateFormat *fmt, syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED); break; + case UDAT_CYCLIC_YEARS_WIDE: + syms->getYearNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE); + break; + + case UDAT_CYCLIC_YEARS_ABBREVIATED: + syms->getYearNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED); + break; + + case UDAT_CYCLIC_YEARS_NARROW: + syms->getYearNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW); + break; + + case UDAT_ZODIAC_NAMES_WIDE: + syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE); + break; + + case UDAT_ZODIAC_NAMES_ABBREVIATED: + syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED); + break; + + case UDAT_ZODIAC_NAMES_NARROW: + syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW); + break; + } return count; @@ -894,6 +942,20 @@ public: setSymbol(syms->fStandaloneShortQuarters, syms->fStandaloneShortQuartersCount, index, value, valueLength, errorCode); } + static void + setShortYearNames(DateFormatSymbols *syms, int32_t index, + const UChar *value, int32_t valueLength, UErrorCode &errorCode) + { + setSymbol(syms->fShortYearNames, syms->fShortYearNamesCount, index, value, valueLength, errorCode); + } + + static void + setShortZodiacNames(DateFormatSymbols *syms, int32_t index, + const UChar *value, int32_t valueLength, UErrorCode &errorCode) + { + setSymbol(syms->fShortZodiacNames, syms->fShortZodiacNamesCount, index, value, valueLength, errorCode); + } + static void setAmPm(DateFormatSymbols *syms, int32_t index, const UChar *value, int32_t valueLength, UErrorCode &errorCode) @@ -1005,6 +1067,14 @@ udat_setSymbols( UDateFormat *format, DateFormatSymbolsSingleSetter::setStandaloneShortQuarter(syms, index, value, valueLength, *status); break; + case UDAT_CYCLIC_YEARS_ABBREVIATED: + DateFormatSymbolsSingleSetter::setShortYearNames(syms, index, value, valueLength, *status); + break; + + case UDAT_ZODIAC_NAMES_ABBREVIATED: + DateFormatSymbolsSingleSetter::setShortZodiacNames(syms, index, value, valueLength, *status); + break; + case UDAT_AM_PMS: DateFormatSymbolsSingleSetter::setAmPm(syms, index, value, valueLength, *status); break; diff --git a/icu4c/source/i18n/unicode/dtfmtsym.h b/icu4c/source/i18n/unicode/dtfmtsym.h index 852b71daef2..8010914685f 100644 --- a/icu4c/source/i18n/unicode/dtfmtsym.h +++ b/icu4c/source/i18n/unicode/dtfmtsym.h @@ -408,6 +408,59 @@ public: */ void setAmPmStrings(const UnicodeString* ampms, int32_t count); +#ifndef U_HIDE_DRAFT_API + /** + * Gets cyclic year name strings if the calendar has them, by width and context. + * For example: "jia-zi", "yi-chou", etc. + * @param count Filled in with length of the array. + * @param context The usage context: FORMAT, STANDALONE. + * @param width The requested name width: WIDE, ABBREVIATED, NARROW. + * @return The year name strings (DateFormatSymbols retains ownership), + * or null if they are not available for this calendar. + * @draft ICU 54 + */ + const UnicodeString* getYearNames(int32_t& count, + DtContextType context, DtWidthType width) const; + + /** + * Sets cyclic year name strings by width and context. For example: "jia-zi", "yi-chou", etc. + * + * @param yearNames The new cyclic year name strings (not adopted; caller retains ownership). + * @param count The length of the array. + * @param context The usage context: FORMAT, STANDALONE (currently only FORMAT is supported). + * @param width The name width: WIDE, ABBREVIATED, NARROW (currently only ABBREVIATED is supported). + * @draft ICU 54 + */ + void setYearNames(const UnicodeString* yearNames, int32_t count, + DtContextType context, DtWidthType width); + + /** + * Gets calendar zodiac name strings if the calendar has them, by width and context. + * For example: "Rat", "Ox", "Tiger", etc. + * @param count Filled in with length of the array. + * @param context The usage context: FORMAT, STANDALONE. + * @param width The requested name width: WIDE, ABBREVIATED, NARROW. + * @return The zodiac name strings (DateFormatSymbols retains ownership), + * or null if they are not available for this calendar. + * @draft ICU 54 + */ + const UnicodeString* getZodiacNames(int32_t& count, + DtContextType context, DtWidthType width) const; + + /** + * Sets calendar zodiac name strings by width and context. For example: "Rat", "Ox", "Tiger", etc. + * + * @param zodiacNames The new zodiac name strings (not adopted; caller retains ownership). + * @param count The length of the array. + * @param context The usage context: FORMAT, STANDALONE (currently only FORMAT is supported). + * @param width The name width: WIDE, ABBREVIATED, NARROW (currently only ABBREVIATED is supported). + * @draft ICU 54 + */ + void setZodiacNames(const UnicodeString* zodiacNames, int32_t count, + DtContextType context, DtWidthType width); + +#endif /* U_HIDE_DRAFT_API */ + #ifndef U_HIDE_INTERNAL_API /** * Somewhat temporary constants for leap month pattern types, adequate for supporting @@ -688,11 +741,21 @@ private: int32_t fLeapMonthPatternsCount; /** - * (Format) Short cyclic year names, for example: "jia-zi", "yi-chou", ... "gui-hai" + * Cyclic year names, for example: "jia-zi", "yi-chou", ... "gui-hai"; + * currently we only have data for format/abbreviated. + * For the others, just get from format/abbreviated, ignore set. */ - UnicodeString* fShortYearNames; + UnicodeString *fShortYearNames; int32_t fShortYearNamesCount; + /** + * Cyclic zodiac names, for example "Rat", "Ox", "Tiger", etc.; + * currently we only have data for format/abbreviated. + * For the others, just get from format/abbreviated, ignore set. + */ + UnicodeString *fShortZodiacNames; + int32_t fShortZodiacNamesCount; + /** * Localized names of time zones in this locale. This is a * two-dimensional array of strings of size n by m, diff --git a/icu4c/source/i18n/unicode/udat.h b/icu4c/source/i18n/unicode/udat.h index e0f098807f2..87af1d2121b 100644 --- a/icu4c/source/i18n/unicode/udat.h +++ b/icu4c/source/i18n/unicode/udat.h @@ -850,7 +850,7 @@ typedef enum UDateFormatBooleanAttribute { UDAT_PARSE_ALLOW_WHITESPACE = 0, /** * indicates tolerance of numeric data when String data may be assumed. eg: UDAT_YEAR_NAME_FIELD, - * UDAT_STANDALONE_MONTH_FIELD, UDAT_DAY_OF_WEEK_FIELD + * UDAT_STANDALONE_MONTH_FIELD, UDAT_DAY_OF_WEEK_FIELD * @draft ICU 53 */ UDAT_PARSE_ALLOW_NUMERIC = 1, @@ -1294,6 +1294,43 @@ typedef enum UDateFormatSymbolType { * @stable ICU 51 */ UDAT_STANDALONE_SHORTER_WEEKDAYS +#ifndef U_HIDE_DRAFT_API + , + /** + * Cyclic year names (only supported for some calendars, and only for FORMAT usage; + * udat_setSymbols not supported for UDAT_CYCLIC_YEARS_WIDE) + * @draft ICU 54 + */ + UDAT_CYCLIC_YEARS_WIDE, + /** + * Cyclic year names (only supported for some calendars, and only for FORMAT usage) + * @draft ICU 54 + */ + UDAT_CYCLIC_YEARS_ABBREVIATED, + /** + * Cyclic year names (only supported for some calendars, and only for FORMAT usage; + * udat_setSymbols not supported for UDAT_CYCLIC_YEARS_NARROW) + * @draft ICU 54 + */ + UDAT_CYCLIC_YEARS_NARROW, + /** + * Calendar zodiac names (only supported for some calendars, and only for FORMAT usage; + * udat_setSymbols not supported for UDAT_ZODIAC_NAMES_WIDE) + * @draft ICU 54 + */ + UDAT_ZODIAC_NAMES_WIDE, + /** + * Calendar zodiac names (only supported for some calendars, and only for FORMAT usage) + * @draft ICU 54 + */ + UDAT_ZODIAC_NAMES_ABBREVIATED, + /** + * Calendar zodiac names (only supported for some calendars, and only for FORMAT usage; + * udat_setSymbols not supported for UDAT_ZODIAC_NAMES_NARROW) + * @draft ICU 54 + */ + UDAT_ZODIAC_NAMES_NARROW +#endif /* U_HIDE_DRAFT_API */ } UDateFormatSymbolType; struct UDateFormatSymbols; diff --git a/icu4c/source/test/cintltst/cdattst.c b/icu4c/source/test/cintltst/cdattst.c index b95db74cfa7..1cac8dd98af 100644 --- a/icu4c/source/test/cintltst/cdattst.c +++ b/icu4c/source/test/cintltst/cdattst.c @@ -565,7 +565,7 @@ static void TestRelativeDateFormat() /*Testing udat_getSymbols() and udat_setSymbols() and udat_countSymbols()*/ static void TestSymbols() { - UDateFormat *def, *fr; + UDateFormat *def, *fr, *zhChiCal; UErrorCode status = U_ZERO_ERROR; UChar *value=NULL; UChar *result = NULL; @@ -595,6 +595,15 @@ static void TestSymbols() myErrorName(status) ); return; } + /*creating a dateformat with zh locale */ + log_verbose("\ncreating a date format with zh locale for chinese calendar\n"); + zhChiCal = udat_open(UDAT_NONE, UDAT_FULL, "zh@calendar=chinese", NULL, 0, NULL, 0, &status); + if(U_FAILURE(status)) + { + log_data_err("error in creating the dateformat using full date, no time, locale zh@calendar=chinese -> %s (Are you missing data?)\n", + myErrorName(status) ); + return; + } /*Testing countSymbols, getSymbols and setSymbols*/ @@ -604,7 +613,8 @@ static void TestSymbols() udat_countSymbols(def, UDAT_SHORT_MONTHS)!=12 || udat_countSymbols(def, UDAT_WEEKDAYS)!=8 || udat_countSymbols(def, UDAT_SHORT_WEEKDAYS)!=8 || udat_countSymbols(def, UDAT_AM_PMS)!=2 || udat_countSymbols(def, UDAT_QUARTERS) != 4 || udat_countSymbols(def, UDAT_SHORT_QUARTERS) != 4 || - udat_countSymbols(def, UDAT_LOCALIZED_CHARS)!=1 || udat_countSymbols(def, UDAT_SHORTER_WEEKDAYS)!=8) + udat_countSymbols(def, UDAT_LOCALIZED_CHARS)!=1 || udat_countSymbols(def, UDAT_SHORTER_WEEKDAYS)!=8 || + udat_countSymbols(zhChiCal, UDAT_CYCLIC_YEARS_NARROW)!=60 || udat_countSymbols(zhChiCal, UDAT_ZODIAC_NAMES_NARROW)!=12) { log_err("FAIL: error in udat_countSymbols\n"); } @@ -659,6 +669,10 @@ static void TestSymbols() VerifygetSymbols(def, UDAT_QUARTERS, 3, "4th quarter"); VerifygetSymbols(fr, UDAT_SHORT_QUARTERS, 1, "T2"); VerifygetSymbols(def, UDAT_SHORT_QUARTERS, 2, "Q3"); + VerifygetSymbols(zhChiCal, UDAT_CYCLIC_YEARS_ABBREVIATED, 0, "\\u7532\\u5B50"); + VerifygetSymbols(zhChiCal, UDAT_CYCLIC_YEARS_NARROW, 59, "\\u7678\\u4EA5"); + VerifygetSymbols(zhChiCal, UDAT_ZODIAC_NAMES_ABBREVIATED, 0, "\\u9F20"); + VerifygetSymbols(zhChiCal, UDAT_ZODIAC_NAMES_WIDE, 11, "\\u732A"); VerifygetSymbols(def,UDAT_LOCALIZED_CHARS, 0, "GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxr"); @@ -773,8 +787,10 @@ free(pattern); VerifysetSymbols(fr, UDAT_SHORT_QUARTERS, 1, "QQ2"); VerifysetSymbols(fr, UDAT_STANDALONE_QUARTERS, 2, "3rd Quar."); VerifysetSymbols(fr, UDAT_STANDALONE_SHORT_QUARTERS, 3, "4QQ"); + VerifysetSymbols(zhChiCal, UDAT_CYCLIC_YEARS_ABBREVIATED, 1, "yi-chou"); + VerifysetSymbols(zhChiCal, UDAT_ZODIAC_NAMES_ABBREVIATED, 1, "Ox"); + - /*run series of tests to test get and setSymbols regressively*/ log_verbose("\nTesting get and set symbols regressively\n"); VerifygetsetSymbols(fr, def, UDAT_WEEKDAYS, 1); @@ -792,6 +808,7 @@ free(pattern); udat_close(fr); udat_close(def); + udat_close(zhChiCal); if(result != NULL) { free(result); result = NULL; @@ -1002,10 +1019,10 @@ static void VerifygetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, in UErrorCode status = U_ZERO_ERROR; UChar *result=NULL; int32_t resultlength, resultlengthout; - + int32_t patternSize = strlen(expected) + 1; - pattern=(UChar*)malloc(sizeof(UChar) * (strlen(expected)+1)); - u_uastrcpy(pattern, expected); + pattern=(UChar*)malloc(sizeof(UChar) * patternSize); + u_unescape(expected, pattern, patternSize); resultlength=0; resultlengthout=udat_getSymbols(datfor, type, idx , NULL, resultlength, &status); if(status==U_BUFFER_OVERFLOW_ERROR) @@ -1024,8 +1041,8 @@ static void VerifygetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, in if(u_strcmp(result, pattern)==0) log_verbose("PASS: getSymbols retrieved the right value\n"); else{ - log_data_err("FAIL: getSymbols retrieved the wrong value\n Expected %s Got %s\n", austrdup(pattern), - austrdup(result) ); + log_data_err("FAIL: getSymbols retrieved the wrong value\n Expected %s Got %s\n", expected, + aescstrdup(result,-1) ); } free(result); free(pattern); @@ -1037,10 +1054,11 @@ static void VerifysetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, in UChar *value=NULL; int32_t resultlength, resultlengthout; UErrorCode status = U_ZERO_ERROR; + int32_t valueLen, valueSize = strlen(expected) + 1; - value=(UChar*)malloc(sizeof(UChar) * (strlen(expected) + 1)); - u_uastrcpy(value, expected); - udat_setSymbols(datfor, type, idx, value, u_strlen(value), &status); + value=(UChar*)malloc(sizeof(UChar) * valueSize); + valueLen = u_unescape(expected, value, valueSize); + udat_setSymbols(datfor, type, idx, value, valueLen, &status); if(U_FAILURE(status)) { log_err("FAIL: Error in udat_setSymbols() %s\n", myErrorName(status) ); @@ -1062,8 +1080,8 @@ static void VerifysetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, in } if(u_strcmp(result, value)!=0){ - log_err("FAIL:Error in setting and then getting symbols\n Expected %s Got %s\n", austrdup(value), - austrdup(result) ); + log_err("FAIL:Error in setting and then getting symbols\n Expected %s Got %s\n", expected, + aescstrdup(result,-1) ); } else log_verbose("PASS: setSymbols successful\n");