<?php
declare(strict_types=1);
namespace Brick\Money;
use Brick\Money\Exception\MoneyMismatchException;
use Brick\Math\BigNumber;
use Brick\Math\BigRational;
use Brick\Math\Exception\MathException;
/**
* An exact monetary amount, represented as a rational number. This class is immutable.
*
* This is used to represent intermediate calculation results, and may not be exactly convertible to a decimal amount
* with a finite number of digits. The final conversion to a Money may require rounding.
*/
final class RationalMoney extends AbstractMoney
{
private BigRational $amount;
private Currency $currency;
/**
* Class constructor.
*
* @param BigRational $amount The amount.
* @param Currency $currency The currency.
*/
public function __construct(BigRational $amount, Currency $currency)
{
$this->amount = $amount;
$this->currency = $currency;
}
/**
* Convenience factory method.
*
* @param BigNumber|int|float|string $amount The monetary amount.
* @param Currency|string|int $currency The Currency instance, ISO currency code or ISO numeric currency code.
*
* @return RationalMoney
*/
public static function of(BigNumber|int|float|string $amount, Currency|string|int $currency) : RationalMoney
{
$amount = BigRational::of($amount);
if (! $currency instanceof Currency) {
$currency = Currency::of($currency);
}
return new RationalMoney($amount, $currency);
}
/**
* @return BigRational
*/
public function getAmount() : BigRational
{
return $this->amount;
}
/**
* @return Currency
*/
public function getCurrency() : Currency
{
return $this->currency;
}
/**
* Returns the sum of this RationalMoney and the given amount.
*
* @param AbstractMoney|BigNumber|int|float|string $that The money or amount to add.
*
* @return RationalMoney
*
* @throws MathException If the argument is not a valid number.
* @throws MoneyMismatchException If the argument is a money in another currency.
*/
public function plus(AbstractMoney|BigNumber|int|float|string $that) : RationalMoney
{
$that = $this->getAmountOf($that);
$amount = $this->amount->plus($that);
return new self($amount, $this->currency);
}
/**
* Returns the difference of this RationalMoney and the given amount.
*
* @param AbstractMoney|BigNumber|int|float|string $that The money or amount to subtract.
*
* @return RationalMoney
*
* @throws MathException If the argument is not a valid number.
* @throws MoneyMismatchException If the argument is a money in another currency.
*/
public function minus(AbstractMoney|BigNumber|int|float|string $that) : RationalMoney
{
$that = $this->getAmountOf($that);
$amount = $this->amount->minus($that);
return new self($amount, $this->currency);
}
/**
* Returns the product of this RationalMoney and the given number.
*
* @param BigNumber|int|float|string $that The multiplier.
*
* @return RationalMoney
*
* @throws MathException If the argument is not a valid number.
*/
public function multipliedBy(BigNumber|int|float|string $that) : RationalMoney
{
$amount = $this->amount->multipliedBy($that);
return new self($amount, $this->currency);
}
/**
* Returns the result of the division of this RationalMoney by the given number.
*
* @param BigNumber|int|float|string $that The divisor.
*
* @return RationalMoney
*
* @throws MathException If the argument is not a valid number.
*/
public function dividedBy(BigNumber|int|float|string $that) : RationalMoney
{
$amount = $this->amount->dividedBy($that);
return new self($amount, $this->currency);
}
/**
* Returns a copy of this BigRational, with the amount simplified.
*
* @return RationalMoney
*/
public function simplified() : RationalMoney
{
return new self($this->amount->simplified(), $this->currency);
}
public function __toString() : string
{
return $this->currency . ' ' . $this->amount;
}
}