NumberFormat.parse() fails for some currency strings

13,263

Solution 1

Since the answers that have been suggested thus far, did not completely solve the problem, I took a painfully amateurish approach:

String value = "$24,76" 
value = value.replace(getCurrencySymbol(locale), StringUtils.EMPTY);

NumberFormat numberFormat = NumberFormat.getInstance(locale);
Number result = numberFormat.parse(value);

So now I simply strip the String value off it's currency symbol... This way I can process everything I want, such as: 45.78 or 45,78 or $45.78 or 45,78€ ....

Whatever the input, the currency symbol is simply stripped and I end up with the plain number. My unittests (see OP) now complete successfully.

If anyone comes up with something better, please let me know.

Solution 2

Try following:

NumberFormat numberFormat = new DecimalFormat("¤#.00", new DecimalFormatSymbols(Locale.UK));
numberFormat.parse("£123.5678");

¤ - currency sign, expects matches with currency symbol by Locale.

other pattern symbols you can see by following link http://docs.oracle.com/javase/6/docs/api/java/text/DecimalFormat.html

Solution 3

Try NumberFormat.getCurrencyInstance().parse() instead of NumberFormat.getInstance().parse().

Share:
13,263
AgentKnopf
Author by

AgentKnopf

Updated on June 04, 2022

Comments

  • AgentKnopf
    AgentKnopf almost 2 years

    I have a simple EditText, which allows the user to enter a number such as 45.60 (example for American Dollar). I then format this number using the following method:

    public String format() {
        NumberFormat formatter = NumberFormat.getCurrencyInstance(Locale.getDefault());
        return formatter.format(amount.doubleValue());
    }
    

    And on my Android phone, the language is set to English (United States) - hence the Locale.getDefault() should return the US locale (and it does).

    Now the edit text is correctly updated to: $45.60 (hence formatting the entered number works).

    However if I attempt to parse the above String "$45.60" using the following method:

    NumberFormat numberFormat = NumberFormat.getInstance(Locale.getDefault());
    Number result = numberFormat.parse("$45.60");
    

    It fails with:

    java.lang.IllegalArgumentException: Failed to parse amount $45.60 using locale en_US.
    

    If I set my phone to English/ UK, formatting this "45.60" to "£45.60" works correctly (as for US), however parsing "£45.60" fails, just as it does for the above US sample.

    However, if I set my phone to German (Germany), formatting "45,60" to "45,60€" works correctly, AND parsing "45,60€" works correctly as well!

    The only difference I see between those three currencies: The Euro is appended to the amount, while the Dollar and the Pound are prepended to the amount.

    Does anyone have an idea, why the same code works for Euro, but not for Pound and Dollar? Am I missing something?

    I also created a unit test, to reproduce the issue:

    public void testCreateStringBased() throws Exception {
    
        // For German locale
        CurrencyAmount amount = new CurrencyAmount("25,46€", Locale.GERMANY);
        assertEquals(25.46, amount.getAsDouble());
    
        // For French locale
        amount = new CurrencyAmount("25,46€", Locale.FRANCE);
        assertEquals(25.46, amount.getAsDouble());
    
        // For US locale
        amount = new CurrencyAmount("$25.46", Locale.US);
        assertEquals(25.46, amount.getAsDouble());
    
        // For UK locale
        amount = new CurrencyAmount("£25.46", Locale.UK);
        assertEquals(25.46, amount.getAsDouble());
    }
    

    CurrencyAmount basically wraps the code I posted for parsing currency strings, except that it takes the given locale instead of the default locale. In the above example, the test succeeds for the GERMANY and FRANCE locale but fails for US and UK locale.