Skip to content

Instantly share code, notes, and snippets.

@17twenty
Created March 2, 2020 03:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 17twenty/85fe0168d7921ef400f1f57b4541a422 to your computer and use it in GitHub Desktop.
Save 17twenty/85fe0168d7921ef400f1f57b4541a422 to your computer and use it in GitHub Desktop.
Accounting and Formatting for Golang Shopspring decimal library
package quicka
import (
"fmt"
"strings"
"github.com/shopspring/decimal"
)
// FormatMoneyDecimal ...
func FormatMoneyDecimal(value decimal.Decimal) string {
return FormatNumberDecimal(value, ".", ",", 2, "$")
}
// FormatNumberDecimal ...
func FormatNumberDecimal(value decimal.Decimal, decimalStr string, thousandStr string, precision int, currencyPrefix string) string {
if value.Equal(decimal.Zero) || value.Equal(decimal.Zero.Neg()) {
return fmt.Sprintf("%s0%s00", currencyPrefix, decimalStr)
}
reFormat := value.StringFixed(int32(precision))
// At this point we have -XXXXXXX.YY so remove neg and get our heads and trails
isNeg := false
if reFormat[0] == '-' {
reFormat = strings.ReplaceAll(reFormat, "-", "")
isNeg = true
}
decs := reFormat[strings.Index(reFormat, "."):]
integral := reFormat[:strings.Index(reFormat, ".")]
// Add the commas
for i := len(integral) - 3; i > 0; i -= 3 {
integral = integral[:i] + thousandStr + integral[i:]
}
finalValue := currencyPrefix + integral + decimalStr + decs[1:]
if isNeg {
finalValue = "-" + finalValue
}
return finalValue
}
package quicka
import (
"testing"
"github.com/shopspring/decimal"
)
func must(s string) decimal.Decimal {
d, _ := decimal.NewFromString(s)
return d
}
func TestFormatMoneyDecimal(t *testing.T) {
tests := []struct {
given string
expected string
}{
{"123.499", "$123.50"},
{"3456.615", "$3,456.62"},
{"777888.99", "$777,888.99"},
{"-77788821412412444424.99", "-$77,788,821,412,412,444,424.99"},
{"-5432", "-$5,432.00"},
{"-1234567", "-$1,234,567.00"},
{"0", "$0.00"},
{"0.212", "$0.21"},
{"-0.0", "$0.00"},
}
for _, tt := range tests {
if got := FormatMoneyDecimal(must(tt.given)); got != tt.expected {
t.Errorf("FormatMoneyDecimal() = %v, want %v", got, tt.expected)
}
}
}
func TestFormatMoneyFromDecimal(t *testing.T) {
tests := []struct {
given decimal.Decimal
expected string
}{
{must("123.5"), "$123.50"},
{must("3456.615"), "$3,456.62"},
{must("777888.99"), "$777,888.99"},
{must("-5432"), "-$5,432.00"},
{must("-1234567"), "-$1,234,567.00"},
{must("0"), "$0.00"},
{must("0.212"), "$0.21"},
{must("-0.0"), "$0.00"},
}
for _, tt := range tests {
if got := FormatMoneyDecimal(tt.given); got != tt.expected {
t.Errorf("FormatMoneyDecimal() = %v, want %v", got, tt.expected)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment