Reputation: 32113
How can I get a NumberFormat
(or DecimalFormat
) instance corresponding to an ISO 4217 currency code (such as "EUR" or "USD") in order to format prices correctly?
Note 1: The problem I'm having is that the
NumberFormat
/DecimalFormat
classes have agetCurrencyInstance(Locale locale)
method but I can't figure out how to get to aLocale
object from an ISO 4217 currency code.Note 2: There is also a
java.util.Currency
class which has agetInstance(String currencyCode)
method (returning theCurrency
instance for a given ISO 4217 currency code) but again I can't figure out how to get from aCurrency
object to aNumberFormat
instance...
Upvotes: 24
Views: 34318
Reputation: 420
public class PriceHelper {
public static String formatPrice(Context context, String currencyCode,
double price) {
if (price == 0) {
return context.getString(R.string.free);
}
Currency currency = Currency.getInstance(currencyCode);
NumberFormat format = NumberFormat.getCurrencyInstance();
format.setCurrency(currency);
return format.format(price);
}
}
Upvotes: 1
Reputation: 8441
For completeness, though I've never used it, you might want to give Joda Money a try. If it's as good as Joda-Time, it probably is easier and more powerful than the standard JDK stuff.
Upvotes: 2
Reputation: 36703
The mapping is sometimes one to many... Like the euro is used in many countries (locales)...
Just because the currency code is the same the format might be different as this example shows:
private static Collection<Locale> getLocalesFromIso4217(String iso4217code) {
Collection<Locale> returnValue = new LinkedList<Locale>();
for (Locale locale : NumberFormat.getAvailableLocales()) {
String code = NumberFormat.getCurrencyInstance(locale).
getCurrency().getCurrencyCode();
if (iso4217code.equals(code)) {
returnValue.add(locale);
}
}
return returnValue;
}
public static void main(String[] args) {
System.out.println(getLocalesFromIso4217("USD"));
System.out.println(getLocalesFromIso4217("EUR"));
for (Locale locale : getLocalesFromIso4217("EUR")) {
System.out.println(locale + "=>" + NumberFormat.getCurrencyInstance(locale).format(1234));
}
}
Output
[en_US, es_US, es_EC, es_PR]
[pt_PT, el_CY, fi_FI, en_MT, sl_SI, ga_IE, fr_BE, es_ES, de_AT, nl_NL, el_GR, it_IT, en_IE, fr_LU, nl_BE, ca_ES, sr_ME, mt_MT, fr_FR, de_DE, de_LU]
pt_PT=>1.234,00 €
el_CY=>€1.234,00
fi_FI=>1 234,00 €
en_MT=>€1,234.00
sl_SI=>€ 1.234
ga_IE=>€1,234.00
fr_BE=>1.234,00 €
es_ES=>1.234,00 €
de_AT=>€ 1.234,00
nl_NL=>€ 1.234,00
el_GR=>1.234,00 €
it_IT=>€ 1.234,00
en_IE=>€1,234.00
fr_LU=>1 234,00 €
nl_BE=>1.234,00 €
ca_ES=>€ 1.234,00
sr_ME=>€ 1.234,00
mt_MT=>€1,234.00
fr_FR=>1 234,00 €
de_DE=>1.234,00 €
de_LU=>1.234,00 €
Upvotes: 6
Reputation: 8441
Locale can be used both to get the standard currency for the Locale and to print any currency symbol properly in the locale you specify. These are two distinct operations, and not really related.
From the Java Internationalization tutorial, you first get an instance of the Currency using either the Locale or the ISO code. Then you can print the symbol using another Locale. So if you get the US Currency from the en_US Locale, and call getSymbol() it will print "$". But if you call getSymbol(Locale) with the British Locale, it will print "USD".
So if you don't care what your current user's locale is, and you just care about the currencies, then you can ignore the Locale in all cases.
If you care about representing the currency symbol correctly based on your current user, then you need to get the Locale of the user specific to the user's location.
Upvotes: 6
Reputation: 7961
Try the following method:
private static NumberFormat getNumberFormat(String currencyCode)
{
Currency currency = Currency.getInstance(currencyCode);
Locale[] locales = NumberFormat.getAvailableLocales();
for (Locale locale : locales)
{
NumberFormat numberFormat = NumberFormat.getCurrencyInstance(locale);
if (numberFormat.getCurrency() == currency)
return numberFormat;
}
return null;
}
Upvotes: 1
Reputation: 16035
I'm not sure I understood this correctly, but you could try something like:
public class CurrencyTest
{
@Test
public void testGetNumberFormatForCurrencyCode()
{
NumberFormat format = NumberFormat.getInstance();
format.setMaximumFractionDigits(2);
Currency currency = Currency.getInstance("USD");
format.setCurrency(currency);
System.out.println(format.format(1234.23434));
}
}
Output:
1,234.23
Notice that I set the maximum amount of fractional digits separately, the NumberFormat.setCurrency doesn't touch the maximum amount of fractional digits:
Sets the currency used by this number format when formatting currency values. This does not update the minimum or maximum number of fraction digits used by the number format.
Upvotes: 25