brick / money

A money and currency library for PHP
MIT License
1.61k stars 96 forks source link

Format with thousand/million/billion/trillion suffix #47

Closed 4n70w4 closed 3 years ago

4n70w4 commented 3 years ago

Hi!

I did not find in the documentation whether such formatting can be done.

For example:

1k instead 1 000 or 1 тыс. instead 1 000 if ru_RU locale. 1.1k instead 1 100 or 1,1 тыс. instead 1 100 if ru_RU locale.

1m instead 1 000 000 or 1 млн instead 1 000 000 if ru_RU locale. 1.5m instead 1 500 000 or 1,5 млн instead 1 500 000 if ru_RU locale. ...etc

BenMorel commented 3 years ago

Hi, there is no built-in way to format the money this way, however, check out the NumberFormatter class to see if it allows this; if you find a way to make it format a monetary amount the way you want, you can use Money::formatWith() and pass the configured NumberFormatter instance.

mininduhewawasam commented 2 years ago
class MoneySuffixFormatter implements MoneyFormatter
{
    private const Million = 'million';
    private const Billion = 'billion';

    public function format(Money $money)
    {
        $million = Money::of(1000000, 'GBP');
        $billion = Money::of(1000000000, 'GBP');

        $formatter = new NumberFormatter('en_GB', NumberFormatter::CURRENCY);

        if ($money->isGreaterThanOrEqualTo($billion)) {
            return $this->formatWithSuffix($money, $billion, self::Billion, $formatter);
        }

        if ($money->isGreaterThanOrEqualTo($million)) {
            return $this->formatWithSuffix($money, $million, self::Million, $formatter);
        }

        $formatter->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, 0);

        return $money->formatWith($formatter);
    }

    protected function formatWithSuffix(Money $money, Money $scale, string $suffix, $formatter)
    {
        $formatter->setPattern("£#0.## $suffix");

        return $money->dividedBy($scale->getAmount(), RoundingMode::UP)->formatWith($formatter);
    }
}