48

I'm doing my best to find a way to format foreign currencies across various locales which are not default for that currency, using Java. I've found java.util.Currency, which can represent the proper symbol to use for various locales. That is, for USD, it provides me the symbol $ in the US, and US$ or USD in other nations. Also, I've found java.text.NumberFormat, which will format a currency for a specific locale. My problem - util.Currency will provide proper symbols and codes for representing currencies in their non-default locales, but will not format currency in any locale-specific way. NumberFormat assumes that the number I pass it, with a locale, is the currency of that locale, not a foreign currency.

For example, if I use getCurrencyInstance(Locale.GERMANY) and then format (1000) it assumes I am formatting 1000 euro. In reality, I may need the correct German-localized representation (correct decimal and thousands separator, whether to put the symbol before or after the amount) for USD, or Yen, or any other currency. The best I've been able to derive so far is to format a number using NumberFormat, then search the output for non-digit characters and replace them with symbols derived from util.Currency. However, this is very brittle, and probably not reliable enough for my purposes. Ideas? Any help is much appreciated.

JPittard
  • 645
  • 1
  • 5
  • 6
  • `1)` are you to display this data somewhere in the GUI, `2)` I never tried (ISO Ccy codes rellevant) then my question are you tried print_out symbol for USD, AUD, SGD maybe is there symbol $, `3)` I suggest to look for ISO codes rather that mixing and set different Locale, for example since out_dated http://www.oanda.com/help/currency-iso-code-country but first from google, – mKorbel Oct 19 '11 at 21:49
  • It's reasons related to this that you shouldn't store money in a primitive 'on-their-own': they should be part of a class that also contains the currency they represent (500 USD is _not_ 500 yen). – Clockwork-Muse Oct 19 '11 at 22:53
  • Did you see the answer I gave below? Does that solve the problem? – les2 Oct 20 '11 at 14:02

8 Answers8

62

Try using setCurrency on the instance returned by getCurrencyInstance(Locale.GERMANY)

Broken:

java.text.NumberFormat format = java.text.NumberFormat.getCurrencyInstance(java.util.Locale.GERMANY);
System.out.println(format.format(23));

Output: 23,00 €

Fixed:

java.util.Currency usd = java.util.Currency.getInstance("USD");
java.text.NumberFormat format = java.text.NumberFormat.getCurrencyInstance(java.util.Locale.GERMANY);
format.setCurrency(usd);
System.out.println(format.format(23));

Output: 23,00 USD

les2
  • 14,093
  • 16
  • 59
  • 76
  • 2
    Better checkout Testo Testini's answer below. – les2 Jul 23 '14 at 15:39
  • Frankly, this is still broken from Java. Optimal output should have been Output: 23,00 $ – Diolor Jan 14 '20 at 11:51
  • @Diolor no, that isn't the optimal output. That's just wrong. To get that output you have to use the US-Locale. Currency symbols aren't matched 1:1 to currency codes. So the same currency symbol can have a different meaning in a different locale. This is why you are only allowed to use currency symbols if locale and currency match. – noamik Oct 15 '20 at 12:43
29

I would add to answer from les2 https://stackoverflow.com/a/7828512/1536382 that I believe the number of fraction digits is not taken from the currency, it must be set manually, otherwise if client (NumberFormat) has JAPAN locale and Currency is EURO or en_US, then the amount is displayed 'a la' Yen', without fraction digits, but this is not as expected since in euro decimals are relevant, also for Japanese ;-).

So les2 example could be improved adding format.setMaximumFractionDigits(usd.getDefaultFractionDigits());, that in that particular case of the example is not relevant but it becomes relevant using a number with decimals and Locale.JAPAN as locale for NumberFormat.

    java.util.Currency usd = java.util.Currency.getInstance("USD");
    java.text.NumberFormat format = java.text.NumberFormat.getCurrencyInstance(
          java.util.Locale.JAPAN);
    format.setCurrency(usd);
    System.out.println(format.format(23.23));
    format.setMaximumFractionDigits(usd.getDefaultFractionDigits());
    System.out.println(format.format(23.23));

will output:

USD23
USD23.23

In NumberFormat code something similar is done for the initial/default currency of the format, calling method DecimalFormat#adjustForCurrencyDefaultFractionDigits. This operation is not done when the currency is changed afterwards with NumberFormat.setCurrency

Community
  • 1
  • 1
