JSR-354 MonetaryAmountFormat not working two way for other currency symbols than $, € or £

妖精的绣舞 提交于 2019-12-12 20:06:20

问题


Here is example code that I'm using with Moneta version 1.1:

    Locale LANG = Locale.CHINA;  // also tried new Locale("pl", "PL");

    final MonetaryAmountFormat format = MonetaryFormats.getAmountFormat(
            AmountFormatQueryBuilder.of(LANG)
                    .set(CurrencyStyle.SYMBOL)
                    .set("pattern", "#,##0.00### ¤")
                    .build()
    );
    final String formatted = format.format(Money.of(new BigDecimal("1234.56"), Monetary.getCurrency(LANG)));

    System.out.println(formatted);

    System.out.println(format.parse(formatted).getNumber());

This should work since I'm converting same object back and forth. Unless I got something wrong and converter is not two-way for other currencies than $, € or £.

The last line crashes with:

Exception in thread "main" java.lang.IllegalArgumentException: Invalid error index > input.length
at javax.money.format.MonetaryParseException.<init>(MonetaryParseException.java:56)
at org.javamoney.moneta.internal.format.AmountNumberToken.parse(AmountNumberToken.java:140)
at org.javamoney.moneta.internal.format.DefaultMonetaryAmountFormat.parse(DefaultMonetaryAmountFormat.java:190)
at test.main(test.java:27)

This happens if provided locale is not associated with one of $, € or £. For instance this code will work for Locale.US, but will crash for Locale.CHINA as well as with new Locale("pl", "PL"). So this is not only problem with custom defined Locale but those statically predefined as well.

I have dug a little into the internal package and found org.javamoney.moneta.internal.format.CurrencyToken.parse(CurrencyToken.java:196), which looks like:

case SYMBOL:
    if (token.startsWith("$")) {
        cur = Monetary.getCurrency("USD");
        context.consume("$");
    } else if (token.startsWith("€")) {
        cur = Monetary.getCurrency("EUR");
        context.consume("€");
    } else if (token.startsWith("£")) {
        cur = Monetary.getCurrency("GBP");
        context.consume("£");
    } else {
        cur = Monetary.getCurrency(token);
        context.consume(token);
    }
    context.setParsedCurrency(cur);
    break;

Is there any way to make my code above work for currencies other than $, € or £?


I have try few more things for instance provided Locale.CANADA they also have $ as currency symbol so it execute without failure but returns wrong data

    Locale LANG = Locale.CANADA;

    final MonetaryAmountFormat format = MonetaryFormats.getAmountFormat(
            AmountFormatQueryBuilder.of(LANG)
                    .set(CurrencyStyle.SYMBOL)
                    .set("pattern", "#,##0.00### ¤")
                    .build()
    );
    final String formatted = format.format(Money.of(new BigDecimal("1234.56"), Monetary.getCurrency(LANG)));

    System.out.println(formatted);

    System.out.println(format.parse(formatted).getCurrency().getCurrencyCode());

last line return USD instead of CAD which is what this if-else does for $. I think it also wrongly assumes that symbol - currency is one to one mapping.


回答1:


We're working on a solution, issues raised https://github.com/JavaMoney/jsr354-ri/issues/149.

Expect Moneta patches for this and other issues soon.

Werner



来源:https://stackoverflow.com/questions/40244526/jsr-354-monetaryamountformat-not-working-two-way-for-other-currency-symbols-than

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!