import java.util.List;
import java.util.Locale;
import java.util.MissingResourceException;
+import java.util.UUID;
import com.ibm.icu.impl.CalendarData;
import com.ibm.icu.impl.DateNumberFormat;
}
/**
- * Overrides superclass method
+ * Overrides superclass method and
+ * This method also clears per field NumberFormat instances
+ * previously set by {@link #setNumberFormat(String, NumberFormat)}
+ *
* @stable ICU 2.0
*/
public void setNumberFormat(NumberFormat newNumberFormat) {
super.setNumberFormat(newNumberFormat);
initLocalZeroPaddingNumberFormat();
initializeTimeZoneFormat(true);
+
+ if (numberFormatters != null) {
+ numberFormatters = null;
+ }
+ if (overrideMap != null) {
+ overrideMap = null;
+ }
}
private void initLocalZeroPaddingNumberFormat() {
}
/**
- * @internal
- * @deprecated This API is ICU internal only.
+ * allow the user to set the NumberFormat for several fields
+ * It can be a single field like: "y"(year) or "M"(month)
+ * It can be several field combined together: "yMd"(year, month and date)
+ * Note:
+ * 1 symbol field is enough for multiple symbol fields (so "y" will override "yy", "yyy")
+ * If the field is not numeric, then override has no effect (like "MMM" will use abbreviation, not numerical field)
+ *
+ * @param fields the fields to override
+ * @param overrideNF the NumbeferFormat used
+ * @exception IllegalArgumentException when the fields contain invalid field
+ * @draft ICU 54
+ * @provisional This API might change or be removed in a future release.
*/
- @Deprecated
- protected NumberFormat getNumberFormat(char ch) {
+ public void setNumberFormat(String fields, NumberFormat overrideNF) {
+ overrideNF.setGroupingUsed(false);
+ String nsName = "$" + UUID.randomUUID().toString();
+
+ // initialize mapping if not there
+ if (numberFormatters == null) {
+ numberFormatters = new HashMap<String, NumberFormat>();
+ }
+ if (overrideMap == null) {
+ overrideMap = new HashMap<Character, String>();
+ }
- Character ovrField;
- ovrField = Character.valueOf(ch);
- if (overrideMap != null && overrideMap.containsKey(ovrField)) {
- String nsName = overrideMap.get(ovrField).toString();
- NumberFormat nf = numberFormatters.get(nsName);
- return nf;
- } else {
- return numberFormat;
- }
+ // separate string into char and add to maps
+ for (int i = 0; i < fields.length(); i++) {
+ char field = fields.charAt(i);
+ if (DateFormatSymbols.patternChars.indexOf(field) == -1) {
+ throw new IllegalArgumentException("Illegal field character " + "'" + field + "' in setNumberFormat.");
+ }
+ overrideMap.put(field, nsName);
+ numberFormatters.put(nsName, overrideNF);
+ }
+
+ // Since one or more of the override number formatters might be complex,
+ // we can't rely on the fast numfmt where we have a partial field override.
+ useLocalZeroPaddingNumberFormat = false;
+ }
+
+ /**
+ * give the NumberFormat used for the field like 'y'(year) and 'M'(year)
+ *
+ * @param field the field the user wants
+ * @return override NumberFormat used for the field
+ * @draft ICU 54
+ * @provisional This API might change or be removed in a future release.
+ */
+ public NumberFormat getNumberFormat(char field) {
+ Character ovrField;
+ ovrField = Character.valueOf(field);
+ if (overrideMap != null && overrideMap.containsKey(ovrField)) {
+ String nsName = overrideMap.get(ovrField).toString();
+ NumberFormat nf = numberFormatters.get(nsName);
+ return nf;
+ } else {
+ return numberFormat;
+ }
}
private void initNumberFormatters(ULocale loc) {
useLocalZeroPaddingNumberFormat = false;
}
- if (!numberFormatters.containsKey(nsName)) {
+ if (!fullOverride && !numberFormatters.containsKey(nsName)) {
numberFormatters.put(nsName,nf);
}
errln("FAIL: parsed -> " + parsedate.toString() + " expected -> " + cal.toString());
}
}
+
+ public void TestOverrideNumberForamt() {
+ SimpleDateFormat fmt = new SimpleDateFormat("MM/dd/yy z");
+
+ // test override get/set NumberFormat
+ for (int i = 0; i < 100; i++) {
+ NumberFormat check_nf = NumberFormat.getInstance(new ULocale("en_US"));
+ fmt.setNumberFormat("y", check_nf);
+ NumberFormat get_nf = fmt.getNumberFormat('y');
+ if (!get_nf.equals(check_nf))
+ errln("FAIL: getter and setter do not work");
+ }
+
+ NumberFormat reused_nf = NumberFormat.getInstance(new ULocale("en_US"));
+ fmt.setNumberFormat("y", reused_nf);
+ fmt.setNumberFormat(reused_nf); // test the same override NF will not crash
+
+ // DATA[i][0] is to tell which field to set, DATA[i][1] is the expected result
+ String[][] DATA = {
+ { "", "\u521D\u516D \u5341\u4E94" },
+ { "M", "\u521D\u516D 15" },
+ { "Mo", "\u521D\u516D \u5341\u4E94" },
+ { "Md", "\u521D\u516D \u5341\u4E94" },
+ { "MdMMd", "\u521D\u516D \u5341\u4E94" },
+ { "mixed", "\u521D\u516D \u5341\u4E94" },
+ };
+
+ NumberFormat override = NumberFormat.getInstance(new ULocale("en@numbers=hanidays"));
+ Calendar cal = Calendar.getInstance();
+ cal.set(1997, Calendar.JUNE, 15);
+ Date test_date = cal.getTime();
+
+ for (int i = 0; i < DATA.length; i++) {
+ fmt = new SimpleDateFormat("MM d", new ULocale("en_US"));
+ String field = DATA[i][0];
+
+ if (field == "") { // use the one w/o field
+ fmt.setNumberFormat(override);
+ } else if (field == "mixed") { // set 1 field at first but then full override, both(M & d) should be override
+ NumberFormat single_override = NumberFormat.getInstance(new ULocale("en@numbers=hebr"));
+ fmt.setNumberFormat("M", single_override);
+ fmt.setNumberFormat(override);
+ } else if (field == "Mo") { // o is invalid field
+ try {
+ fmt.setNumberFormat(field, override);
+ } catch (IllegalArgumentException e) {
+ logln("IllegalArgumentException is thrown for invalid fields");
+ continue;
+ }
+ } else {
+ fmt.setNumberFormat(field, override);
+ }
+ String result = fmt.format(test_date);
+ String expected = DATA[i][1];
+
+ if (!result.equals(expected))
+ errln((String) "FAIL: -> " + result.toString() + " expected -> " + expected);
+ }
+ }
public void TestParsePosition() {
class ParseTestData {