JSR-354 MonetaryAmountFormat не работает в двух направлениях для других символов валюты, кроме $, € или £

Вот пример кода, который я использую с Moneta версии 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 ответ

Мы работаем над решением проблем, поднятых https://github.com/JavaMoney/jsr354-ri/issues/149.

Ожидайте исправления Moneta для этой и других проблем в ближайшее время.

Вернер

Другие вопросы по тегам