Как заставить NumberFormatter печатать отрицательные значения валюты со знаком минус? - PullRequest
7 голосов
/ 21 июля 2009

Я использую класс PHP NumberFormatter для печати значений валют.

Например:

  $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".

Есть ли какой-нибудь управляющий код для символа валюты, который мне нужно использовать при установке атрибута NEGATIVE_PREFIX?

Редактировать: Я рад установить другую локаль, если это даст мне результат, который я ищу.

Редактировать 2: Глядя на документы библиотеки Intl (которая используется для реализации NumberFormatter), следующие предложения выглядели многообещающими:

¤ (\ u00A4): префикс или суффикс: без знака валюты, заменен символом валюты. При удвоении заменяется международным символом валюты. Если утроено, заменяется валютой во множественном числе, например, «доллар США» или «доллары США» для Америки. Если присутствует в шаблоне, вместо десятичного разделителя используется денежный десятичный разделитель.

Но это:

$cFormatter->setTextAttribute(NumberFormatter::NEGATIVE_PREFIX, "-¤");

Просто печатает "-¤123", так что радости нет.

Редактировать 3: Я думаю, что нашел ответ, см. Ниже.

Ответы [ 3 ]

14 голосов
/ 22 июля 2009

Я нашел немного менее хакерский способ подчинить поведение локали 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
1 голос
/ 29 ноября 2014

Тем самым вы как бы разрушаете точку локализации. Поскольку ¤ представляет знак доллара, а вы говорите, что ваш шаблон всегда ставит знак в начале числа, что не относится к каждой валюте. Если вы хотите убрать круглые скобки, я бы пошел что-то вроде,

$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);
0 голосов
/ 29 июля 2016

Просто вы можете сделать

$cFormatter->setTextAttribute(NumberFormatter::PAD_BEFORE_PREFIX, '-$')."\n";
...