Last active
January 4, 2023 08:42
-
-
Save nurrony/2bf17cb961ce3592dfccded6c4cf57b3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.math.BigDecimal; | |
import java.math.RoundingMode; | |
import java.text.NumberFormat; | |
import java.util.Arrays; | |
import java.util.Locale; | |
import java.util.function.BinaryOperator; | |
/** | |
* A simple utility class to calculate Money related calculation. It provides | |
* three private properties along with setters and these following default | |
* values | |
* <ul> | |
* <li><code>toPrecision: 2</code></li> | |
* <li><code>locale: java.utils.Locale.US</code></li> | |
* <li><code>roundingMode: java.math.RoundingMode.HALF_EVEN</code></li> | |
* </ul> | |
* | |
* @author Nur Rony | |
* @since v1.0.0 | |
*/ | |
final public class MoneyUtil { | |
private static int toPrecision = 2; | |
private static Locale locale = Locale.US; | |
private static RoundingMode roundingMode = RoundingMode.HALF_EVEN; | |
public static final BigDecimal ONE_HUNDRED = new BigDecimal(100); | |
private MoneyUtil() { | |
throw new IllegalStateException("MoneyUtil Utility Class"); | |
} | |
/** | |
* Converts array of {@link String} to array of {@link BigDecimal} | |
* | |
* @param numbers array of {@link String} | |
* @return {@link BigDecimal[]} | |
* @throws NumberFormatException | |
*/ | |
private static BigDecimal[] toBigDecimalArray(String... numbers) throws NumberFormatException { | |
return Arrays.stream(numbers).sequential().map(BigDecimal::new).toArray(BigDecimal[]::new); | |
} | |
/** | |
* Set precision for calculation | |
* | |
* @param toPrecision precision to set for decimal part | |
*/ | |
public static void setPrecision(int toPrecision) { | |
MoneyUtil.toPrecision = toPrecision; | |
} | |
/** | |
* Set rounding for calculation; defaults: {@link RoundingMode.HALF_EVEN} | |
* | |
* @param roundingMode precision to set for decimal part | |
*/ | |
public static void setRoundingMode(RoundingMode roundingMode) { | |
MoneyUtil.roundingMode = roundingMode; | |
} | |
/** | |
* Format a {@link BigDecimal} number for given locale | |
* | |
* @param number number to format | |
* @param locale locale of the formatted number | |
* @return {@link String} | |
*/ | |
public static String formatToLocale(BigDecimal number, Locale locale) { | |
return NumberFormat.getNumberInstance(locale == null ? MoneyUtil.locale : locale).format(number); | |
} | |
/** | |
* Format a {@link BigDecimal} number for given locale with currency symbol | |
* | |
* @param number number to format | |
* @param locale locale of the formatted number | |
* @return {@link String} | |
*/ | |
public static String formatToCurrency(BigDecimal number, Locale locale) { | |
return NumberFormat.getCurrencyInstance(locale == null ? MoneyUtil.locale : locale).format(number); | |
} | |
/** | |
* Add numbers given as {@link String} | |
* | |
* @param numbers array of {@link String} | |
* @return {@link BigDecimal} | |
* | |
* @see {@link #add(BigDecimal...)} | |
* @see {@link #toBigDecimalArray(String...)} | |
*/ | |
public static BigDecimal add(String... numbers) throws NumberFormatException { | |
return add(toBigDecimalArray(numbers)); | |
} | |
/** | |
* Add numbers given as {@link BigDecimal} | |
* | |
* @param numbers array of {@link BigDecimal} | |
* @return {@link BigDecimal} | |
*/ | |
public static BigDecimal add(BigDecimal... numbers) { | |
return Arrays.stream(numbers).sequential().reduce(BigDecimal.ZERO, BigDecimal::add) | |
.setScale(toPrecision, roundingMode); | |
} | |
/** | |
* Subtracts numbers given as {@link String} | |
* | |
* @param numbers array of {@link String} | |
* @return {@link BigDecimal} | |
* @see {@link #subtract(BigDecimal...)} | |
*/ | |
public static BigDecimal subtract(String... numbers) throws NumberFormatException { | |
return subtract(toBigDecimalArray(numbers)); | |
} | |
/** | |
* Subtracts numbers given as {@link BigDecimal} | |
* | |
* @param numbers arrays of {@link BigDecimal} | |
* @return {@link BigDecimal} | |
*/ | |
public static BigDecimal subtract(BigDecimal... numbers) { | |
BigDecimal[] shiftedArray = Arrays.copyOfRange(numbers, 1, numbers.length); | |
return Arrays.stream(shiftedArray).sequential().reduce(numbers[0], BigDecimal::subtract) | |
.setScale(toPrecision, roundingMode); | |
} | |
/** | |
* Multiplies numbers given as {@link String} | |
* | |
* @param numbers arrays of {@link String} | |
* @return {@link BigDecimal} | |
* @see {@link #multiply(BigDecimal...)} | |
* @see {@link #toBigDecimalArray(String...)} | |
*/ | |
public static BigDecimal multiply(String... numbers) throws NumberFormatException { | |
return multiply(toBigDecimalArray(numbers)); | |
} | |
/** | |
* Multiplies numbers given as {@link BigDecimal} | |
* | |
* @param numbers arrays of {@link BigDecimal} | |
* @return {@link BigDecimal} | |
*/ | |
public static BigDecimal multiply(BigDecimal... numbers) { | |
return Arrays.stream(numbers).sequential().reduce(BigDecimal.ONE, BigDecimal::multiply) | |
.setScale(toPrecision, roundingMode); | |
} | |
/** | |
* Divides numbers given as {@link String} | |
* | |
* @param numbers arrays of {@link String} | |
* @return {@link BigDecimal} | |
* | |
* @see {@link #divide(BigDecimal...)} | |
* @see {@link #toBigDecimalArray(String...)} | |
*/ | |
public static BigDecimal divide(String... numbers) throws NumberFormatException { | |
return divide(toBigDecimalArray(numbers)); | |
} | |
/** | |
* Divides numbers given as {@link BigDecimal} | |
* | |
* @param numbers arrays of {@link BigDecimal} | |
* @return {@link BigDecimal} | |
*/ | |
public static BigDecimal divide(BigDecimal... numbers) { | |
BigDecimal[] shiftedArray = Arrays.copyOfRange(numbers, 1, numbers.length); | |
BinaryOperator<BigDecimal> accumulator = (result, number) -> result.divide(number, 2, roundingMode); | |
return Arrays.stream(shiftedArray).sequential().reduce(numbers[0], accumulator).setScale(toPrecision, roundingMode); | |
} | |
/** | |
* Calculates percentage for given base number | |
* | |
* @param base number to calculate percentage on | |
* @param percentage amount of percentage | |
* @return {@link BigDecimal} | |
* | |
* @see {@link #percentage(BigDecimal, BigDecimal)} | |
*/ | |
public static BigDecimal percentage(String base, String percentage) { | |
return percentage(new BigDecimal(base), new BigDecimal(percentage)); | |
} | |
/** | |
* Calculates percentage for given base number | |
* | |
* @param base number to calculate percentage on | |
* @param percentage amount of percentage | |
* @return {@link BigDecimal} | |
*/ | |
public static BigDecimal percentage(BigDecimal base, BigDecimal percentage) { | |
return (base.multiply(percentage).divide(ONE_HUNDRED)).setScale(toPrecision, roundingMode); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment