Skip to content

Commit

Permalink
add NewFromFloat and NewFromString (#108)
Browse files Browse the repository at this point in the history
  • Loading branch information
npinochet committed Jul 25, 2022
1 parent e9a67ed commit 9a62bed
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 0 deletions.
30 changes: 30 additions & 0 deletions money.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import (
"encoding/json"
"errors"
"fmt"
"math"
"strconv"
"strings"
)

// Injection points for backward compatibility.
Expand Down Expand Up @@ -85,6 +88,33 @@ func New(amount int64, code string) *Money {
}
}

// NewFromFloat creates and returns new instance of Money from a float64.
func NewFromFloat(amount float64, currency string) *Money {
currencyDecimals := math.Pow(10, float64(GetCurrency(currency).Fraction))
return New(int64(amount*currencyDecimals), currency)
}

// NewFromFloat creates and returns new instance of Money from a float64.
func NewFromString(amount string, currency string) (*Money, error) {
amount = strings.Trim(amount, "0")

var exponent int
if pointIndex := strings.Index(amount, "."); pointIndex != -1 {
exponent = len(amount[pointIndex+1:])
}

intString := strings.ReplaceAll(amount, ".", "")
parsed, err := strconv.ParseInt(intString, 10, 64)
if err != nil {
return nil, fmt.Errorf("can't parse '%s' to money", amount)
}

currencyFraction := GetCurrency(currency).Fraction
parsed /= int64(math.Pow(10, float64(exponent-currencyFraction)))

return New(parsed, currency), nil
}

// Currency returns the currency used by Money.
func (m *Money) Currency() *Currency {
return m.currency
Expand Down
50 changes: 50 additions & 0 deletions money_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,56 @@ func TestMoney_Amount(t *testing.T) {
}
}

func TestNewFromFloat(t *testing.T) {
m := NewFromFloat(12.34, EUR)

if m.amount.val != 1234 {
t.Errorf("Expected %d got %d", 1234, m.amount.val)
}

if m.currency.Code != EUR {
t.Errorf("Expected currency %s got %s", EUR, m.currency.Code)
}

m = NewFromFloat(-0.123, EUR)

if m.amount.val != -12 {
t.Errorf("Expected %d got %d", -12, m.amount.val)
}
}

func TestNewFromString(t *testing.T) {
m, err := NewFromString("12.34", EUR)

if err != nil {
t.Error(err)
}

if m.amount.val != 1234 {
t.Errorf("Expected %d got %d", 1234, m.amount.val)
}

if m.currency.Code != EUR {
t.Errorf("Expected currency %s got %s", EUR, m.currency.Code)
}

m, err = NewFromString("-1.12345", EUR)

if err != nil {
t.Error(err)
}

if m.amount.val != -112 {
t.Errorf("Expected %d got %d", -112, m.amount.val)
}

_, err = NewFromString("invalid_input", EUR)

if err.Error() != "can't parse 'invalid_input' to money" {
t.Error(err)
}
}

func TestDefaultMarshal(t *testing.T) {
given := New(12345, IQD)
expected := `{"amount":12345,"currency":"IQD"}`
Expand Down

0 comments on commit 9a62bed

Please sign in to comment.