Question

I found a bug in my app where my currency strings were not showing the correct grouping and decimal separators when using an international format. I extracted the code to try to isolate and demonstrate the problem. In the code below, I create a US formatter and a World formatter. They both use the same currency pattern, but the USA formatter uses a period as the decimal separator and the World formatter uses a comma as the decimal separator.

When I ask the World formatter to tell me what its separators are, it reports them correctly. However, when I have it generate the string for my value, it doesn't do it properly. It strangely uses the period for both the grouping AND the decimal separator.

public static void main(String[] args) throws Exception {

    String currencyFormat = "¤#,##0.00;-¤#,##0.00";
    NumberFormat currencyUSA = NumberFormat.getCurrencyInstance();
    DecimalFormat decimalCurrencyUSA = (DecimalFormat)currencyUSA;
    decimalCurrencyUSA.applyPattern(currencyFormat);

    NumberFormat currencyWorld = NumberFormat.getCurrencyInstance();
    DecimalFormat decimalCurrencyWorld = (DecimalFormat)currencyWorld;
    decimalCurrencyWorld.applyPattern(currencyFormat);

    DecimalFormatSymbols decimalFormatSymbols = decimalCurrencyWorld.getDecimalFormatSymbols();
    //DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols(Locale.GERMAN);

    System.out.println(String.format("Original grouping: %c decimal: %c", decimalFormatSymbols.getGroupingSeparator(), decimalFormatSymbols.getDecimalSeparator()));
    decimalFormatSymbols.setDecimalSeparator(',');
    decimalFormatSymbols.setGroupingSeparator('.');
    decimalCurrencyWorld.setDecimalFormatSymbols(decimalFormatSymbols);
    System.out.println(String.format("  After grouping: %c decimal: %c", decimalFormatSymbols.getGroupingSeparator(), decimalFormatSymbols.getDecimalSeparator()));

    String moneyUSA = currencyUSA.format(1500.75);
    String moneyWorld = currencyWorld.format(1500.75);

    DecimalFormatSymbols decimalFormatSymbols2 = decimalCurrencyWorld.getDecimalFormatSymbols();
    System.out.println(String.format("   Real grouping: %c decimal: %c", decimalFormatSymbols2.getGroupingSeparator(), decimalFormatSymbols2.getDecimalSeparator()));

    System.out.println(String.format("  USA String: %s", moneyUSA));
    System.out.println(String.format("World String: %s", moneyWorld));

    Number numberUSA = currencyUSA.parse(moneyUSA);
    Number numberWorld = currencyWorld.parse(moneyWorld);

    System.out.println(String.format("  USA Number: %f", numberUSA));
    System.out.println(String.format("World Number: %f", numberWorld));

}

When I run the above code (on my Mac OS X 10.9, Eclipse Indigo, Java 1.6), the output is:

Original grouping: , decimal: .
  After grouping: . decimal: ,
   Real grouping: . decimal: ,
  USA String: $1,500.75
World String: $1.500.75
  USA Number: 1500.750000
World Number: 1.500000

The World currency value should be $1.500,75 however it used a period in both places.

EDIT:

I need to control the separators specifically. I can respect the user's Locale when it comes to the currency symbol, but due to the requirements of this app, I need to provide the user the ability to swap the period/comma when it comes to the separators. I can't just rely on the Locale to control these things.

The problem is that I'm clearly setting those values in my formatters and they aren't being respected.

EDIT 2: I added code to then parse the previously generated money string to see if the Decimal separators were being respected for parsing, but not for formatting. It appears that during parsing, the period is still being treated as the decimal separator as well because the World Number came out as 1.5 instead of 1500.75.

Was it helpful?

Solution

From Customizing Formats

¤ currency sign; replaced by currency symbol; if doubled, replaced by international currency symbol; if present in a pattern, the monetary decimal separator is used instead of the decimal separator

So:

decimalFormatSymbols.setMonetaryDecimalSeparator(',');

Will do it.

OTHER TIPS

If you change

DecimalFormatSymbols decimalFormatSymbols = decimalCurrencyWorld.getDecimalFormatSymbols();

to

DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols(Locale.GERMAN);

(or some other Locale) you will find that the separators work properly.

decimalFormatSymbols.setDecimalSeparator(','); apparently does not change the format (although setGroupingSeparator() does, as you have discovered).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top