Testo Testini
  • 2,200
  • 18
  • 29
  • Good catch. This really is tedious enough to mandate being a utility library, e.g., commons-currency. Does one exist? CurrencyUtils.getFormatter(Locale, Currency).format(BigDecimal) – les2 Jul 23 '14 at 15:36
  • Leaving this for anyone who might be bitten by this behaviour: On Android (specifically, Samsung Galaxy Note 2 with 4.3), with locale de_CH (Deutsch (Schweiz)), if I get the default currency formatter, and call setCurrency("CAD"), I will get "Swedish" rounding. That is, a value of 26.98 gets formatted to 27.00! But with setCurrency("USD"), I don't see this behaviour. Calling setMaximumFractionDigits() as above seems to resolve things, but it doesn't make sense to me, since both CAD and USD use 2 fractional digits by default. – gnuf Nov 26 '14 at 20:37
  • This only solves the problem for the maximum number of fraction digits displayed. Everything else, such as rounding behavior and placement of currency symbol will keep the settings of the native currency for the specified locale. – mpontes Oct 08 '15 at 16:21
  • @gnuf I tried your example but I see no rounding with CAD, and also if using JPY, that has no fraction digits. The fraction digits value (2) come from the "Schweizer Franken" initial/default currency of Locale "de_CH". See also updated answer. – Testo Testini Dec 16 '16 at 23:10
  • @mpontes placement of currency symbol I think is correctly locale-specific (eg: french people put symbol after amount for any currency). Could you expand on the rounding behavior ? May be with an example. Thanks. – Testo Testini Jun 04 '17 at 23:23
13
import java.util.*;
import java.text.*;

public class Solution {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        double payment = scanner.nextDouble();
        scanner.close();

        NumberFormat lp;  //Local Payment

        lp = NumberFormat.getCurrencyInstance(Locale.US);
        System.out.println("US: " + lp.format(payment));

        lp = NumberFormat.getCurrencyInstance(new Locale("en", "in"));
        System.out.println("India: " + lp.format(payment));

        lp = NumberFormat.getCurrencyInstance(Locale.CHINA);
        System.out.println("China: " + lp.format(payment));

        lp = NumberFormat.getCurrencyInstance(Locale.FRANCE);
        System.out.println("France: " + lp.format(payment));
    }
}
Ankush
  • 131
  • 1
  • 4
3
Scanner scanner = new Scanner(System.in);
double payment = scanner.nextDouble();
scanner.close();
java.text.NumberFormat formatUS = java.text.NumberFormat.getCurrencyInstance(java.util.Locale.US);
String us=formatUS.format(payment);
java.text.NumberFormat formatIn = java.text.NumberFormat.getCurrencyInstance(new java.util.Locale("en","in"));
String india=formatIn.format(payment);
java.text.NumberFormat formatChina = java.text.NumberFormat.getCurrencyInstance(java.util.Locale.CHINA);
String china=formatChina.format(payment);
java.text.NumberFormat formatFrance = java.text.NumberFormat.getCurrencyInstance(java.util.Locale.FRANCE);
String france=formatFrance.format(payment);

System.out.println("US: " + us);
System.out.println("India: " + india);
System.out.println("China: " + china);
System.out.println("France: " + france);
Nubok
  • 3,502
  • 7
  • 27
  • 47
3

Code below, Ref Java Locale:

Scanner scanner = new Scanner(System.in);
double payment = scanner.nextDouble();
scanner.close();

// Write your code here.
String china = NumberFormat.getCurrencyInstance(new Locale("zh", "CN")).format(payment);
String india = NumberFormat.getCurrencyInstance(new Locale("en", "IN")).format(payment);
String us = NumberFormat.getCurrencyInstance(Locale.US).format(payment);
String france = NumberFormat.getCurrencyInstance(Locale.FRANCE).format(payment);

System.out.println("US: " + us);
System.out.println("India: " + india);
System.out.println("China: " + china);
System.out.println("France: " + france);
TechFree
  • 2,600
  • 1
  • 17
  • 18
1

Better way is just to import java.util.Locale.

Then use the method like this:

NumberFormat.getCurrencyInstance(Locale.theCountryYouWant);

e.g. NumberFormat.getCurrencyInstance(Locale.US);

programandoconro
  • 2,378
  • 2
  • 18
  • 33
0

    import java.util.*;
    import java.text.*;
    public class CurrencyConvertor {   
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            double curr= scanner.nextDouble();
            scanner.close();
            if(curr>=0 && curr<=1000000000){
     NumberFormat france = NumberFormat.getCurrencyInstance(Locale.FRANCE);
    NumberFormat us = NumberFormat.getCurrencyInstance(Locale.US);
    NumberFormat china = NumberFormat.getCurrencyInstance(Locale.CHINA);
            NumberFormat india = NumberFormat.getCurrencyInstance(Locale.ENGLISH);
             
          System.out.println("India: "+NumberFormat.getCurrencyInstance(new Locale("en","IN")).format(curr)); 
           System.out.println("US: " + us.format(curr));
          System.out.println("China: "+ china.format(curr));
            System.out.println("France: " + france.format(curr));
            }
        }
    }

Aarti
  • 101
  • 7
0

Try this, Using Locale, you can pass the country and get the currency.

Locale currentLocale = Locale.GERMANY;
Double currencyAmount = new Double(9876543.21);
Currency currentCurrency = Currency.getInstance(currentLocale);
NumberFormat currencyFormatter = 
    NumberFormat.getCurrencyInstance(currentLocale);

System.out.println(
    currentLocale.getDisplayName() + ", " +
    currentCurrency.getDisplayName() + ": " +
    currencyFormatter.format(currencyAmount));

Output: German (Germany), Euro: 9.876.543,21 €

Sathiamoorthy
  • 8,831
  • 9
  • 65
  • 77