Search code examples
javainternationalizationlocale

Displaying Currency in Indian Numbering Format


I have a question about formatting the Rupee currency (Indian Rupee - INR).

Typically a value like 450500 is formatted and shown as 450,500. In India, the same value is displayed as 4,50,500

For example, numbers here are represented as:

1
10
100
1,000
10,000
1,00,000
10,00,000
1,00,00,000
10,00,00,000

Refer Indian Numbering System

The separators are after two digits, except for the last set, which is in thousands.

I've searched on the internet and people have asked to use the locale en_GB or pattern #,##,##,##,##0.00

I tried this on JSTL by using the following tag:

<fmt:formatNumber value="${product.price}" type="currency" 
  pattern="#,##,##,##,###.00"/>

But this does not seem to solve the issue.


Solution

  • Unfortunately on standard Java SE DecimalFormat doesn't support variable-width groups. So it won't ever format the values exactly as you want to:

    If you supply a pattern with multiple grouping characters, the interval between the last one and the end of the integer is the one that is used. So "#,##,###,####" == "######,####" == "##,####,####".

    Most number formatting mechanisms in Java are based on that class and therefore inherit this flaw.

    ICU4J (the Java version of the International Components for Unicode) provides a NumberFormat class that does support this formatting:

    Format format = com.ibm.icu.text.NumberFormat.getCurrencyInstance(new Locale("en", "in"));
    System.out.println(format.format(new BigDecimal("100000000")));
    

    This code will produce this output:

    Rs 10,00,00,000.00

    Note: the com.ibm.icu.text.NumberFormat class does not extend the java.text.NumberFormat class (because it already extends an ICU-internal base class), it does however extend the java.text.Format class, which has the format(Object) method.

    Note that the Android version of java.text.DecimalFormat class is implemented using ICU under the hood and does support the feature in the same way that the ICU class itself does (even though the summary incorrectly mentions that it's not supported).