JSR-354 MonetaryAmountFormat 对于 $、€ 或 £ 之外的其他货币符号无法以两种方式工作

2024-01-07

这是我正在使用的示例代码莫尼塔版本1.1 https://github.com/JavaMoney/jsr354-ri/tree/1.1-release:

    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 对 $ 所做的事情。我认为它也错误地假设符号-货币是一对一的映射。


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

预计 Moneta 很快就会修复这个问题和其他问题。

Werner

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JSR-354 MonetaryAmountFormat 对于 $、€ 或 £ 之外的其他货币符号无法以两种方式工作 的相关文章

随机推荐