Как заставить NumberFormatter печатать отрицательные значения валюты со знаком минус?
-
18-09-2019 - |
Вопрос
Я использую PHP Числовой форматтер класс для печати значений валюты.
Например:
$cFormatter = new NumberFormatter('en_US', NumberFormatter::CURRENCY);
$cFormatter->formatCurrency(123, 'USD');
$cFormatter->formatCurrency(123, 'BRL');
$cFormatter->formatCurrency(123, 'GBP');
Это отлично работает и возвращает "$123.00
", "R$123.00
", "£123.00
"соответственно, как и ожидалось.
Но отрицательные числа печатаются в «бухгалтерском стиле» и заключены в скобки, а не в начале минус «-».
например:
$cFormatter->formatCurrency(-456, 'USD');
Возврат "($456.00)"
, тогда как я хочу "-$456.00"
.Наверняка есть простой способ сделать это?
Я могу удалить скобки, переопределив префикс и постфикс следующим образом:
$cFormatter->setTextAttribute(NumberFormatter::NEGATIVE_PREFIX, "-");
$cFormatter->setTextAttribute(NumberFormatter::NEGATIVE_SUFFIX, "");
Но тогда я не получаю символ валюты, например "-456.00"
.
Есть ли какой-нибудь escape-код для символа валюты, который мне нужно использовать при установке атрибута NEGATIVE_PREFIX?
Редактировать: Я буду рад установить другой языковой стандарт, если это даст мне тот результат, который я ищу.
Редактировать 2: Глядя на Документы международной библиотеки (библиотека, используемая для реализации NumberFormatter), многообещающе выглядело следующее:
¤ (\u00A4) :Префикс или суффикс:Знак валюты отсутствует, заменен символом валюты.При удвоении заменяется символом международной валюты.Если утроено, заменяется названиями валют во множественном числе, например, «доллар США» или «доллары США» для Америки.Если он присутствует в шаблоне, вместо десятичного разделителя используется денежный десятичный разделитель.
Но это:
$cFormatter->setTextAttribute(NumberFormatter::NEGATIVE_PREFIX, "-¤");
Просто печатает «-¤123», так что никакой радости.
Редактировать 3: Думаю, я нашел ответ, см. ниже.
Решение
Я нашел немного менее хакерский способ изменить поведение локали en_US на то, что мне нужно - getPattern() / setPattern() функции.
$cFormatter = new NumberFormatter('en_US', NumberFormatter::CURRENCY);
$sPattern = $cFormatter->getPattern(); // returns "¤#,##0.00;(¤#,##0.00)";
$sMyPattern = "¤#,##0.00;-¤#,##0.00";
$cFormatter->setPattern($sMyPattern);
$cFormatter->formatCurrency(-456, 'USD'); // returns -$456.00
Другие советы
Поступая так, вы как бы портите смысл локализации.Поскольку ¤ представляет знак доллара, и вы говорите, что ваш шаблон всегда помещает знак в начало числа, что не относится к каждой валюте.Если вы хотите удалить скобки, я бы сказал что-то вроде:
$locale = 'en_US';
$nf = new \NumberFormatter($locale, \NumberFormatter::CURRENCY);
$nf->setAttribute(\NumberFormatter::MAX_FRACTION_DIGITS, $decimals);
$pattern = str_replace(array('(',')'),'',$nf->getPattern());
$nf->setPattern($pattern);
echo $nf->format($number);
Просто вы можете сделать
$cFormatter->setTextAttribute(NumberFormatter::PAD_BEFORE_PREFIX, '-$')."\n";