ICU-9110 Add date format functions to set/get context, use when formatting

X-SVN-Rev: 31458
This commit is contained in:
Peter Edberg 2012-02-21 01:29:50 +00:00
parent be22ad9f19
commit 60152763f3
6 changed files with 422 additions and 47 deletions

View file

@ -203,6 +203,8 @@ static const char gHourFormatTag[]="hourFormat";
static const char gLocalPatternCharsTag[]="localPatternChars";
static const char gContextTransformsTag[]="contextTransforms";
static UMTX LOCK;
/**
@ -370,6 +372,8 @@ DateFormatSymbols::copyData(const DateFormatSymbols& other) {
// fastCopyFrom() - see assignArray comments
fLocalPatternChars.fastCopyFrom(other.fLocalPatternChars);
uprv_memcpy(fCapitalization, other.fCapitalization, sizeof(fCapitalization));
}
/**
@ -483,7 +487,8 @@ DateFormatSymbols::operator==(const DateFormatSymbols& other) const
fShortYearNamesCount == other.fShortYearNamesCount &&
fGmtHourFormatsCount == other.fGmtHourFormatsCount &&
fGmtZero == other.fGmtZero &&
fGmtFormat == other.fGmtFormat)
fGmtFormat == other.fGmtFormat &&
(uprv_memcmp(fCapitalization, other.fCapitalization, sizeof(fCapitalization))==0))
{
// Now compare the arrays themselves
if (arrayCompare(fEras, other.fEras, fErasCount) &&
@ -1254,6 +1259,29 @@ initLeapMonthPattern(UnicodeString *field, int32_t index, const UResourceBundle
status = U_ZERO_ERROR;
}
typedef struct {
const char * usageTypeName;
DateFormatSymbols::ECapitalizationContextUsageType usageTypeEnumValue;
} ContextUsageTypeNameToEnumValue;
static const ContextUsageTypeNameToEnumValue contextUsageTypeMap[] = {
// Entries must be sorted by usageTypeName; entry with NULL name terminates list.
{ "day-format-except-narrow", DateFormatSymbols::kCapContextUsageDayFormat },
{ "day-narrow", DateFormatSymbols::kCapContextUsageDayNarrow },
{ "day-standalone-except-narrow", DateFormatSymbols::kCapContextUsageDayStandalone },
{ "era-abbr", DateFormatSymbols::kCapContextUsageEraAbbrev },
{ "era-name", DateFormatSymbols::kCapContextUsageEraWide },
{ "era-narrow", DateFormatSymbols::kCapContextUsageEraNarrow },
{ "metazone-long", DateFormatSymbols::kCapContextUsageMetazoneLong },
{ "metazone-short", DateFormatSymbols::kCapContextUsageMetazoneShort },
{ "month-format-except-narrow", DateFormatSymbols::kCapContextUsageMonthFormat },
{ "month-narrow", DateFormatSymbols::kCapContextUsageMonthNarrow },
{ "month-standalone-except-narrow", DateFormatSymbols::kCapContextUsageMonthStandalone },
{ "zone-long", DateFormatSymbols::kCapContextUsageZoneLong },
{ "zone-short", DateFormatSymbols::kCapContextUsageZoneShort },
{ NULL, (DateFormatSymbols::ECapitalizationContextUsageType)0 },
};
void
DateFormatSymbols::initializeData(const Locale& locale, const char *type, UErrorCode& status, UBool useLastResortData)
{
@ -1311,6 +1339,7 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError
fZoneStringsColCount = 0;
fZoneStrings = NULL;
fLocaleZoneStrings = NULL;
uprv_memset(fCapitalization, 0, sizeof(fCapitalization));
// We need to preserve the requested locale for
// lazy ZoneStringFormat instantiation. ZoneStringFormat
@ -1350,19 +1379,19 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError
narrowEras = ures_getByKeyWithFallback(erasMain, gNamesAbbrTag, NULL, &status);
}
UErrorCode monthPatternStatus = U_ZERO_ERROR;
UResourceBundle *monthPatterns = calData.getByKey(gMonthPatternsTag, monthPatternStatus);
if (U_SUCCESS(monthPatternStatus) && monthPatterns != NULL) {
UErrorCode tempStatus = U_ZERO_ERROR;
UResourceBundle *monthPatterns = calData.getByKey(gMonthPatternsTag, tempStatus);
if (U_SUCCESS(tempStatus) && monthPatterns != NULL) {
fLeapMonthPatterns = newUnicodeStringArray(kMonthPatternsCount);
if (fLeapMonthPatterns) {
initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatWide, calData.getByKey2(gMonthPatternsTag, gNamesWideTag, monthPatternStatus), monthPatternStatus);
initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatAbbrev, calData.getByKey2(gMonthPatternsTag, gNamesAbbrTag, monthPatternStatus), monthPatternStatus);
initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatNarrow, calData.getByKey2(gMonthPatternsTag, gNamesNarrowTag, monthPatternStatus), monthPatternStatus);
initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneWide, calData.getByKey3(gMonthPatternsTag, gNamesStandaloneTag, gNamesWideTag, monthPatternStatus), monthPatternStatus);
initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneAbbrev, calData.getByKey3(gMonthPatternsTag, gNamesStandaloneTag, gNamesAbbrTag, monthPatternStatus), monthPatternStatus);
initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneNarrow, calData.getByKey3(gMonthPatternsTag, gNamesStandaloneTag, gNamesNarrowTag, monthPatternStatus), monthPatternStatus);
initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternNumeric, calData.getByKey3(gMonthPatternsTag, gNamesNumericTag, gNamesAllTag, monthPatternStatus), monthPatternStatus);
if (U_SUCCESS(monthPatternStatus)) {
initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatWide, calData.getByKey2(gMonthPatternsTag, gNamesWideTag, tempStatus), tempStatus);
initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatAbbrev, calData.getByKey2(gMonthPatternsTag, gNamesAbbrTag, tempStatus), tempStatus);
initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatNarrow, calData.getByKey2(gMonthPatternsTag, gNamesNarrowTag, tempStatus), tempStatus);
initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneWide, calData.getByKey3(gMonthPatternsTag, gNamesStandaloneTag, gNamesWideTag, tempStatus), tempStatus);
initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneAbbrev, calData.getByKey3(gMonthPatternsTag, gNamesStandaloneTag, gNamesAbbrTag, tempStatus), tempStatus);
initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneNarrow, calData.getByKey3(gMonthPatternsTag, gNamesStandaloneTag, gNamesNarrowTag, tempStatus), tempStatus);
initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternNumeric, calData.getByKey3(gMonthPatternsTag, gNamesNumericTag, gNamesAllTag, tempStatus), tempStatus);
if (U_SUCCESS(tempStatus)) {
fLeapMonthPatternsCount = kMonthPatternsCount;
} else {
delete[] fLeapMonthPatterns;
@ -1371,16 +1400,16 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError
}
}
UErrorCode cyclicNamesStatus = U_ZERO_ERROR;
UResourceBundle *cyclicNameSets= calData.getByKey(gCyclicNameSetsTag, cyclicNamesStatus);
if (U_SUCCESS(cyclicNamesStatus) && cyclicNameSets != NULL) {
UResourceBundle *nameSetYears = ures_getByKeyWithFallback(cyclicNameSets, gNameSetYearsTag, NULL, &cyclicNamesStatus);
if (U_SUCCESS(cyclicNamesStatus)) {
UResourceBundle *nameSetYearsFmt = ures_getByKeyWithFallback(nameSetYears, gNamesFormatTag, NULL, &cyclicNamesStatus);
if (U_SUCCESS(cyclicNamesStatus)) {
UResourceBundle *nameSetYearsFmtAbbrev = ures_getByKeyWithFallback(nameSetYearsFmt, gNamesAbbrTag, NULL, &cyclicNamesStatus);
if (U_SUCCESS(cyclicNamesStatus)) {
initField(&fShortYearNames, fShortYearNamesCount, nameSetYearsFmtAbbrev, cyclicNamesStatus);
tempStatus = U_ZERO_ERROR;
UResourceBundle *cyclicNameSets= calData.getByKey(gCyclicNameSetsTag, tempStatus);
if (U_SUCCESS(tempStatus) && cyclicNameSets != NULL) {
UResourceBundle *nameSetYears = ures_getByKeyWithFallback(cyclicNameSets, gNameSetYearsTag, NULL, &tempStatus);
if (U_SUCCESS(tempStatus)) {
UResourceBundle *nameSetYearsFmt = ures_getByKeyWithFallback(nameSetYears, gNamesFormatTag, NULL, &tempStatus);
if (U_SUCCESS(tempStatus)) {
UResourceBundle *nameSetYearsFmtAbbrev = ures_getByKeyWithFallback(nameSetYearsFmt, gNamesAbbrTag, NULL, &tempStatus);
if (U_SUCCESS(tempStatus)) {
initField(&fShortYearNames, fShortYearNamesCount, nameSetYearsFmtAbbrev, tempStatus);
ures_close(nameSetYearsFmtAbbrev);
}
ures_close(nameSetYearsFmt);
@ -1389,6 +1418,37 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError
}
}
tempStatus = U_ZERO_ERROR;
UResourceBundle *localeBundle = ures_open(NULL, locale.getName(), &tempStatus);
if (U_SUCCESS(tempStatus)) {
UResourceBundle *contextTransforms = ures_getByKeyWithFallback(localeBundle, gContextTransformsTag, NULL, &tempStatus);
if (U_SUCCESS(tempStatus)) {
UResourceBundle *contextTransformUsage;
while ( (contextTransformUsage = ures_getNextResource(contextTransforms, NULL, &tempStatus)) != NULL ) {
const int32_t * intVector = ures_getIntVector(contextTransformUsage, &len, &status);
if (U_SUCCESS(tempStatus) && intVector != NULL && len >= 2) {
const char* usageType = ures_getKey(contextTransformUsage);
if (usageType != NULL) {
const ContextUsageTypeNameToEnumValue * typeMapPtr = contextUsageTypeMap;
int32_t compResult = 0;
// linear search; list is short and we cannot be sure that bsearch is available
while ( typeMapPtr->usageTypeName != NULL && (compResult = uprv_strcmp(usageType, typeMapPtr->usageTypeName)) > 0 ) {
++typeMapPtr;
}
if (typeMapPtr->usageTypeName != NULL && compResult == 0) {
fCapitalization[typeMapPtr->usageTypeEnumValue][0] = intVector[0];
fCapitalization[typeMapPtr->usageTypeEnumValue][1] = intVector[1];
}
}
}
tempStatus = U_ZERO_ERROR;
ures_close(contextTransformUsage);
}
ures_close(contextTransforms);
}
ures_close(localeBundle);
}
UResourceBundle *lsweekdaysData = NULL; // Data closed by calData
UResourceBundle *weekdaysData = NULL; // Data closed by calData
UResourceBundle *narrowWeekdaysData = NULL; // Data closed by calData

View file

@ -244,7 +244,8 @@ SimpleDateFormat::SimpleDateFormat(UErrorCode& status)
fTimeZoneFormat(NULL),
fGMTFormatters(NULL),
fNumberFormatters(NULL),
fOverrideList(NULL)
fOverrideList(NULL),
fDefaultCapitalizationContext(UDAT_CAPITALIZATION_UNKNOWN)
{
construct(kShort, (EStyle) (kShort + kDateOffset), fLocale, status);
initializeDefaultCentury();
@ -260,7 +261,8 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
fTimeZoneFormat(NULL),
fGMTFormatters(NULL),
fNumberFormatters(NULL),
fOverrideList(NULL)
fOverrideList(NULL),
fDefaultCapitalizationContext(UDAT_CAPITALIZATION_UNKNOWN)
{
fDateOverride.setToBogus();
fTimeOverride.setToBogus();
@ -280,7 +282,8 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
fTimeZoneFormat(NULL),
fGMTFormatters(NULL),
fNumberFormatters(NULL),
fOverrideList(NULL)
fOverrideList(NULL),
fDefaultCapitalizationContext(UDAT_CAPITALIZATION_UNKNOWN)
{
fDateOverride.setTo(override);
fTimeOverride.setToBogus();
@ -302,7 +305,8 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
fTimeZoneFormat(NULL),
fGMTFormatters(NULL),
fNumberFormatters(NULL),
fOverrideList(NULL)
fOverrideList(NULL),
fDefaultCapitalizationContext(UDAT_CAPITALIZATION_UNKNOWN)
{
fDateOverride.setToBogus();
@ -324,7 +328,8 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
fTimeZoneFormat(NULL),
fGMTFormatters(NULL),
fNumberFormatters(NULL),
fOverrideList(NULL)
fOverrideList(NULL),
fDefaultCapitalizationContext(UDAT_CAPITALIZATION_UNKNOWN)
{
fDateOverride.setTo(override);
@ -349,7 +354,8 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
fTimeZoneFormat(NULL),
fGMTFormatters(NULL),
fNumberFormatters(NULL),
fOverrideList(NULL)
fOverrideList(NULL),
fDefaultCapitalizationContext(UDAT_CAPITALIZATION_UNKNOWN)
{
fDateOverride.setToBogus();
@ -371,7 +377,8 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
fTimeZoneFormat(NULL),
fGMTFormatters(NULL),
fNumberFormatters(NULL),
fOverrideList(NULL)
fOverrideList(NULL),
fDefaultCapitalizationContext(UDAT_CAPITALIZATION_UNKNOWN)
{
fDateOverride.setToBogus();
@ -394,7 +401,8 @@ SimpleDateFormat::SimpleDateFormat(EStyle timeStyle,
fTimeZoneFormat(NULL),
fGMTFormatters(NULL),
fNumberFormatters(NULL),
fOverrideList(NULL)
fOverrideList(NULL),
fDefaultCapitalizationContext(UDAT_CAPITALIZATION_UNKNOWN)
{
construct(timeStyle, dateStyle, fLocale, status);
if(U_SUCCESS(status)) {
@ -417,7 +425,8 @@ SimpleDateFormat::SimpleDateFormat(const Locale& locale,
fTimeZoneFormat(NULL),
fGMTFormatters(NULL),
fNumberFormatters(NULL),
fOverrideList(NULL)
fOverrideList(NULL),
fDefaultCapitalizationContext(UDAT_CAPITALIZATION_UNKNOWN)
{
if (U_FAILURE(status)) return;
initializeSymbols(fLocale, initializeCalendar(NULL, fLocale, status),status);
@ -451,7 +460,8 @@ SimpleDateFormat::SimpleDateFormat(const SimpleDateFormat& other)
fTimeZoneFormat(NULL),
fGMTFormatters(NULL),
fNumberFormatters(NULL),
fOverrideList(NULL)
fOverrideList(NULL),
fDefaultCapitalizationContext(UDAT_CAPITALIZATION_UNKNOWN)
{
*this = other;
}
@ -482,6 +492,8 @@ SimpleDateFormat& SimpleDateFormat::operator=(const SimpleDateFormat& other)
delete fTimeZoneFormat;
}
fDefaultCapitalizationContext = other.fDefaultCapitalizationContext;
return *this;
}
@ -506,7 +518,8 @@ SimpleDateFormat::operator==(const Format& other) const
that->fSymbols != NULL && // Check for pathological object
*fSymbols == *that->fSymbols &&
fHaveDefaultCentury == that->fHaveDefaultCentury &&
fDefaultCenturyStart == that->fDefaultCenturyStart);
fDefaultCenturyStart == that->fDefaultCenturyStart &&
fDefaultCapitalizationContext == that->fDefaultCapitalizationContext);
}
return FALSE;
}
@ -813,7 +826,22 @@ SimpleDateFormat::format(Calendar& cal, UnicodeString& appendTo, FieldPosition&
{
UErrorCode status = U_ZERO_ERROR;
FieldPositionOnlyHandler handler(pos);
return _format(cal, appendTo, handler, status);
return _format(cal, fDefaultCapitalizationContext, appendTo, handler, status);
}
//----------------------------------------------------------------------
UnicodeString&
SimpleDateFormat::format(Calendar& cal, const UDateFormatContextType* types, const UDateFormatContextValue* values,
int32_t typesAndValuesCount, UnicodeString& appendTo, FieldPosition& pos) const
{
UErrorCode status = U_ZERO_ERROR;
FieldPositionOnlyHandler handler(pos);
UDateFormatContextValue capitalizationContext = fDefaultCapitalizationContext;
if (types != NULL && values != NULL && typesAndValuesCount==1 && types[0]==UDAT_CAPITALIZATION) {
capitalizationContext = values[0];
}
return _format(cal, capitalizationContext, appendTo, handler, status);
}
//----------------------------------------------------------------------
@ -823,14 +851,14 @@ SimpleDateFormat::format(Calendar& cal, UnicodeString& appendTo,
FieldPositionIterator* posIter, UErrorCode& status) const
{
FieldPositionIteratorHandler handler(posIter, status);
return _format(cal, appendTo, handler, status);
return _format(cal, fDefaultCapitalizationContext, appendTo, handler, status);
}
//----------------------------------------------------------------------
UnicodeString&
SimpleDateFormat::_format(Calendar& cal, UnicodeString& appendTo, FieldPositionHandler& handler,
UErrorCode& status) const
SimpleDateFormat::_format(Calendar& cal, UDateFormatContextValue capitalizationContext,
UnicodeString& appendTo, FieldPositionHandler& handler, UErrorCode& status) const
{
if ( U_FAILURE(status) ) {
return appendTo;
@ -856,6 +884,7 @@ SimpleDateFormat::_format(Calendar& cal, UnicodeString& appendTo, FieldPositionH
UBool inQuote = FALSE;
UChar prevCh = 0;
int32_t count = 0;
int32_t fieldNum = 0;
// loop through the pattern string character by character
for (int32_t i = 0; i < fPattern.length() && U_SUCCESS(status); ++i) {
@ -864,7 +893,7 @@ SimpleDateFormat::_format(Calendar& cal, UnicodeString& appendTo, FieldPositionH
// Use subFormat() to format a repeated pattern character
// when a different pattern or non-pattern character is seen
if (ch != prevCh && count > 0) {
subFormat(appendTo, prevCh, count, handler, *workCal, status);
subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, handler, *workCal, status);
count = 0;
}
if (ch == QUOTE) {
@ -892,7 +921,7 @@ SimpleDateFormat::_format(Calendar& cal, UnicodeString& appendTo, FieldPositionH
// Format the last item in the pattern, if any
if (count > 0) {
subFormat(appendTo, prevCh, count, handler, *workCal, status);
subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, handler, *workCal, status);
}
if (calClone != NULL) {
@ -1536,6 +1565,8 @@ void
SimpleDateFormat::subFormat(UnicodeString &appendTo,
UChar ch,
int32_t count,
UDateFormatContextValue capitalizationContext,
int32_t fieldNum,
FieldPositionHandler& handler,
Calendar& cal,
UErrorCode& status) const
@ -1552,6 +1583,7 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
const int32_t maxIntCount = 10;
int32_t beginOffset = appendTo.length();
NumberFormat *currentNumberFormat;
DateFormatSymbols::ECapitalizationContextUsageType capContextUsageType = DateFormatSymbols::kCapContextUsageOther;
UBool isHebrewCalendar = (uprv_strcmp(cal.getType(),"hebrew") == 0);
UBool isChineseCalendar = (uprv_strcmp(cal.getType(),"chinese") == 0);
@ -1583,10 +1615,13 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
} else {
if (count == 5) {
_appendSymbol(appendTo, value, fSymbols->fNarrowEras, fSymbols->fNarrowErasCount);
capContextUsageType = DateFormatSymbols::kCapContextUsageEraNarrow;
} else if (count == 4) {
_appendSymbol(appendTo, value, fSymbols->fEraNames, fSymbols->fEraNamesCount);
capContextUsageType = DateFormatSymbols::kCapContextUsageEraWide;
} else {
_appendSymbol(appendTo, value, fSymbols->fEras, fSymbols->fErasCount);
capContextUsageType = DateFormatSymbols::kCapContextUsageEraAbbrev;
}
}
break;
@ -1640,21 +1675,26 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
_appendSymbolWithMonthPattern(appendTo, value, fSymbols->fStandaloneNarrowMonths, fSymbols->fStandaloneNarrowMonthsCount,
(isLeapMonth!=0)? &(fSymbols->fLeapMonthPatterns[DateFormatSymbols::kLeapMonthPatternStandaloneNarrow]): NULL, status);
}
capContextUsageType = DateFormatSymbols::kCapContextUsageMonthNarrow;
} else if (count == 4) {
if (patternCharIndex == UDAT_MONTH_FIELD) {
_appendSymbolWithMonthPattern(appendTo, value, fSymbols->fMonths, fSymbols->fMonthsCount,
(isLeapMonth!=0)? &(fSymbols->fLeapMonthPatterns[DateFormatSymbols::kLeapMonthPatternFormatWide]): NULL, status);
capContextUsageType = DateFormatSymbols::kCapContextUsageMonthFormat;
} else {
_appendSymbolWithMonthPattern(appendTo, value, fSymbols->fStandaloneMonths, fSymbols->fStandaloneMonthsCount,
(isLeapMonth!=0)? &(fSymbols->fLeapMonthPatterns[DateFormatSymbols::kLeapMonthPatternStandaloneWide]): NULL, status);
capContextUsageType = DateFormatSymbols::kCapContextUsageMonthStandalone;
}
} else if (count == 3) {
if (patternCharIndex == UDAT_MONTH_FIELD) {
_appendSymbolWithMonthPattern(appendTo, value, fSymbols->fShortMonths, fSymbols->fShortMonthsCount,
(isLeapMonth!=0)? &(fSymbols->fLeapMonthPatterns[DateFormatSymbols::kLeapMonthPatternFormatAbbrev]): NULL, status);
capContextUsageType = DateFormatSymbols::kCapContextUsageMonthFormat;
} else {
_appendSymbolWithMonthPattern(appendTo, value, fSymbols->fStandaloneShortMonths, fSymbols->fStandaloneShortMonthsCount,
(isLeapMonth!=0)? &(fSymbols->fLeapMonthPatterns[DateFormatSymbols::kLeapMonthPatternStandaloneAbbrev]): NULL, status);
capContextUsageType = DateFormatSymbols::kCapContextUsageMonthStandalone;
}
} else {
UnicodeString monthNumber;
@ -1709,15 +1749,19 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
}
// fall through, do not break here
case UDAT_DAY_OF_WEEK_FIELD:
if (count == 5)
if (count == 5) {
_appendSymbol(appendTo, value, fSymbols->fNarrowWeekdays,
fSymbols->fNarrowWeekdaysCount);
else if (count == 4)
capContextUsageType = DateFormatSymbols::kCapContextUsageDayNarrow;
} else if (count == 4) {
_appendSymbol(appendTo, value, fSymbols->fWeekdays,
fSymbols->fWeekdaysCount);
else
capContextUsageType = DateFormatSymbols::kCapContextUsageDayFormat;
} else {
_appendSymbol(appendTo, value, fSymbols->fShortWeekdays,
fSymbols->fShortWeekdaysCount);
capContextUsageType = DateFormatSymbols::kCapContextUsageDayFormat;
}
break;
// for "ccc", write out the abbreviated day-of-the-week name
@ -1734,15 +1778,19 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
if (U_FAILURE(status)) {
return;
}
if (count == 5)
if (count == 5) {
_appendSymbol(appendTo, value, fSymbols->fStandaloneNarrowWeekdays,
fSymbols->fStandaloneNarrowWeekdaysCount);
else if (count == 4)
capContextUsageType = DateFormatSymbols::kCapContextUsageDayNarrow;
} else if (count == 4) {
_appendSymbol(appendTo, value, fSymbols->fStandaloneWeekdays,
fSymbols->fStandaloneWeekdaysCount);
else // count == 3
capContextUsageType = DateFormatSymbols::kCapContextUsageDayStandalone;
} else { // count == 3
_appendSymbol(appendTo, value, fSymbols->fStandaloneShortWeekdays,
fSymbols->fStandaloneShortWeekdaysCount);
capContextUsageType = DateFormatSymbols::kCapContextUsageDayStandalone;
}
break;
// for and "a" symbol, write out the whole AM/PM string
@ -1778,25 +1826,31 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
if (count < 4) {
// "z", "zz", "zzz"
tzFormat()->format(UTZFMT_STYLE_SPECIFIC_SHORT, tz, date, zoneString);
capContextUsageType = DateFormatSymbols::kCapContextUsageMetazoneShort;
} else {
// "zzzz"
tzFormat()->format(UTZFMT_STYLE_SPECIFIC_LONG, tz, date, zoneString);
capContextUsageType = DateFormatSymbols::kCapContextUsageMetazoneLong;
}
} else if (patternCharIndex == UDAT_TIMEZONE_GENERIC_FIELD) {
if (count == 1) {
// "v"
tzFormat()->format(UTZFMT_STYLE_GENERIC_SHORT, tz, date, zoneString);
capContextUsageType = DateFormatSymbols::kCapContextUsageMetazoneShort;
} else if (count == 4) {
// "vvvv"
tzFormat()->format(UTZFMT_STYLE_GENERIC_LONG, tz, date, zoneString);
capContextUsageType = DateFormatSymbols::kCapContextUsageMetazoneLong;
}
} else { // patternCharIndex == UDAT_TIMEZONE_SPECIAL_FIELD
if (count == 1) {
// "V"
tzFormat()->format(UTZFMT_STYLE_SPECIFIC_SHORT, tz, date, zoneString);
capContextUsageType = DateFormatSymbols::kCapContextUsageMetazoneShort;
} else if (count == 4) {
// "VVVV"
tzFormat()->format(UTZFMT_STYLE_LOCATION, tz, date, zoneString);
capContextUsageType = DateFormatSymbols::kCapContextUsageZoneLong;
}
}
}
@ -1848,6 +1902,30 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
zeroPaddingNumber(currentNumberFormat,appendTo, value, count, maxIntCount);
break;
}
if (fieldNum == 0) {
// first field, check to see whether we need to titlecase it
UBool titlecase = FALSE;
switch (capitalizationContext) {
case UDAT_CAPITALIZATION_BEGINNING_OF_SENTENCE:
titlecase = TRUE;
break;
case UDAT_CAPITALIZATION_UI_LIST_OR_MENU:
titlecase = fSymbols->fCapitalization[capContextUsageType][0];
break;
case UDAT_CAPITALIZATION_STANDALONE:
titlecase = fSymbols->fCapitalization[capContextUsageType][1];
break;
default:
// titlecase = FALSE;
break;
}
if (titlecase) {
UnicodeString firstField(appendTo, beginOffset);
firstField.toTitle(NULL, fLocale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
appendTo.replaceBetween(beginOffset, appendTo.length(), firstField);
}
}
handler.addAttribute(fgPatternIndexToDateFormatField[patternCharIndex], beginOffset, appendTo.length());
}
@ -3519,6 +3597,37 @@ void SimpleDateFormat::adoptCalendar(Calendar* calendarToAdopt)
//----------------------------------------------------------------------
void SimpleDateFormat::setDefaultContext(UDateFormatContextType type,
UDateFormatContextValue value, UErrorCode& status)
{
if (U_FAILURE(status))
return;
if (type != UDAT_CAPITALIZATION) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
fDefaultCapitalizationContext = value;
}
//----------------------------------------------------------------------
int32_t SimpleDateFormat::getDefaultContext(UDateFormatContextType type, UErrorCode& status) const
{
if (U_FAILURE(status))
return 0;
if (type != UDAT_CAPITALIZATION) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return 0;
}
return (int32_t)fDefaultCapitalizationContext;
}
//----------------------------------------------------------------------
UBool
SimpleDateFormat::isFieldUnitIgnored(UCalendarDateFields field) const {
return isFieldUnitIgnored(fPattern, field);

View file

@ -941,6 +941,32 @@ udat_getLocaleByType(const UDateFormat *fmt,
return ((Format*)fmt)->getLocaleID(type, *status);
}
U_CAPI void U_EXPORT2
udat_setDefaultContext(UDateFormat* fmt,
UDateFormatContextType type, UDateFormatContextValue value,
UErrorCode* status)
{
verifyIsSimpleDateFormat(fmt, status);
if (U_FAILURE(*status)) {
return;
}
((SimpleDateFormat*)fmt)->setDefaultContext(type, value, *status);
}
U_CAPI int32_t U_EXPORT2
udat_getDefaultContext(UDateFormat* fmt,
UDateFormatContextType type,
UErrorCode* status)
{
verifyIsSimpleDateFormat(fmt, status);
if (U_FAILURE(*status)) {
return 0;
}
return ((SimpleDateFormat*)fmt)->getDefaultContext(type, *status);
}
/**
* Verify that fmt is a RelativeDateFormat. Invalid error if not.
* @param fmt the UDateFormat, definitely a DateFormat, maybe something else

View file

@ -493,6 +493,31 @@ public:
*/
Locale getLocale(ULocDataLocaleType type, UErrorCode& status) const;
#ifndef U_HIDE_INTERNAL_API
/**
* Constants for capitalization context usage types.
* @internal
*/
enum ECapitalizationContextUsageType
{
kCapContextUsageOther,
kCapContextUsageMonthFormat, /* except narrow */
kCapContextUsageMonthStandalone, /* except narrow */
kCapContextUsageMonthNarrow,
kCapContextUsageDayFormat, /* except narrow */
kCapContextUsageDayStandalone, /* except narrow */
kCapContextUsageDayNarrow,
kCapContextUsageEraWide,
kCapContextUsageEraAbbrev,
kCapContextUsageEraNarrow,
kCapContextUsageZoneLong,
kCapContextUsageZoneShort,
kCapContextUsageMetazoneLong,
kCapContextUsageMetazoneShort,
kCapContextUsageTypeCount
};
#endif /* U_HIDE_INTERNAL_API */
/**
* ICU "poor man's RTTI", returns a UClassID for the actual class.
*
@ -717,6 +742,14 @@ private:
*/
UnicodeString fLocalPatternChars;
/**
* Capitalization transforms. For each usage type, the first array element indicates
* whether to titlecase for uiListOrMenu context, the second indicates whether to
* titlecase for stand-alone context.
*/
UBool fCapitalization[kCapContextUsageTypeCount][2];
private:
/** valid/actual locale information
* these are always ICU locales, so the length should not be a problem

View file

@ -398,6 +398,38 @@ public:
UnicodeString& appendTo,
FieldPosition& pos) const;
/* Cannot use #ifndef U_HIDE_DRAFT_API for the following draft method since it is virtual */
/**
* Format a date or time, which is the standard millis since 24:00 GMT, Jan
* 1, 1970. Overrides DateFormat pure virtual method.
* <P>
* Example: using the US locale: "yyyy.MM.dd e 'at' HH:mm:ss zzz" ->>
* 1996.07.10 AD at 15:08:56 PDT
*
* @param cal Calendar set to the date and time to be formatted
* into a date/time string.
* @param types Array of UDateFormatContextTypes for which the corresponding
* value specified in the next parameter should override the
* formatter's default value for this call (this does not
* change the default value).
* @param values Array of UDateFormatContextValues corresponding 1-1 to the
* UDateFormatContextTypes in the previous parameter.
* @param typesAndValuesCount Number of elements in the types and values
* arrays.
* @param appendTo Output parameter to receive result.
* Result is appended to existing contents.
* @param pos The formatting position. On input: an alignment field,
* if desired. On output: the offsets of the alignment field.
* @return Reference to 'appendTo' parameter.
* @draft ICU 49
*/
virtual UnicodeString& format( Calendar& cal,
const UDateFormatContextType* types,
const UDateFormatContextValue* values,
int32_t typesAndValuesCount,
UnicodeString& appendTo,
FieldPosition& pos) const;
/**
* Format a date or time, which is the standard millis since 24:00 GMT, Jan
* 1, 1970. Overrides DateFormat pure virtual method.
@ -772,6 +804,33 @@ public:
*/
virtual void adoptCalendar(Calendar* calendarToAdopt);
/* Cannot use #ifndef U_HIDE_DRAFT_API for the following draft method since it is virtual */
/**
* Set the formatter's default value for a particular context type,
* such as UDAT_CAPITALIZATION.
* @param type The context type for which the default value should be set.
* @param value The default value to set for the specified context type.
* @param status Input/output status. If at entry this indicates a failure
* status, the function will do nothing; otherwise this will be
* updated with any new status from the function.
* @draft ICU 49
*/
virtual void setDefaultContext(UDateFormatContextType type, UDateFormatContextValue value,
UErrorCode& status);
/* Cannot use #ifndef U_HIDE_DRAFT_API for the following draft method since it is virtual */
/**
* Get the formatter's default value for a particular context type,
* such as UDAT_CAPITALIZATION.
* @param type The context type for which the default value should be obtained.
* @param status Input/output status. If at entry this indicates a failure
* status, the function will do nothing; otherwise this will be
* updated with any new status from the function.
* @return The current default value for the specified context type.
* @draft ICU 49
*/
virtual int32_t getDefaultContext(UDateFormatContextType type, UErrorCode& status) const;
#ifndef U_HIDE_INTERNAL_API
/**
* This is for ICU internal use only. Please do not use.
@ -841,8 +900,8 @@ private:
/**
* Hook called by format(... FieldPosition& ...) and format(...FieldPositionIterator&...)
*/
UnicodeString& _format(Calendar& cal, UnicodeString& appendTo, FieldPositionHandler& handler,
UErrorCode& status) const;
UnicodeString& _format(Calendar& cal, UDateFormatContextValue capitalizationContext,
UnicodeString& appendTo, FieldPositionHandler& handler, UErrorCode& status) const;
/**
* Called by format() to format a single field.
@ -853,6 +912,8 @@ private:
* @param count Number of characters in the current pattern symbol (e.g.,
* "yyyy" in the pattern would result in a call to this function
* with ch equal to 'y' and count equal to 4)
* @param capitalizationContext Capitalization context for this date format.
* @param fieldNum Zero-based numbering of current field within the overall format.
* @param handler Records information about field positions.
* @param cal Calendar to use
* @param status Receives a status code, which will be U_ZERO_ERROR if the operation
@ -861,6 +922,8 @@ private:
void subFormat(UnicodeString &appendTo,
UChar ch,
int32_t count,
UDateFormatContextValue capitalizationContext,
int32_t fieldNum,
FieldPositionHandler& handler,
Calendar& cal,
UErrorCode& status) const; // in case of illegal argument
@ -1213,6 +1276,8 @@ private:
NSOverride *fOverrideList;
UBool fHaveDefaultCentury;
UDateFormatContextValue fDefaultCapitalizationContext;
};
inline UDate

View file

@ -172,6 +172,58 @@ typedef enum UDateFormatStyle {
} UDateFormatStyle;
/* Cannot use #ifndef U_HIDE_DRAFT_API for UDateFormatContextType and UDateFormatContextValue
* since a SimpleDateFormat virtual method & data member depends on them */
/** Date format context types
* @draft ICU 49
*/
typedef enum UDateFormatContextType {
/**
* Type (key) for specifying the capitalization context for which a date
* is to be formatted (possible values are in UDateFormatContextValue).
* @draft ICU 49
*/
UDAT_CAPITALIZATION = 1
} UDateFormatContextType;
/** Values for date format context types
* @draft ICU 49
*/
typedef enum UDateFormatContextValue {
/** Values for type (key) UDAT_CAPITALIZATION */
/**
* UDAT_CAPITALIZATION value if the capitalization context for which a date
* (or date symbol) is to be formatted is unknown (this is the default if
* no UDAT_CAPITALIZATION value is explicitly specified).
* @draft ICU 49
*/
UDAT_CAPITALIZATION_UNKNOWN = 0,
/**
* UDAT_CAPITALIZATION value if a date (or date symbol) is to be formatted
* with capitalization appropriate for the middle of a sentence.
* @draft ICU 49
*/
UDAT_CAPITALIZATION_MIDDLE_OF_SENTENCE = 1,
/**
* UDAT_CAPITALIZATION value if a date (or date symbol) is to be formatted
* with capitalization appropriate for the beginning of a sentence.
* @draft ICU 49
*/
UDAT_CAPITALIZATION_BEGINNING_OF_SENTENCE = 2,
/**
* UDAT_CAPITALIZATION value if a date (or date symbol) is to be formatted
* with capitalization appropriate for a user-interface list or menu item.
* @draft ICU 49
*/
UDAT_CAPITALIZATION_UI_LIST_OR_MENU = 3,
/**
* UDAT_CAPITALIZATION value if a date (or date symbol) is to be formatted
* with capitalization appropriate for stand-alone usage such as an
* isolated name on a calendar page.
* @draft ICU 49
*/
UDAT_CAPITALIZATION_STANDALONE = 4
} UDateFormatContextValue;
/**
* @{
@ -966,6 +1018,36 @@ udat_getLocaleByType(const UDateFormat *fmt,
ULocDataLocaleType type,
UErrorCode* status);
#ifndef U_HIDE_DRAFT_API
/**
* Set the formatter's default value for a particular context type,
* such as UDAT_CAPITALIZATION.
* @param fmt The formatter for which to set a context type's default value.
* @param type The context type for which the default value should be set.
* @param value The default value to set for the specified context type.
* @param status A pointer to an UErrorCode to receive any errors
* @draft ICU 49
*/
U_DRAFT void U_EXPORT2
udat_setDefaultContext(UDateFormat* fmt,
UDateFormatContextType type, UDateFormatContextValue value,
UErrorCode* status);
/**
* Get the formatter's default value for a particular context type,
* such as UDAT_CAPITALIZATION.
* @param fmt The formatter from which to get a context type's default value.
* @param type The context type for which the default value should be obtained.
* @param status A pointer to an UErrorCode to receive any errors
* @return The current default value for the specified context type.
* @draft ICU 49
*/
U_DRAFT int32_t U_EXPORT2
udat_getDefaultContext(UDateFormat* fmt,
UDateFormatContextType type,
UErrorCode* status);
#endif /* U_HIDE_DRAFT_API */
#ifndef U_HIDE_INTERNAL_API
/**
* Extract the date pattern from a UDateFormat set for relative date formatting.