Java Currency Formatter

  • + 0 comments

    I managed to adapt the solution for Java 15 and I got the correct output, but the test fails either way 😞 I double checked it with diff and it's 100% the same, including types of spaces (narrow non-breaking space vs. regular space for French formatting). I spent a lot of time investigating on how to get the correct response with NumberFormat, so I share the solution.

    The idea is based on using the DecimalFormat derived class that alllows for cusomization of many low-level aspects of the currency rendering through DecimalFormatSymbols substitution – these include the currency symbol and grouping separator that have changed in the locales between Java 8 and Java 15. The second one obviously doesn't work again, so I have to apply the substitution on the final string too, which I'm not happy with, of course. But in general it looks for me like a good answer, with one quirk. What do you think?

    Here's the code:

    import java.text.DecimalFormat;
    import java.text.DecimalFormatSymbols;
    import java.text.NumberFormat;
    import java.util.Locale;
    import java.util.Scanner;
    
    import java.util.Map;
    import java.util.LinkedHashMap;
    
    public class Solution {
    
        private static DecimalFormat getCurrencyFormat(Locale locale) {
            return (DecimalFormat) NumberFormat.getCurrencyInstance(locale);
        }
    
        private static DecimalFormat getCurrencyFormat(Locale locale, String sym, Character sep) {
            DecimalFormatSymbols symbols = new DecimalFormatSymbols(locale);
            if (sym != null) symbols.setCurrencySymbol(sym);
            if (sep != null) symbols.setGroupingSeparator(sep);
            DecimalFormat format = (DecimalFormat) NumberFormat.getCurrencyInstance(locale);
            format.setDecimalFormatSymbols(symbols);
            return format;
        }
    
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            double payment = sc.nextDouble();
            sc.close();
    
            Map<String, DecimalFormat> formats = new LinkedHashMap<>();
            formats.put("US", getCurrencyFormat(Locale.US));
            formats.put("India", getCurrencyFormat(new Locale("en", "IN"), "Rs.", null));
            formats.put("China", getCurrencyFormat(Locale.CHINA, "\uFFe5", null));
            formats.put("France", getCurrencyFormat(Locale.FRANCE, null, ' '));
    
            for (Map.Entry<String, DecimalFormat> entry : formats.entrySet()) {
                System.out.println(entry.getKey() + ": "
                + entry.getValue().format(payment).replace("\u202F", " "));
            }
        }
    }