Adil Hussain
Adil Hussain

Reputation: 32113

How to get NumberFormat instance from currency code?

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 a getCurrencyInstance(Locale locale) method but I can't figure out how to get to a Locale object from an ISO 4217 currency code.

Note 2: There is also a java.util.Currency class which has a getInstance(String currencyCode) method (returning the Currency instance for a given ISO 4217 currency code) but again I can't figure out how to get from a Currency object to a NumberFormat instance...

Upvotes: 24

Views: 34318

Answers (6)

Shroud
Shroud

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

Spencer Kormos
Spencer Kormos

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

Adam
Adam

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

Spencer Kormos
Spencer Kormos

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

Bernard
Bernard

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

esaj
esaj

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

Related Questions