JSR-354 MonetaryAmountFormat没有为$,€或£之外的其他货币符号工作

时间:2016-10-25 15:56:37

标签: java internationalization currency-formatting java-money jsr354

以下是我与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());

这应该有效,因为我来回转换同一个对象。除非我出错了,转换器对于其他货币不是双向的,而不是$,€或£。

最后一行崩溃:

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)

如果提供的区域设置与$,€或£之一无关,则会发生这种情况。例如,此代码适用于Locale.US,但会Locale.CHINA以及new Locale("pl", "PL")崩溃。因此,这不仅是自定义Locale的问题,也是静态预定义的问题。

我在内部包中挖了一点,发现org.javamoney.moneta.internal.format.CurrencyToken.parse(CurrencyToken.java:196),看起来像是:

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;

有没有办法让我的代码能够使用$,€或£?以外的其他货币?

我已经尝试了更多的东西,例如Locale.CANADA,他们也有$作为货币符号,所以它执行没有失败,但返回错误的数据

    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());

最后一行返回USD而不是CAD这就是这个if-else对$的作用。我认为它也错误地假设符号 - 货币是一对一的映射。

1 个答案:

答案 0 :(得分:0)

我们正在制定解决方案,提出问题https://github.com/JavaMoney/jsr354-ri/issues/149

很快就会出现Moneta补丁以及其他问题。

沃纳