ICU-9110 J -Add SimpleDateFormat methods for setting context, use context when formatting
X-SVN-Rev: 31482
This commit is contained in:
parent
4eac54f2f6
commit
331eea1d3f
@ -10,7 +10,9 @@ package com.ibm.icu.text;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
@ -26,6 +28,7 @@ import com.ibm.icu.util.TimeZone;
|
||||
import com.ibm.icu.util.ULocale;
|
||||
import com.ibm.icu.util.ULocale.Category;
|
||||
import com.ibm.icu.util.UResourceBundle;
|
||||
import com.ibm.icu.util.UResourceBundleIterator;
|
||||
|
||||
/**
|
||||
* {@icuenhanced java.text.DateFormatSymbols}.{@icu _usage_}
|
||||
@ -542,6 +545,55 @@ public class DateFormatSymbols implements Serializable, Cloneable {
|
||||
{"EthiopicCalendar", "ethiopic"},
|
||||
};
|
||||
|
||||
/**
|
||||
* {@icu} Constants for capitalization context usage types
|
||||
* related to date formatting.
|
||||
* @internal
|
||||
*/
|
||||
enum CapitalizationContextUsage {
|
||||
OTHER,
|
||||
MONTH_FORMAT, /* except narrow */
|
||||
MONTH_STANDALONE, /* except narrow */
|
||||
MONTH_NARROW,
|
||||
DAY_FORMAT, /* except narrow */
|
||||
DAY_STANDALONE, /* except narrow */
|
||||
DAY_NARROW,
|
||||
ERA_WIDE,
|
||||
ERA_ABBREV,
|
||||
ERA_NARROW,
|
||||
ZONE_LONG,
|
||||
ZONE_SHORT,
|
||||
METAZONE_LONG,
|
||||
METAZONE_SHORT
|
||||
}
|
||||
|
||||
/** Map from resource key to CapitalizationContextUsage value
|
||||
*/
|
||||
private static final Map<String, CapitalizationContextUsage> contextUsageTypeMap;
|
||||
static {
|
||||
contextUsageTypeMap=new HashMap<String, CapitalizationContextUsage>();
|
||||
contextUsageTypeMap.put("month-format-except-narrow", CapitalizationContextUsage.MONTH_FORMAT);
|
||||
contextUsageTypeMap.put("month-standalone-except-narrow", CapitalizationContextUsage.MONTH_STANDALONE);
|
||||
contextUsageTypeMap.put("month-narrow", CapitalizationContextUsage.MONTH_NARROW);
|
||||
contextUsageTypeMap.put("day-format-except-narrow", CapitalizationContextUsage.DAY_FORMAT);
|
||||
contextUsageTypeMap.put("day-standalone-except-narrow", CapitalizationContextUsage.DAY_STANDALONE);
|
||||
contextUsageTypeMap.put("day-narrow", CapitalizationContextUsage.DAY_NARROW);
|
||||
contextUsageTypeMap.put("era-name", CapitalizationContextUsage.ERA_WIDE);
|
||||
contextUsageTypeMap.put("era-abbr", CapitalizationContextUsage.ERA_ABBREV);
|
||||
contextUsageTypeMap.put("era-narrow", CapitalizationContextUsage.ERA_NARROW);
|
||||
contextUsageTypeMap.put("zone-long", CapitalizationContextUsage.ZONE_LONG);
|
||||
contextUsageTypeMap.put("zone-short", CapitalizationContextUsage.ZONE_SHORT);
|
||||
contextUsageTypeMap.put("metazone-long", CapitalizationContextUsage.METAZONE_LONG);
|
||||
contextUsageTypeMap.put("metazone-short", CapitalizationContextUsage.METAZONE_SHORT);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @serial
|
||||
*/
|
||||
Map<CapitalizationContextUsage,boolean[]> capitalization = null;
|
||||
|
||||
/**
|
||||
* Returns era strings. For example: "AD" and "BC".
|
||||
@ -1134,6 +1186,8 @@ public class DateFormatSymbols implements Serializable, Cloneable {
|
||||
|
||||
this.zoneStrings = dfs.zoneStrings; // always null at initialization time for now
|
||||
this.localPatternChars = dfs.localPatternChars;
|
||||
|
||||
this.capitalization = dfs.capitalization;
|
||||
|
||||
this.actualLocale = dfs.actualLocale;
|
||||
this.validLocale = dfs.validLocale;
|
||||
@ -1249,7 +1303,7 @@ public class DateFormatSymbols implements Serializable, Cloneable {
|
||||
if (cyclicNameSetsBundle != null) {
|
||||
shortYearNames = calData.get("cyclicNameSets", "years", "format", "abbreviated").getStringArray();
|
||||
}
|
||||
|
||||
|
||||
requestedLocale = desiredLocale;
|
||||
|
||||
ICUResourceBundle rb =
|
||||
@ -1266,6 +1320,39 @@ public class DateFormatSymbols implements Serializable, Cloneable {
|
||||
// TODO: obtain correct actual/valid locale later
|
||||
ULocale uloc = rb.getULocale();
|
||||
setLocale(uloc, uloc);
|
||||
|
||||
capitalization = new HashMap<CapitalizationContextUsage,boolean[]>();
|
||||
boolean[] noTransforms = new boolean[2];
|
||||
noTransforms[0] = false;
|
||||
noTransforms[1] = false;
|
||||
CapitalizationContextUsage allUsages[] = CapitalizationContextUsage.values();
|
||||
for (CapitalizationContextUsage usage: allUsages) {
|
||||
capitalization.put(usage, noTransforms);
|
||||
}
|
||||
UResourceBundle contextTransformsBundle = null;
|
||||
try {
|
||||
contextTransformsBundle = (UResourceBundle)rb.getWithFallback("contextTransforms");
|
||||
}
|
||||
catch (MissingResourceException e) {
|
||||
contextTransformsBundle = null; // probably redundant
|
||||
}
|
||||
if (contextTransformsBundle != null) {
|
||||
UResourceBundleIterator ctIterator = contextTransformsBundle.getIterator();
|
||||
while ( ctIterator.hasNext() ) {
|
||||
UResourceBundle contextTransformUsage = ctIterator.next();
|
||||
int[] intVector = contextTransformUsage.getIntVector();
|
||||
if (intVector.length >= 2) {
|
||||
String usageKey = contextTransformUsage.getKey();
|
||||
CapitalizationContextUsage usage = contextUsageTypeMap.get(usageKey);
|
||||
if (usage != null) {
|
||||
boolean[] transforms = new boolean[2];
|
||||
transforms[0] = (intVector[0] != 0);
|
||||
transforms[1] = (intVector[1] != 0);
|
||||
capitalization.put(usage, transforms);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final boolean arrayOfArrayEquals(Object[][] aa1, Object[][]aa2) {
|
||||
|
@ -20,6 +20,7 @@ import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.MissingResourceException;
|
||||
|
||||
import com.ibm.icu.impl.CalendarData;
|
||||
@ -375,6 +376,64 @@ public class SimpleDateFormat extends DateFormat {
|
||||
*/
|
||||
private volatile TimeZoneFormat tzFormat;
|
||||
|
||||
/*
|
||||
* Default capitalization context, introduced in ICU 49
|
||||
*/
|
||||
private ContextValue defaultCapitalizationContext;
|
||||
|
||||
/** Date format context types
|
||||
* @draft ICU 49
|
||||
*/
|
||||
public enum ContextType {
|
||||
/**
|
||||
* Type (key) for specifying the capitalization context for which a date
|
||||
* is to be formatted (possible values are in ContextValue).
|
||||
* @draft ICU 49
|
||||
*/
|
||||
CAPITALIZATION
|
||||
}
|
||||
|
||||
/** Values for date format context types
|
||||
* @draft ICU 49
|
||||
*/
|
||||
public enum ContextValue {
|
||||
/** Values for any ContextType (key) */
|
||||
/**
|
||||
* Value for any ContextType (such as CAPITALIZATION) if the
|
||||
* relevant context to be used in formatting a date is unknown (this is the
|
||||
* default value for any ContextType when no value has been
|
||||
* explicitly specified for that ContextType).
|
||||
* @draft ICU 49
|
||||
*/
|
||||
UNKNOWN,
|
||||
/** Values for context type (key) CAPITALIZATION */
|
||||
/**
|
||||
* CAPITALIZATION value if a date (or date symbol) is to be formatted
|
||||
* with capitalization appropriate for the middle of a sentence.
|
||||
* @draft ICU 49
|
||||
*/
|
||||
CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE,
|
||||
/**
|
||||
* CAPITALIZATION value if a date (or date symbol) is to be formatted
|
||||
* with capitalization appropriate for the beginning of a sentence.
|
||||
* @draft ICU 49
|
||||
*/
|
||||
CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE,
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
CAPITALIZATION_FOR_UI_LIST_OR_MENU,
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
CAPITALIZATION_FOR_STANDALONE
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a SimpleDateFormat using the default pattern for the default <code>FORMAT</code>
|
||||
* locale. <b>Note:</b> Not all locales support SimpleDateFormat; for full
|
||||
@ -541,6 +600,8 @@ public class SimpleDateFormat extends DateFormat {
|
||||
if (override != null) {
|
||||
initNumberFormatters(locale);
|
||||
}
|
||||
|
||||
defaultCapitalizationContext = ContextValue.UNKNOWN;
|
||||
|
||||
}
|
||||
|
||||
@ -693,6 +754,36 @@ public class SimpleDateFormat extends DateFormat {
|
||||
*/
|
||||
public StringBuffer format(Calendar cal, StringBuffer toAppendTo,
|
||||
FieldPosition pos) {
|
||||
return format(cal, null, toAppendTo, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a date or time, which is the standard millis
|
||||
* since January 1, 1970, 00:00:00 GMT.
|
||||
* <p>Example: using the US locale:
|
||||
* "yyyy.MM.dd G 'at' HH:mm:ss zzz" ->> 1996.07.10 AD at 15:08:56 PDT
|
||||
* @param cal the calendar whose date-time value is to be formatted into a date-time string
|
||||
* @param contextValues a list of DateFormatContextTypes (e.g. CAPITALIZATION) and
|
||||
* corresponding DateFormatContextValues (e.g. CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE)
|
||||
* which should override the formatter's default values just for this call (does not change
|
||||
* the default values). May be null, in which case the default values are used.
|
||||
* @param toAppendTo where the new date-time text is to be appended
|
||||
* @param pos the formatting position. On input: an alignment field,
|
||||
* if desired. On output: the offsets of the alignment field.
|
||||
* @return the formatted date-time string.
|
||||
* @see DateFormat
|
||||
* @draft ICU 49
|
||||
*/
|
||||
public StringBuffer format(Calendar cal,
|
||||
Map<ContextType,ContextValue> contextValues,
|
||||
StringBuffer toAppendTo, FieldPosition pos) {
|
||||
ContextValue capitalizationContext = defaultCapitalizationContext;
|
||||
if (contextValues != null ) {
|
||||
ContextValue newCapContextValue = contextValues.get(ContextType.CAPITALIZATION);
|
||||
if (newCapContextValue != null) {
|
||||
capitalizationContext = newCapContextValue;
|
||||
}
|
||||
}
|
||||
TimeZone backupTZ = null;
|
||||
if (cal != calendar && !cal.getType().equals(calendar.getType())) {
|
||||
// Different calendar type
|
||||
@ -703,7 +794,7 @@ public class SimpleDateFormat extends DateFormat {
|
||||
calendar.setTimeZone(cal.getTimeZone());
|
||||
cal = calendar;
|
||||
}
|
||||
StringBuffer result = format(cal, toAppendTo, pos, null);
|
||||
StringBuffer result = format(cal, capitalizationContext, toAppendTo, pos, null);
|
||||
if (backupTZ != null) {
|
||||
// Restore the original time zone
|
||||
calendar.setTimeZone(backupTZ);
|
||||
@ -713,8 +804,8 @@ public class SimpleDateFormat extends DateFormat {
|
||||
|
||||
// The actual method to format date. If List attributes is not null,
|
||||
// then attribute information will be recorded.
|
||||
private StringBuffer format(Calendar cal, StringBuffer toAppendTo,
|
||||
FieldPosition pos, List<FieldPosition> attributes) {
|
||||
private StringBuffer format(Calendar cal, ContextValue capitalizationContext,
|
||||
StringBuffer toAppendTo, FieldPosition pos, List<FieldPosition> attributes) {
|
||||
// Initialize
|
||||
pos.setBeginIndex(0);
|
||||
pos.setEndIndex(0);
|
||||
@ -735,10 +826,11 @@ public class SimpleDateFormat extends DateFormat {
|
||||
start = toAppendTo.length();
|
||||
}
|
||||
if (useFastFormat) {
|
||||
subFormat(toAppendTo, item.type, item.length, toAppendTo.length(), pos, cal);
|
||||
subFormat(toAppendTo, item.type, item.length, toAppendTo.length(),
|
||||
i, capitalizationContext, pos, cal);
|
||||
} else {
|
||||
toAppendTo.append(subFormat(item.type, item.length, toAppendTo.length(), pos,
|
||||
formatData, cal));
|
||||
toAppendTo.append(subFormat(item.type, item.length, toAppendTo.length(),
|
||||
i, capitalizationContext, pos, cal));
|
||||
}
|
||||
if (attributes != null) {
|
||||
// Check the sub format length
|
||||
@ -865,12 +957,27 @@ public class SimpleDateFormat extends DateFormat {
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
// Note: formatData is ignored
|
||||
return subFormat(ch, count, beginOffset, 0, ContextValue.UNKNOWN, pos, cal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a single field. This is the version called internally; it
|
||||
* adds fieldNum and capitalizationContext parameters.
|
||||
*
|
||||
* @internal
|
||||
* @deprecated This API is ICU internal only.
|
||||
*/
|
||||
protected String subFormat(char ch, int count, int beginOffset,
|
||||
int fieldNum, ContextValue capitalizationContext,
|
||||
FieldPosition pos,
|
||||
Calendar cal)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
subFormat(buf, ch, count, beginOffset, pos, cal);
|
||||
subFormat(buf, ch, count, beginOffset, fieldNum, capitalizationContext, pos, cal);
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Formats a single field; useFastFormat variant. Reuses a
|
||||
* StringBuffer for results instead of creating a String on the
|
||||
* heap for each call.
|
||||
@ -885,6 +992,7 @@ public class SimpleDateFormat extends DateFormat {
|
||||
@SuppressWarnings("fallthrough")
|
||||
protected void subFormat(StringBuffer buf,
|
||||
char ch, int count, int beginOffset,
|
||||
int fieldNum, ContextValue capitalizationContext,
|
||||
FieldPosition pos,
|
||||
Calendar cal) {
|
||||
|
||||
@ -914,6 +1022,7 @@ public class SimpleDateFormat extends DateFormat {
|
||||
int value = cal.get(field);
|
||||
|
||||
NumberFormat currentNumberFormat = getNumberFormat(ch);
|
||||
DateFormatSymbols.CapitalizationContextUsage capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.OTHER;
|
||||
|
||||
switch (patternCharIndex) {
|
||||
case 0: // 'G' - ERA
|
||||
@ -923,10 +1032,13 @@ public class SimpleDateFormat extends DateFormat {
|
||||
} else {
|
||||
if (count == 5) {
|
||||
safeAppend(formatData.narrowEras, value, buf);
|
||||
capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.ERA_NARROW;
|
||||
} else if (count == 4) {
|
||||
safeAppend(formatData.eraNames, value, buf);
|
||||
capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.ERA_WIDE;
|
||||
} else {
|
||||
safeAppend(formatData.eras, value, buf);
|
||||
capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.ERA_ABBREV;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -970,17 +1082,22 @@ public class SimpleDateFormat extends DateFormat {
|
||||
} else {
|
||||
safeAppendWithMonthPattern(formatData.standaloneNarrowMonths, value, buf, (isLeapMonth!=0)? formatData.leapMonthPatterns[DateFormatSymbols.DT_LEAP_MONTH_PATTERN_STANDALONE_NARROW]: null);
|
||||
}
|
||||
capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.MONTH_NARROW;
|
||||
} else if (count == 4) {
|
||||
if (patternCharIndex == 2) {
|
||||
safeAppendWithMonthPattern(formatData.months, value, buf, (isLeapMonth!=0)? formatData.leapMonthPatterns[DateFormatSymbols.DT_LEAP_MONTH_PATTERN_FORMAT_WIDE]: null);
|
||||
capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.MONTH_FORMAT;
|
||||
} else {
|
||||
safeAppendWithMonthPattern(formatData.standaloneMonths, value, buf, (isLeapMonth!=0)? formatData.leapMonthPatterns[DateFormatSymbols.DT_LEAP_MONTH_PATTERN_STANDALONE_WIDE]: null);
|
||||
capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.MONTH_STANDALONE;
|
||||
}
|
||||
} else if (count == 3) {
|
||||
if (patternCharIndex == 2) {
|
||||
safeAppendWithMonthPattern(formatData.shortMonths, value, buf, (isLeapMonth!=0)? formatData.leapMonthPatterns[DateFormatSymbols.DT_LEAP_MONTH_PATTERN_FORMAT_ABBREV]: null);
|
||||
capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.MONTH_FORMAT;
|
||||
} else {
|
||||
safeAppendWithMonthPattern(formatData.standaloneShortMonths, value, buf, (isLeapMonth!=0)? formatData.leapMonthPatterns[DateFormatSymbols.DT_LEAP_MONTH_PATTERN_STANDALONE_ABBREV]: null);
|
||||
capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.MONTH_STANDALONE;
|
||||
}
|
||||
} else {
|
||||
StringBuffer monthNumber = new StringBuffer();
|
||||
@ -1029,10 +1146,13 @@ public class SimpleDateFormat extends DateFormat {
|
||||
case 9: // 'E' - DAY_OF_WEEK
|
||||
if (count == 5) {
|
||||
safeAppend(formatData.narrowWeekdays, value, buf);
|
||||
capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.DAY_NARROW;
|
||||
} else if (count == 4) {
|
||||
safeAppend(formatData.weekdays, value, buf);
|
||||
capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.DAY_FORMAT;
|
||||
} else {// count <= 3, use abbreviated form if exists
|
||||
safeAppend(formatData.shortWeekdays, value, buf);
|
||||
capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.DAY_FORMAT;
|
||||
}
|
||||
break;
|
||||
case 14: // 'a' - AM_PM
|
||||
@ -1051,8 +1171,10 @@ public class SimpleDateFormat extends DateFormat {
|
||||
if (count < 4) {
|
||||
// "z", "zz", "zzz"
|
||||
result = tzFormat().format(Style.SPECIFIC_SHORT, tz, date);
|
||||
capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.METAZONE_SHORT;
|
||||
} else {
|
||||
result = tzFormat().format(Style.SPECIFIC_LONG, tz, date);
|
||||
capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.METAZONE_LONG;
|
||||
}
|
||||
buf.append(result);
|
||||
break;
|
||||
@ -1075,10 +1197,12 @@ public class SimpleDateFormat extends DateFormat {
|
||||
if (count == 1) {
|
||||
// "v"
|
||||
result = tzFormat().format(Style.GENERIC_SHORT, tz, date);
|
||||
capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.METAZONE_SHORT;
|
||||
} else if (count == 4) {
|
||||
// "vvvv"
|
||||
result = tzFormat().format(Style.GENERIC_LONG, tz, date);
|
||||
}
|
||||
capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.METAZONE_LONG;
|
||||
}
|
||||
buf.append(result);
|
||||
break;
|
||||
|
||||
@ -1092,10 +1216,13 @@ public class SimpleDateFormat extends DateFormat {
|
||||
value = cal.get(Calendar.DAY_OF_WEEK);
|
||||
if (count == 5) {
|
||||
safeAppend(formatData.standaloneNarrowWeekdays, value, buf);
|
||||
capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.DAY_NARROW;
|
||||
} else if (count == 4) {
|
||||
safeAppend(formatData.standaloneWeekdays, value, buf);
|
||||
capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.DAY_STANDALONE;
|
||||
} else { // count == 3
|
||||
safeAppend(formatData.standaloneShortWeekdays, value, buf);
|
||||
capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.DAY_STANDALONE;
|
||||
}
|
||||
break;
|
||||
case 27: // 'Q' - QUARTER
|
||||
@ -1120,9 +1247,11 @@ public class SimpleDateFormat extends DateFormat {
|
||||
if (count == 1) {
|
||||
// "V"
|
||||
result = tzFormat().format(Style.SPECIFIC_SHORT, tz, date);
|
||||
capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.METAZONE_SHORT;
|
||||
} else if (count == 4) {
|
||||
// "VVVV"
|
||||
result = tzFormat().format(Style.GENERIC_LOCATION, tz, date);
|
||||
capContextUsageType = DateFormatSymbols.CapitalizationContextUsage.ZONE_LONG;
|
||||
}
|
||||
buf.append(result);
|
||||
break;
|
||||
@ -1144,6 +1273,31 @@ public class SimpleDateFormat extends DateFormat {
|
||||
break;
|
||||
} // switch (patternCharIndex)
|
||||
|
||||
if (fieldNum == 0) {
|
||||
boolean titlecase = false;
|
||||
if (capitalizationContext != null) {
|
||||
switch (capitalizationContext) {
|
||||
case CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE:
|
||||
titlecase = true;
|
||||
break;
|
||||
case CAPITALIZATION_FOR_UI_LIST_OR_MENU:
|
||||
case CAPITALIZATION_FOR_STANDALONE:
|
||||
boolean[] transforms = formatData.capitalization.get(capContextUsageType);
|
||||
titlecase = (capitalizationContext==ContextValue.CAPITALIZATION_FOR_UI_LIST_OR_MENU)?
|
||||
transforms[0]: transforms[1];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (titlecase) {
|
||||
String firstField = buf.substring(bufstart); // bufstart or beginOffset, should be the same
|
||||
String firstFieldTitleCase = UCharacter.toTitleCase(locale, firstField, null,
|
||||
UCharacter.TITLECASE_NO_LOWERCASE | UCharacter.TITLECASE_NO_BREAK_ADJUSTMENT);
|
||||
buf.replace(bufstart, buf.length(), firstFieldTitleCase);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the FieldPosition (for the first occurrence only)
|
||||
if (pos.getBeginIndex() == pos.getEndIndex()) {
|
||||
if (pos.getField() == PATTERN_INDEX_TO_DATE_FORMAT_FIELD[patternCharIndex]) {
|
||||
@ -2503,7 +2657,7 @@ public class SimpleDateFormat extends DateFormat {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@icu} Allows you to set the time zoen formatter.
|
||||
* {@icu} Allows you to set the time zone formatter.
|
||||
*
|
||||
* @param tzfmt the new time zone formatter
|
||||
* @draft ICU 49
|
||||
@ -2519,6 +2673,33 @@ public class SimpleDateFormat extends DateFormat {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@icu} Set the formatter's default value for a particular context type,
|
||||
* such as 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.
|
||||
* @draft ICU 49
|
||||
*/
|
||||
public void setDefaultContext(ContextType type, ContextValue value) {
|
||||
if (type == ContextType.CAPITALIZATION && value != null) {
|
||||
defaultCapitalizationContext = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@icu} Get the formatter's default value for a particular context type,
|
||||
* such as CAPITALIZATION.
|
||||
*
|
||||
* @param type The context type for which the default value should be obtained.
|
||||
* @return The current default value for the specified context type.
|
||||
* @draft ICU 49
|
||||
*/
|
||||
public ContextValue getDefaultContext(ContextType type) {
|
||||
return (type == ContextType.CAPITALIZATION && defaultCapitalizationContext != null)?
|
||||
defaultCapitalizationContext: ContextValue.UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides Cloneable
|
||||
* @stable ICU 2.0
|
||||
@ -2617,7 +2798,7 @@ public class SimpleDateFormat extends DateFormat {
|
||||
StringBuffer toAppendTo = new StringBuffer();
|
||||
FieldPosition pos = new FieldPosition(0);
|
||||
List<FieldPosition> attributes = new ArrayList<FieldPosition>();
|
||||
format(cal, toAppendTo, pos, attributes);
|
||||
format(cal, defaultCapitalizationContext, toAppendTo, pos, attributes);
|
||||
|
||||
AttributedString as = new AttributedString(toAppendTo.toString());
|
||||
|
||||
@ -2845,11 +3026,11 @@ public class SimpleDateFormat extends DateFormat {
|
||||
} else {
|
||||
PatternItem item = (PatternItem)items[i];
|
||||
if (useFastFormat) {
|
||||
subFormat(appendTo, item.type, item.length, appendTo.length(), pos,
|
||||
fromCalendar);
|
||||
subFormat(appendTo, item.type, item.length, appendTo.length(),
|
||||
i, defaultCapitalizationContext, pos, fromCalendar);
|
||||
} else {
|
||||
appendTo.append(subFormat(item.type, item.length, appendTo.length(), pos,
|
||||
formatData, fromCalendar));
|
||||
appendTo.append(subFormat(item.type, item.length, appendTo.length(),
|
||||
i, defaultCapitalizationContext, pos, fromCalendar));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2863,10 +3044,11 @@ public class SimpleDateFormat extends DateFormat {
|
||||
} else {
|
||||
PatternItem item = (PatternItem)items[i];
|
||||
if (useFastFormat) {
|
||||
subFormat(appendTo, item.type, item.length, appendTo.length(), pos, toCalendar);
|
||||
subFormat(appendTo, item.type, item.length, appendTo.length(),
|
||||
i, defaultCapitalizationContext, pos, toCalendar);
|
||||
} else {
|
||||
appendTo.append(subFormat(item.type, item.length, appendTo.length(), pos,
|
||||
formatData, toCalendar));
|
||||
appendTo.append(subFormat(item.type, item.length, appendTo.length(),
|
||||
i, defaultCapitalizationContext, pos, toCalendar));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import java.text.ParseException;
|
||||
import java.text.ParsePosition;
|
||||
import java.util.Date;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
@ -4022,6 +4023,68 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
|
||||
errln("FAIL: Unexpected result in two digit WOY parse. Expected 2098, got " + result);
|
||||
}
|
||||
}
|
||||
|
||||
public void TestContext() {
|
||||
class TestContextItem {
|
||||
public String locale;
|
||||
public String pattern;
|
||||
public SimpleDateFormat.ContextValue capitalizationContext;
|
||||
public String expectedFormat;
|
||||
// Simple constructor
|
||||
public TestContextItem(String loc, String pat, SimpleDateFormat.ContextValue capCtxt, String expFmt) {
|
||||
locale = loc;
|
||||
pattern = pat;
|
||||
capitalizationContext = capCtxt;
|
||||
expectedFormat = expFmt;
|
||||
}
|
||||
};
|
||||
final TestContextItem[] items = {
|
||||
new TestContextItem( "fr", "MMMM y", SimpleDateFormat.ContextValue.UNKNOWN, "juillet 2008" ),
|
||||
new TestContextItem( "fr", "MMMM y", SimpleDateFormat.ContextValue.CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, "juillet 2008" ),
|
||||
new TestContextItem( "fr", "MMMM y", SimpleDateFormat.ContextValue.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, "Juillet 2008" ),
|
||||
new TestContextItem( "fr", "MMMM y", SimpleDateFormat.ContextValue.CAPITALIZATION_FOR_UI_LIST_OR_MENU, "juillet 2008" ),
|
||||
new TestContextItem( "fr", "MMMM y", SimpleDateFormat.ContextValue.CAPITALIZATION_FOR_STANDALONE, "Juillet 2008" ),
|
||||
new TestContextItem( "cs", "LLLL y", SimpleDateFormat.ContextValue.UNKNOWN, "\u010Dervenec 2008" ),
|
||||
new TestContextItem( "cs", "LLLL y", SimpleDateFormat.ContextValue.CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, "\u010Dervenec 2008" ),
|
||||
new TestContextItem( "cs", "LLLL y", SimpleDateFormat.ContextValue.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, "\u010Cervenec 2008" ),
|
||||
new TestContextItem( "cs", "LLLL y", SimpleDateFormat.ContextValue.CAPITALIZATION_FOR_UI_LIST_OR_MENU, "\u010Cervenec 2008" ),
|
||||
new TestContextItem( "cs", "LLLL y", SimpleDateFormat.ContextValue.CAPITALIZATION_FOR_STANDALONE, "\u010Dervenec 2008" ),
|
||||
};
|
||||
Calendar cal = new GregorianCalendar(2008, Calendar.JULY, 2);
|
||||
for (TestContextItem item: items) {
|
||||
ULocale locale = new ULocale(item.locale);
|
||||
SimpleDateFormat sdfmt = new SimpleDateFormat(item.pattern, locale);
|
||||
|
||||
// first try with the format method that uses per-call values
|
||||
Map<SimpleDateFormat.ContextType,SimpleDateFormat.ContextValue> contextValues =
|
||||
new HashMap<SimpleDateFormat.ContextType,SimpleDateFormat.ContextValue>();
|
||||
contextValues.put(SimpleDateFormat.ContextType.CAPITALIZATION, item.capitalizationContext);
|
||||
StringBuffer result1 = new StringBuffer();
|
||||
FieldPosition fpos1 = new FieldPosition(0);
|
||||
sdfmt.format(cal, contextValues, result1, fpos1);
|
||||
if (result1.toString().compareTo(item.expectedFormat) != 0) {
|
||||
errln("FAIL: format (per-call context) for locale " + item.locale + ", capitalizationContext " + item.capitalizationContext +
|
||||
", expected \"" + item.expectedFormat + "\", got \"" + result1 + "\"");
|
||||
}
|
||||
|
||||
// now try setting default context & standard format call
|
||||
sdfmt.setDefaultContext(SimpleDateFormat.ContextType.CAPITALIZATION, item.capitalizationContext);
|
||||
StringBuffer result2 = new StringBuffer();
|
||||
FieldPosition fpos2 = new FieldPosition(0);
|
||||
sdfmt.format(cal, result2, fpos2);
|
||||
if (result2.toString().compareTo(item.expectedFormat) != 0) {
|
||||
errln("FAIL: format (default context) for locale " + item.locale + ", capitalizationContext " + item.capitalizationContext +
|
||||
", expected \"" + item.expectedFormat + "\", got \"" + result2 + "\"");
|
||||
}
|
||||
|
||||
// now read back default context, make sure it is what we set
|
||||
SimpleDateFormat.ContextValue capitalizationContext = sdfmt.getDefaultContext(SimpleDateFormat.ContextType.CAPITALIZATION);
|
||||
if (capitalizationContext != item.capitalizationContext) {
|
||||
errln("FAIL: getDefaultContext for locale " + item.locale + ", capitalizationContext " + item.capitalizationContext +
|
||||
", but got context " + capitalizationContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user