import java.util.List;
import com.ibm.icu.impl.Grego;
+import com.ibm.icu.util.Currency.CurrencyUsage;
/**
* Provides information about currencies that is not specific to a locale.
/**
* Returns the CurrencyDigits for the currency code.
+ * This is equivalent to currencyDigits(isoCode, CurrencyUsage.STANDARD);
* @param isoCode the currency code
* @return the CurrencyDigits
* @stable ICU 4.4
*/
public CurrencyDigits currencyDigits(String isoCode) {
+ return currencyDigits(isoCode, CurrencyUsage.STANDARD);
+ }
+
+ /**
+ * Returns the CurrencyDigits for the currency code with Context Usage.
+ * @param isoCode the currency code
+ * @param currencyUsage the currency usage
+ * @return the CurrencyDigits
+ * @draft ICU 54
+ * @provisional This API might change or be removed in a future release.
+ */
+ public CurrencyDigits currencyDigits(String isoCode, CurrencyUsage currencyUsage) {
return defaultDigits;
}
import com.ibm.icu.math.MathContext;
import com.ibm.icu.text.PluralRules.FixedDecimal;
import com.ibm.icu.util.Currency;
+import com.ibm.icu.util.Currency.CurrencyUsage;
import com.ibm.icu.util.CurrencyAmount;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.ULocale.Category;
0xFB29, 0xFB29,
0xFE62, 0xFE62,
0xFF0B, 0xFF0B).freeze();
-
+
// equivalent grouping and decimal support
static final boolean skipExtendedSeparatorParsing = ICUConfig.get(
"com.ibm.icu.text.DecimalFormat.SkipExtendedSeparatorParsing", "false")
other.currencyPluralInfo = (CurrencyPluralInfo) currencyPluralInfo.clone();
}
other.attributes = new ArrayList<FieldPosition>(); // #9240
+ other.currencyUsage = currencyUsage;
// TODO: We need to figure out whether we share a single copy of DigitList by
// multiple cloned copies. format/subformat are designed to use a single
&& (!useSignificantDigits || minSignificantDigits == other.minSignificantDigits
&& maxSignificantDigits == other.maxSignificantDigits)
&& symbols.equals(other.symbols)
- && Utility.objectEquals(currencyPluralInfo, other.currencyPluralInfo);
+ && Utility.objectEquals(currencyPluralInfo, other.currencyPluralInfo)
+ && currencyUsage.equals(other.currencyUsage);
}
// method to unquote the strings and compare
// by the currency
Currency theCurrency = getCurrency();
if (theCurrency != null) {
- setRoundingIncrement(theCurrency.getRoundingIncrement());
- int d = theCurrency.getDefaultFractionDigits();
+ setRoundingIncrement(theCurrency.getRoundingIncrement(currencyUsage));
+ int d = theCurrency.getDefaultFractionDigits(currencyUsage);
setMinimumFractionDigits(d);
_setMaximumFractionDigits(d);
}
if (currencySignCount != CURRENCY_SIGN_COUNT_ZERO) {
if (theCurrency != null) {
- setRoundingIncrement(theCurrency.getRoundingIncrement());
- int d = theCurrency.getDefaultFractionDigits();
+ setRoundingIncrement(theCurrency.getRoundingIncrement(currencyUsage));
+ int d = theCurrency.getDefaultFractionDigits(currencyUsage);
setMinimumFractionDigits(d);
setMaximumFractionDigits(d);
}
}
}
}
+
+ /**
+ * Sets the <tt>Currency Usage</tt> object used to display currency.
+ * This takes effect immediately, if this format is a
+ * currency format.
+ * @param newUsage new currency context object to use.
+ * @draft ICU 54
+ * @provisional This API might change or be removed in a future release.
+ */
+ public void setCurrencyUsage(CurrencyUsage newUsage) {
+ if (newUsage == null) {
+ throw new NullPointerException("return value is null at method AAA");
+ }
+ currencyUsage = newUsage;
+ Currency theCurrency = this.getCurrency();
+
+ // We set rounding/digit based on currency context
+ if (theCurrency != null) {
+ setRoundingIncrement(theCurrency.getRoundingIncrement(currencyUsage));
+ int d = theCurrency.getDefaultFractionDigits(currencyUsage);
+ setMinimumFractionDigits(d);
+ _setMaximumFractionDigits(d);
+ }
+ }
+ /**
+ * Returns the <tt>Currency Usage</tt> object used to display currency
+ * @draft ICU 54
+ * @provisional This API might change or be removed in a future release.
+ */
+ public CurrencyUsage getCurrencyUsage() {
+ return currencyUsage;
+ }
+
/**
* Returns the currency in effect for this formatter. Subclasses should override this
* method as needed. Unlike getCurrency(), this method should never return null.
// the DecimalFormatSymbols object.
setCurrencyForSymbols();
}
+ if (serialVersionOnStream < 4) {
+ currencyUsage = CurrencyUsage.STANDARD;
+ }
serialVersionOnStream = currentSerialVersion;
digitList = new DigitList();
*/
private boolean parseBigDecimal = false;
+ /**
+ * The currency usage for the NumberFormat(standard or cash usage).
+ * It is used as STANDARD by default
+ * @since ICU 54
+ */
+ private CurrencyUsage currencyUsage = CurrencyUsage.STANDARD;
+
// ----------------------------------------------------------------------
- static final int currentSerialVersion = 3;
+ static final int currentSerialVersion = 4;
/**
* The internal serial version which says which version was written Possible values
*
* <li><b>3</b>: ICU 2.2. Adds currency object.
*
+ * <li><b>4</b>: ICU 54. Adds currency usage(standard vs cash)
+ *
* </ul>
*
* @serial
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.util.Currency;
+import com.ibm.icu.util.Currency.CurrencyUsage;
import com.ibm.icu.util.CurrencyAmount;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.ULocale.Category;
* @provisional This API might change or be removed in a future release.
*/
public static final int ACCOUNTINGCURRENCYSTYLE = 7;
+ /**
+ * {@icu} Constant to specify currency cash style of format which uses currency
+ * ISO code to represent currency, for example: "NT$3" instead of "NT$3.23".
+ * @draft ICU 54
+ * @provisional This API might change or be removed in a future release.
+ */
+ public static final int CASHCURRENCYSTYLE = 8;
+ /**
/**
* Field constant used to construct a FieldPosition object. Signifies that
* @stable ICU 2.0
*/
public static final int FRACTION_FIELD = 1;
-
+
/**
* Formats a number and appends the resulting text to the given string buffer.
* {@icunote} recognizes <code>BigInteger</code>
public Currency getCurrency() {
return currency;
}
-
+
/**
* Returns the currency in effect for this formatter. Subclasses
* should override this method as needed. Unlike getCurrency(),
* @stable ICU 4.2
*/
public static NumberFormat getInstance(ULocale desiredLocale, int choice) {
- if (choice < NUMBERSTYLE || choice > ACCOUNTINGCURRENCYSTYLE) {
+ if (choice < NUMBERSTYLE || choice > CASHCURRENCYSTYLE) {
throw new IllegalArgumentException(
"choice should be from NUMBERSTYLE to PLURALCURRENCYSTYLE");
}
// This style wont work for currency plural format.
// For currency plural format, the pattern is get from
// the locale (from CurrencyUnitPatterns) without override.
- if(choice == CURRENCYSTYLE || choice == ISOCURRENCYSTYLE || choice == ACCOUNTINGCURRENCYSTYLE){
+ if (choice == CURRENCYSTYLE || choice == ISOCURRENCYSTYLE || choice == ACCOUNTINGCURRENCYSTYLE
+ || choice == CASHCURRENCYSTYLE) {
String temp = symbols.getCurrencyPattern();
if(temp!=null){
pattern = temp;
f.setDecimalSeparatorAlwaysShown(false);
f.setParseIntegerOnly(true);
}
+
+ if (choice == CASHCURRENCYSTYLE) {
+ f.setCurrencyUsage(CurrencyUsage.CASH);
+ }
format = f;
}
// TODO: the actual locale of the *pattern* may differ from that
patternKey = "decimalFormat";
break;
case CURRENCYSTYLE:
+ case CASHCURRENCYSTYLE:
case ISOCURRENCYSTYLE:
case PLURALCURRENCYSTYLE:
patternKey = "currencyFormat";
.add("\u20a8", "\u20b9")
.add("\u00a3", "\u20a4");
+ /**
+ * Currency Usage used for Decimal Format
+ * @draft ICU 54
+ * @provisional This API might change or be removed in a future release.
+ */
+ public enum CurrencyUsage{
+ /**
+ * a setting to specify currency usage which determines currency digit and rounding
+ * for standard usage, for example: "50.00 NT$"
+ * @draft ICU 54
+ * @provisional This API might change or be removed in a future release.
+ */
+ STANDARD,
+
+ /**
+ * a setting to specify currency usage which determines currency digit and rounding
+ * for cash usage, for example: "50 NT$"
+ * @draft ICU 54
+ * @provisional This API might change or be removed in a future release.
+ */
+ CASH
+ }
+
// begin registry stuff
// shim for service code
/**
* Returns the number of the number of fraction digits that should
* be displayed for this currency.
+ * This is equivalent to getDefaultFractionDigits(CurrencyUsage.STANDARD);
* @return a non-negative number of fraction digits to be
* displayed
* @stable ICU 2.2
*/
public int getDefaultFractionDigits() {
+ return getDefaultFractionDigits(CurrencyUsage.STANDARD);
+ }
+
+ /**
+ * Returns the number of the number of fraction digits that should
+ * be displayed for this currency with Usage.
+ * @param Usage the usage of currency(Standard or Cash)
+ * @return a non-negative number of fraction digits to be
+ * displayed
+ * @draft ICU 54
+ * @provisional This API might change or be removed in a future release.
+ */
+ public int getDefaultFractionDigits(CurrencyUsage Usage) {
CurrencyMetaInfo info = CurrencyMetaInfo.getInstance();
- CurrencyDigits digits = info.currencyDigits(subType);
+ CurrencyDigits digits = info.currencyDigits(subType, Usage);
return digits.fractionDigits;
}
/**
* Returns the rounding increment for this currency, or 0.0 if no
* rounding is done by this currency.
+ * This is equivalent to getRoundingIncrement(CurrencyUsage.STANDARD);
* @return the non-negative rounding increment, or 0.0 if none
* @stable ICU 2.2
*/
public double getRoundingIncrement() {
+ return getRoundingIncrement(CurrencyUsage.STANDARD);
+ }
+
+ /**
+ * Returns the rounding increment for this currency, or 0.0 if no
+ * rounding is done by this currency with the Usage.
+ * @param Usage the usage of currency(Standard or Cash)
+ * @return the non-negative rounding increment, or 0.0 if none
+ * @draft ICU 54
+ * @provisional This API might change or be removed in a future release.
+ */
+ public double getRoundingIncrement(CurrencyUsage Usage) {
CurrencyMetaInfo info = CurrencyMetaInfo.getInstance();
- CurrencyDigits digits = info.currencyDigits(subType);
+ CurrencyDigits digits = info.currencyDigits(subType, Usage);
int data1 = digits.roundingIncrement;
return 0.0;
}
- // Return data[1] / 10^(data[0]). The only actual rounding data,
+ // Return data[1] / 10^(data[0]). The only actual rounding data,
// as of this writing, is CHF { 2, 25 }.
return (double) data1 / POW10[data0];
}
import java.util.Set;
import com.ibm.icu.text.CurrencyMetaInfo;
+import com.ibm.icu.util.Currency.CurrencyUsage;
/**
* ICU's currency meta info data.
@Override
public CurrencyDigits currencyDigits(String isoCode) {
+ return currencyDigits(isoCode, CurrencyUsage.STANDARD);
+ }
+
+ @Override
+ public CurrencyDigits currencyDigits(String isoCode, CurrencyUsage currencyPurpose) {
ICUResourceBundle b = digitInfo.findWithFallback(isoCode);
if (b == null) {
b = digitInfo.findWithFallback("DEFAULT");
}
int[] data = b.getIntVector();
- return new CurrencyDigits(data[0], data[1]);
+ if (currencyPurpose == CurrencyUsage.CASH) {
+ return new CurrencyDigits(data[2], data[3]);
+ } else if (currencyPurpose == CurrencyUsage.STANDARD) {
+ return new CurrencyDigits(data[0], data[1]);
+ } else {
+ return new CurrencyDigits(data[0], data[1]);
+ }
}
-
+
private <T> List<T> collect(Collector<T> collector, CurrencyFilter filter) {
// We rely on the fact that the data lists the regions in order, and the
// priorities in order within region. This means we don't need
*/
public void TestGetInstance() {
// Tests "public final static NumberFormat getInstance(int style)"
- int maxStyle = NumberFormat.ACCOUNTINGCURRENCYSTYLE;
+ int maxStyle = NumberFormat.CASHCURRENCYSTYLE;
int[] invalid_cases = { NumberFormat.NUMBERSTYLE - 1, NumberFormat.NUMBERSTYLE - 2,
maxStyle + 1, maxStyle + 2 };
expect(acfmt, num, fmt, rt);
}
}
+
+ public void TestCurrencyUsage() {
+ // the 1st one is checking setter/getter, while the 2nd one checks for getInstance
+ // compare the Currency and Currency Cash Digits
+ for (int i = 0; i < 2; i++) {
+ String original_expected = "NT$123.57";
+ DecimalFormat custom = null;
+ if (i == 0) {
+ custom = (DecimalFormat) DecimalFormat.getInstance(new ULocale("en_US@currency=TWD"),
+ DecimalFormat.CURRENCYSTYLE);
+
+ String original = custom.format(123.567);
+ assertEquals("Test Currency Context", original_expected, original);
+
+ // test the getter
+ assertEquals("Test Currency Context Purpose", custom.getCurrencyUsage(),
+ Currency.CurrencyUsage.STANDARD);
+ custom.setCurrencyUsage(Currency.CurrencyUsage.CASH);
+ assertEquals("Test Currency Context Purpose", custom.getCurrencyUsage(), Currency.CurrencyUsage.CASH);
+ } else {
+ custom = (DecimalFormat) DecimalFormat.getInstance(new ULocale("en_US@currency=TWD"),
+ DecimalFormat.CASHCURRENCYSTYLE);
+
+ // test the getter
+ assertEquals("Test Currency Context Purpose", custom.getCurrencyUsage(), Currency.CurrencyUsage.CASH);
+ }
+
+ String cash_currency = custom.format(123.567);
+ String cash_currency_expected = "NT$124";
+ assertEquals("Test Currency Context", cash_currency_expected, cash_currency);
+ }
+
+ // the 1st one is checking setter/getter, while the 2nd one checks for getInstance
+ // compare the Currency and Currency Cash Rounding
+ for (int i = 0; i < 2; i++) {
+ String original_rounding_expected = "CA$123.57";
+ DecimalFormat fmt = null;
+ if (i == 0) {
+ fmt = (DecimalFormat) DecimalFormat.getInstance(new ULocale("en_US@currency=CAD"),
+ DecimalFormat.CURRENCYSTYLE);
+
+ String original_rounding = fmt.format(123.566);
+ assertEquals("Test Currency Context", original_rounding_expected, original_rounding);
+
+ fmt.setCurrencyUsage(Currency.CurrencyUsage.CASH);
+ } else {
+ fmt = (DecimalFormat) DecimalFormat.getInstance(new ULocale("en_US@currency=CAD"),
+ DecimalFormat.CASHCURRENCYSTYLE);
+ }
+
+ String cash_rounding_currency = fmt.format(123.567);
+ String cash__rounding_currency_expected = "CA$123.55";
+ assertEquals("Test Currency Context", cash__rounding_currency_expected, cash_rounding_currency);
+ }
+
+ // the 1st one is checking setter/getter, while the 2nd one checks for getInstance
+ // Test the currency change
+ for (int i = 0; i < 2; i++) {
+ DecimalFormat fmt2 = null;
+ if (i == 1) {
+ fmt2 = (DecimalFormat) NumberFormat.getInstance(new ULocale("en_US@currency=JPY"),
+ NumberFormat.CURRENCYSTYLE);
+ fmt2.setCurrencyUsage(Currency.CurrencyUsage.CASH);
+ } else {
+ fmt2 = (DecimalFormat) NumberFormat.getInstance(new ULocale("en_US@currency=JPY"),
+ NumberFormat.CASHCURRENCYSTYLE);
+ }
+
+ fmt2.setCurrency(Currency.getInstance("TWD"));
+ String TWD_changed = fmt2.format(123.567);
+ String TWD_changed_expected = "NT$124";
+ assertEquals("Test Currency Context", TWD_changed_expected, TWD_changed);
+ }
+ }
}