Add Currency type

This commit is contained in:
Aaron Lindsay 2017-04-17 20:11:53 -04:00
parent 9bd9c01962
commit faac776ca4
2 changed files with 120 additions and 0 deletions

View File

@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"github.com/aclindsa/go/src/encoding/xml"
"golang.org/x/text/currency"
"math/big"
"regexp"
"strconv"
@ -321,3 +322,54 @@ func RandomUID() (*UID, error) {
uid := UID(fmt.Sprintf("%08x-%04x-%04x-%04x-%012x", uidbytes[:4], uidbytes[4:6], uidbytes[6:8], uidbytes[8:10], uidbytes[10:]))
return &uid, nil
}
// CurrSymbol represents an ISO-4217 currency
type CurrSymbol struct {
currency.Unit
}
// UnmarshalXML handles unmarshalling a CurrSymbol from an SGML/XML string.
// Leading and trailing whitespace is ignored.
func (c *CurrSymbol) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
var value string
err := d.DecodeElement(&value, &start)
if err != nil {
return err
}
value = strings.TrimSpace(value)
unit, err := currency.ParseISO(value)
if err != nil {
errors.New("Error parsing CurrSymbol:" + err.Error())
}
c.Unit = unit
return nil
}
// MarshalXML marshals a CurrSymbol to SGML/XML
func (c *CurrSymbol) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
return e.EncodeElement(c.String(), start)
}
// Equal returns true if the two Currencies are the same
func (c CurrSymbol) Equal(o CurrSymbol) bool {
return c.String() == o.String()
}
// Valid returns true, nil if the CurrSymbol is valid.
func (c CurrSymbol) Valid() (bool, error) {
if c.String() == "XXX" {
return false, fmt.Errorf("Invalid CurrSymbol: %s", c.Unit)
}
return true, nil
}
func NewCurrSymbol(s string) (*CurrSymbol, error) {
unit, err := currency.ParseISO(s)
if err != nil {
return nil, errors.New("Error parsing string to create new CurrSymbol:" + err.Error())
}
return &CurrSymbol{unit}, nil
}

View File

@ -373,3 +373,71 @@ func TestRandomUID(t *testing.T) {
t.Fatalf("UID generated with RandomUID() doesn't match recommended format: %s\n", err)
}
}
func TestMarshalCurrSymbol(t *testing.T) {
c, _ := ofxgo.NewCurrSymbol("USD")
marshalHelper(t, "USD", &c)
}
func TestUnmarshalCurrSymbol(t *testing.T) {
var overwritten ofxgo.CurrSymbol
c, _ := ofxgo.NewCurrSymbol("USD")
unmarshalHelper(t, "USD", c, &overwritten)
// Make sure stray newlines are handled properly
c, _ = ofxgo.NewCurrSymbol("EUR")
unmarshalHelper(t, "EUR\n", c, &overwritten)
unmarshalHelper(t, "EUR\n\t", c, &overwritten)
}
func TestCurrSymbolEqual(t *testing.T) {
usd1, _ := ofxgo.NewCurrSymbol("USD")
usd2, _ := ofxgo.NewCurrSymbol("USD")
if !usd1.Equal(*usd2) {
t.Fatalf("Two \"USD\" CurrSymbols returned !Equal()\n")
}
xxx, _ := ofxgo.NewCurrSymbol("XXX")
if usd1.Equal(*xxx) {
t.Fatalf("\"USD\" and \"XXX\" CurrSymbols returned Equal()\n")
}
}
func TestCurrSymbolValid(t *testing.T) {
var initial ofxgo.CurrSymbol
ok, err := initial.Valid()
if ok || err == nil {
t.Fatalf("CurrSymbol unexpectedly returned Valid() for initial value\n")
}
ars, _ := ofxgo.NewCurrSymbol("ARS")
ok, err = ars.Valid()
if !ok || err != nil {
t.Fatalf("CurrSymbol unexpectedly returned !Valid() for \"ARS\": %s\n", err.Error())
}
xxx, _ := ofxgo.NewCurrSymbol("XXX")
ok, err = xxx.Valid()
if ok || err == nil {
t.Fatalf("CurrSymbol unexpectedly returned Valid() for \"XXX\"\n")
}
}
func TestNewCurrSymbol(t *testing.T) {
curr, err := ofxgo.NewCurrSymbol("GBP")
if err != nil {
t.Fatalf("Unexpected error calling NewCurrSymbol: %s\n", err)
}
if curr.String() != "GBP" {
t.Fatalf("Created CurrSymbol doesn't print \"GBP\" as string representation\n")
}
curr, err = ofxgo.NewCurrSymbol("AFN")
if err != nil {
t.Fatalf("Unexpected error calling NewCurrSymbol: %s\n", err)
}
if curr.String() != "AFN" {
t.Fatalf("Created CurrSymbol doesn't print \"AFN\" as string representation\n")
}
curr, err = ofxgo.NewCurrSymbol("BLAH")
if err == nil {
t.Fatalf("NewCurrSymbol didn't error on invalid currency identifier\n")
}
}