ICU-9110 J -Add SimpleDateFormat methods for setting context, use context when formatting

X-SVN-Rev: 31482
This commit is contained in:
Peter Edberg 2012-02-22 08:26:12 +00:00
parent 4eac54f2f6
commit 331eea1d3f
3 changed files with 351 additions and 19 deletions

View File

@ -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) {

View File

@ -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));
}
}
}

View File

@ -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);
}
}
}
}