Статьи

Проверка формата валюты и анализ

В Java форматирование числа в соответствии с форматом валюты для конкретной локали довольно просто. Вы используете экземпляр   класса java.text.NumberFormat, создав его экземпляр с помощью  NumberFormat.getCurrencyInstance ()  и вызывая один из   методов format () . Ниже приведен фрагмент кода из  https://docs.oracle.com/javase/tutorial/i18n/format/numberFormat.html.

static public void displayCurrency( Locale currentLocale) {

    Double currencyAmount = new Double(9876543.21);
    Currency currentCurrency = Currency.getInstance(currentLocale);
    NumberFormat currencyFormatter = 
        NumberFormat.getCurrencyInstance(currentLocale);

    System.out.println(
        currentLocale.getDisplayName() + ", " +
        currentCurrency.getDisplayName() + ": " +
        currencyFormatter.format(currencyAmount));
}

Однако, если приложение позволяет пользователям вводить сумму в виде строки с использованием разделителей и символов валюты, вполне возможно, что формат валюты может не соблюдаться в  зависимости от локали. Например, пользователь может использовать неправильный разделитель тысяч или десятичный разделитель или неверный символ валюты в целом.

В этом случае приложение должно включать механизм, обеспечивающий сначала соблюдение этого формата, а затем анализ этой строки, чтобы преобразовать ее в правильное число, чтобы выполнить несколько математических вычислений независимо от формата валюты. 

Это важно отметить , что разбор строки с использованием  java.text.NumberFormat # общедоступного номер разобраны (источник String)  метод требует, чтобы строка валюты должна содержать значение по образцу локалей , определенные в  java.text.DecimalFormat  и символы , определенные в  java.text.DecimalFormatSymbols . Если шаблон и / или символы не соблюдаются, программа выдаст  исключение java.text.ParseException . Например, шаблон валюты для  it_CH = итальянский (Швейцария) равен  ¤ #, ## 0,00,  а разделитель группировки —  , следовательно,  SFr. 1’234,56 действует, а 1  234,56 SFr.  является недействительным 

Для проверки действительности суммы валюты перед ее фактическим анализом  очень удобен проект org.apache.commons.validator.routines.CurrencyValidator проекта Apache Commons Validator  . Все, что вам нужно сделать, — это создать его объект и вызвать  публичный логический  метод isValid (String value, Locale locale), чтобы проверить, соблюдается ли специфичный для локали формат или нет.

Как только вы закончите проверку и обнаружите, что номер является действительным, вы можете затем проанализировать номер, вызвав метод parse (). Следующий фрагмент кода показывает, как проверить и проанализировать. Обратите внимание, что проверка мягкая и если символ валюты еще не присутствует в строке, он добавляет соответствующий символ валюты в соответствии с шаблоном, а затем проверяет и анализирует его.

/**
	 * Converts given item price into a number based on given
	 * currency code.
	 * <p>
	 * It works generically for all currencies supported by Java
	 * </p>
	 * 
	 * @param itemPrice currency amount
	 * @param currencyCode 3-letter ISO country code
	 * @return {@link String} containing stripped price or same as given price
	 *         if parsing failed or formatter couldn't be constructed
	 * @author Muhammad Haris
	 */
	public static Double convertPrice(String itemPrice, String currencyCode) {
		Double itemPriceConverted = null;
		Locale currencyLocale = LocaleUtility
				.getLocaleAgainstCurrency(currencyCode);
		DecimalFormat currencyFormatter = getCurrencyFormatter(currencyLocale);

		if (currencyFormatter != null) {
			itemPrice = appendCurrencySymbol(itemPrice,
					currencyFormatter);

			try {
				Number number = currencyFormatter.parse(itemPrice);
				itemPriceConverted = number.doubleValue();				
			} catch (ParseException e) {
				LOG.error("Failed to parse currency: " + currencyCode
						+ ", value: " + itemPrice + ". " + e.getMessage(), e);
			}

		} else {
			LOG.error("No appropriate formatter found for currency: "
					+ currencyCode + ", value: " + itemPrice + ". ");
		}

		return itemPriceConverted;
	}

	/**
	 * Gets currency formatter against given currency locale
	 * 
	 * @param currencyCode
	 *            {@link String} containing 3 letter ISO currency code
	 * @return {@link NumberFormat} object specialized for the currency or null
	 *         if it couldn't be composed
	 * @author Muhammad Haris
	 */
	public static DecimalFormat getCurrencyFormatter(Locale currencyLocale) {

		if (currencyLocale != null) {
			return (DecimalFormat) NumberFormat
					.getCurrencyInstance(currencyLocale);
		}

		return null;
	}

	/**
	 * Appends appropriate currency symbol to the given price using the pattern
	 * defined in the given currency formatter
	 * 
	 * @param itemPrice
	 *            {@link String} containing price of the item in locale specific
	 *            format
	 * @param currencyFormatter
	 *            {@link DecimalFormat} object containing currency locale
	 *            specific formatting info
	 * @author Muhammad Haris
	 */
	public static String appendCurrencySymbol(String itemPrice,
			DecimalFormat currencyFormatter) {
		String currencySymbol = currencyFormatter.getDecimalFormatSymbols()
				.getCurrencySymbol();
		String pattern = currencyFormatter.toPattern();

		if (!itemPrice.contains(currencySymbol)) {
			if (pattern.startsWith("¤ ")) {
				itemPrice = currencySymbol + " " + itemPrice;
			} else if (pattern.endsWith(" ¤")) {
				itemPrice = itemPrice + " " + currencySymbol;
			} else if (pattern.startsWith("¤")) {
				itemPrice = currencySymbol + itemPrice;
			} else if (pattern.endsWith("¤")) {
				itemPrice = itemPrice + currencySymbol;
			}
		}

		return itemPrice;
	}