精准的金额类

</pre><pre name="code" class="java">package com.qunar.flight.ib2b.trade.center.web.util;

import java.io.IOException;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;

/**
 * 用于表示记账金额, 标准6位小数.
 * 
 */
public final class Money implements Comparable<Money>, Serializable {

    private static final long serialVersionUID = -6657228621542472076L;

    private static final transient RoundingMode DEFAULT_ROUNDING = RoundingMode.HALF_EVEN;

    private static final transient MathContext DEF_MC = MathContext.DECIMAL64;

    private static final transient int PARSE_SCALE = 6;

    private BigDecimal amount;

    public static Money of(BigDecimal amount) {
        return new Money(amount);
    }

    public static Money of(double amount) {
        return of(BigDecimal.valueOf(amount));
    }

    public static Money ofMajor(long amountMajor) {
        return of(BigDecimal.valueOf(amountMajor));
    }

    public static Money parseStoreValue(long amount) {
        return of(BigDecimal.valueOf(amount, PARSE_SCALE));
    }

    public static Money total(Money... monies) {
        if (monies.length == 0) {
            throw new IllegalArgumentException("Money array must not be empty");
        }
        Money total = monies[0];
        for (int i = 1; i < monies.length; i++) {
            total = total.plus(monies[i]);
        }
        return total;
    }

    // just for serialize/deserialize
    private Money() {

    }

    private Money(BigDecimal amount) {
        this.amount = amount;
    }

    private Money with(BigDecimal newAmount) {
        if (newAmount.equals(amount)) {
            return this;
        }
        return new Money(newAmount);
    }

    // -----------------------------------------------------------------------

    /**
     * Checks if the amount is zero.
     * 
     * @return true if the amount is zero
     */
    public boolean isZero() {
        return amount.compareTo(BigDecimal.ZERO) == 0;
    }

    /**
     * Checks if the amount is greater than zero.
     * 
     * @return true if the amount is greater than zero
     */
    public boolean isPositive() {
        return amount.compareTo(BigDecimal.ZERO) > 0;
    }

    /**
     * Checks if the amount is zero or greater.
     * 
     * @return true if the amount is zero or greater
     */
    public boolean isPositiveOrZero() {
        return amount.compareTo(BigDecimal.ZERO) >= 0;
    }

    /**
     * Checks if the amount is less than zero.
     * 
     * @return true if the amount is less than zero
     */
    public boolean isNegative() {
        return amount.compareTo(BigDecimal.ZERO) < 0;
    }

    /**
     * 检查 值 <= 0
     * 
     * @return true if the amount is zero or less
     */
    public boolean isNegativeOrZero() {
        return amount.compareTo(BigDecimal.ZERO) <= 0;
    }

    public Money plus(Money... toAdds) {
        BigDecimal total = amount;
        for (Money money : toAdds) {
            total = total.add(money.amount, DEF_MC);
        }
        return with(total);
    }

    public Money plus(BigDecimal amountToAdd) {
        if (amountToAdd.compareTo(BigDecimal.ZERO) == 0) {
            return this;
        }
        BigDecimal newAmount = amount.add(amountToAdd, DEF_MC);
        return with(newAmount);
    }

    public Money plus(double amountToAdd) {
        if (amountToAdd == 0) {
            return this;
        }
        BigDecimal newAmount = amount.add(BigDecimal.valueOf(amountToAdd), DEF_MC);
        return with(newAmount);
    }

    public Money minus(Money... accountMoneys) {
        BigDecimal total = amount;
        for (Money money : accountMoneys) {
            total = total.subtract(money.amount, DEF_MC);
        }
        return with(total);
    }

    public Money minus(Money moneyToSubtract) {
        return minus(moneyToSubtract.amount);
    }

    public Money minus(BigDecimal amountToSubtract) {
        if (amountToSubtract.compareTo(BigDecimal.ZERO) == 0) {
            return this;
        }
        BigDecimal newAmount = amount.subtract(amountToSubtract, DEF_MC);
        return with(newAmount);
    }

    public Money minus(double amountToSubtract) {
        if (amountToSubtract == 0) {
            return this;
        }
        BigDecimal newAmount = amount.subtract(BigDecimal.valueOf(amountToSubtract), DEF_MC);
        return with(newAmount);
    }

    public Money minusMajor(long amountToSubtract) {
        if (amountToSubtract == 0) {
            return this;
        }
        BigDecimal newAmount = amount.subtract(BigDecimal.valueOf(amountToSubtract), DEF_MC);
        return with(newAmount);
    }

    public Money minusMinor(long amountToSubtract, int scale) {
        if (amountToSubtract == 0) {
            return this;
        }
        BigDecimal newAmount = amount.subtract(BigDecimal.valueOf(amountToSubtract, scale), DEF_MC);
        return with(newAmount);
    }

    public Money multiply(BigDecimal valueToMultiplyBy) {
        if (valueToMultiplyBy.compareTo(BigDecimal.ONE) == 0) {
            return this;
        }
        BigDecimal newAmount = amount.multiply(valueToMultiplyBy, DEF_MC);
        return with(newAmount);
    }

    public Money multiply(double valueToMultiplyBy) {
        if (valueToMultiplyBy == 1) {
            return this;
        }
        BigDecimal newAmount = amount.multiply(BigDecimal.valueOf(valueToMultiplyBy), DEF_MC);
        return with(newAmount);
    }

    public Money multiply(long valueToMultiplyBy) {
        if (valueToMultiplyBy == 1) {
            return this;
        }
        BigDecimal newAmount = amount.multiply(BigDecimal.valueOf(valueToMultiplyBy), DEF_MC);
        return with(newAmount);
    }

    public Money divide(BigDecimal value) {
        if (value.compareTo(BigDecimal.ONE) == 0) {
            return this;
        }
        BigDecimal newAmount = amount.divide(value, DEF_MC);
        return with(newAmount);
    }

    public Money divide(double value) {
        if (value == 1) {
            return this;
        }
        BigDecimal newAmount = amount.divide(BigDecimal.valueOf(value), DEF_MC);
        return with(newAmount);
    }

    public Money divide(long value) {
        if (value == 1) {
            return this;
        }
        BigDecimal newAmount = amount.divide(BigDecimal.valueOf(value), DEF_MC);

        return with(newAmount);
    }

    public Money negate() {
        if (isZero()) {
            return this;
        }
        return with(amount.negate());
    }

    public Money abs() {
        return (isNegative() ? negate() : this);
    }

    public boolean isGreaterThan(Money other) {
        return compareTo(other) > 0;
    }

    public boolean isLessThan(Money other) {
        return compareTo(other) < 0;
    }

    public BigDecimal getAmount() {
        return amount;
    }

    @Override
    public int compareTo(Money o) {
        return amount.compareTo(o.amount);
    }

    @Override
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }
        if (other instanceof Money) {
            Money otherMoney = (Money) other;
            return amount.equals(otherMoney.amount);
        }
        return false;
    }

    @Override
    public int hashCode() {
        return 7 * amount.hashCode();
    }

    public long toStoreValue() {
        return amount.movePointRight(PARSE_SCALE).setScale(0, DEFAULT_ROUNDING).longValue();
    }

    public BigDecimal toStoreDecimal() {
        return amount.setScale(PARSE_SCALE, DEFAULT_ROUNDING);
    }

    @Override
    public String toString() {
        return amount.toString();
    }

    public String toMoneyString() {
        return amount.setScale(2, DEFAULT_ROUNDING).toString();
    }

    public static void main(String[] args) throws IOException {
    }

}


你可能感兴趣的:(精准的金额类)