WIP
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
namespace ROLAC.API.Services.Disbursement;
|
||||
|
||||
/// <summary>
|
||||
/// Converts a monetary amount to the English words used on a check, e.g.
|
||||
/// 1234.56 → "One Thousand Two Hundred Thirty-Four and 56/100 Dollars".
|
||||
/// Pure and dependency-free so it is easily unit-tested.
|
||||
/// </summary>
|
||||
public static class AmountToWords
|
||||
{
|
||||
private static readonly string[] Ones =
|
||||
[
|
||||
"Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine",
|
||||
"Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen",
|
||||
"Seventeen", "Eighteen", "Nineteen",
|
||||
];
|
||||
|
||||
private static readonly string[] Tens =
|
||||
[
|
||||
"", "", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety",
|
||||
];
|
||||
|
||||
// index 1.. → 10^(3*index)
|
||||
private static readonly string[] Scales = ["", "Thousand", "Million", "Billion", "Trillion"];
|
||||
|
||||
public static string Convert(decimal amount)
|
||||
{
|
||||
if (amount < 0) amount = 0m;
|
||||
// Round half-up to cents.
|
||||
amount = Math.Round(amount, 2, MidpointRounding.AwayFromZero);
|
||||
|
||||
var dollars = (long)Math.Floor(amount);
|
||||
var cents = (int)Math.Round((amount - dollars) * 100m, MidpointRounding.AwayFromZero);
|
||||
|
||||
var words = dollars == 0 ? "Zero" : ThreeDigitGroupsToWords(dollars);
|
||||
return $"{words} and {cents:00}/100 Dollars";
|
||||
}
|
||||
|
||||
private static string ThreeDigitGroupsToWords(long n)
|
||||
{
|
||||
// Split into groups of three digits, low to high.
|
||||
var groups = new List<int>();
|
||||
while (n > 0) { groups.Add((int)(n % 1000)); n /= 1000; }
|
||||
|
||||
var parts = new List<string>();
|
||||
for (var i = groups.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (groups[i] == 0) continue;
|
||||
var group = HundredsToWords(groups[i]);
|
||||
var scale = Scales[i];
|
||||
parts.Add(string.IsNullOrEmpty(scale) ? group : $"{group} {scale}");
|
||||
}
|
||||
return string.Join(" ", parts);
|
||||
}
|
||||
|
||||
private static string HundredsToWords(int n)
|
||||
{
|
||||
var parts = new List<string>();
|
||||
if (n >= 100)
|
||||
{
|
||||
parts.Add($"{Ones[n / 100]} Hundred");
|
||||
n %= 100;
|
||||
}
|
||||
if (n >= 20)
|
||||
{
|
||||
var t = Tens[n / 10];
|
||||
var o = n % 10;
|
||||
parts.Add(o == 0 ? t : $"{t}-{Ones[o]}");
|
||||
}
|
||||
else if (n > 0)
|
||||
{
|
||||
parts.Add(Ones[n]);
|
||||
}
|
||||
return string.Join(" ", parts);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user