money

package module
v1.0.14 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 29, 2024 License: MIT Imports: 8 Imported by: 133

README

Money

alt text

Go Report Card Coverage Status GoDoc

GoMoney provides ability to work with monetary value using a currency's smallest unit. This package provides basic and precise Money operations such as rounding, splitting and allocating. Monetary values should not be stored as floats due to small rounding differences.

package main

import (
  "log"

  "github.com/Rhymond/go-money"
)

func main() {
    pound := money.New(100, money.GBP)
    twoPounds, err := pound.Add(pound)

    if err != nil {
        log.Fatal(err)
    }

    parties, err := twoPounds.Split(3)

    if err != nil {
        log.Fatal(err)
    }

    parties[0].Display() // £0.67
    parties[1].Display() // £0.67
    parties[2].Display() // £0.66
}

Quick start

Get the package:

$ go get github.com/Rhymond/go-money

Features

  • Provides a Money struct which stores information about an Money amount value and its currency.
  • Provides a Money.Amount struct which encapsulates all information about a monetary unit.
  • Represents monetary values as integers, in cents. This avoids floating point rounding errors.
  • Represents currency as Money.Currency instances providing a high level of flexibility.

Usage

Initialization

Initialize Money by using smallest unit value (e.g 100 represents 1 pound). Use ISO 4217 Currency Code to set money Currency. Note that constants are also provided for all ISO 4217 currency codes.

pound := money.New(100, money.GBP)

Or initialize Money using the direct amount.

quarterEuro := money.NewFromFloat(0.25, money.EUR)

Comparison

Go-money provides base compare operations like:

  • Equals
  • GreaterThan
  • GreaterThanOrEqual
  • LessThan
  • LessThanOrEqual
  • Compare

Comparisons must be made between the same currency units.

pound := money.New(100, money.GBP)
twoPounds := money.New(200, money.GBP)
twoEuros := money.New(200, money.EUR)

pound.GreaterThan(twoPounds) // false, nil
pound.LessThan(twoPounds) // true, nil
twoPounds.Equals(twoEuros) // false, error: Currencies don't match
twoPounds.Compare(pound) // 1, nil
pound.Compare(twoPounds) // -1, nil
pound.Compare(pound) // 0, nil
pound.Compare(twoEuros) // pound.amount, ErrCurrencyMismatch

Asserts

  • IsZero
  • IsNegative
  • IsPositive
Zero value

To assert if Money value is equal to zero use IsZero()

pound := money.New(100, money.GBP)
result := pound.IsZero() // false
Positive value

To assert if Money value is more than zero use IsPositive()

pound := money.New(100, money.GBP)
pound.IsPositive() // true
Negative value

To assert if Money value is less than zero use IsNegative()

pound := money.New(100, money.GBP)
pound.IsNegative() // false

Operations

  • Add
  • Subtract
  • Multiply
  • Absolute
  • Negative

Comparisons must be made between the same currency units.

Addition

Additions can be performed using Add().

pound := money.New(100, money.GBP)
twoPounds := money.New(200, money.GBP)

result, err := pound.Add(twoPounds) // £3.00, nil
Subtraction

Subtraction can be performed using Subtract().

pound := money.New(100, money.GBP)
twoPounds := money.New(200, money.GBP)

result, err := pound.Subtract(twoPounds) // -£1.00, nil
Multiplication

Multiplication can be performed using Multiply().

pound := money.New(100, money.GBP)

result := pound.Multiply(2) // £2.00
Absolute

Return absolute value of Money structure

pound := money.New(-100, money.GBP)

result := pound.Absolute() // £1.00
Negative

Return negative value of Money structure

pound := money.New(100, money.GBP)

result := pound.Negative() // -£1.00

Allocation

  • Split
  • Allocate
Splitting

In order to split Money for parties without losing any pennies due to rounding differences, use Split().

After division leftover pennies will be distributed round-robin amongst the parties. This means that parties listed first will likely receive more pennies than ones that are listed later.

pound := money.New(100, money.GBP)
parties, err := pound.Split(3)

if err != nil {
    log.Fatal(err)
}

parties[0].Display() // £0.34
parties[1].Display() // £0.33
parties[2].Display() // £0.33
Allocation

To perform allocation operation use Allocate().

It splits money using the given ratios without losing pennies and as Split operations distributes leftover pennies amongst the parties with round-robin principle.

pound := money.New(100, money.GBP)
// Allocate is variadic function which can receive ratios as
// slice (int[]{33, 33, 33}...) or separated by a comma integers
parties, err := pound.Allocate(33, 33, 33)

if err != nil {
    log.Fatal(err)
}

parties[0].Display() // £0.34
parties[1].Display() // £0.33
parties[2].Display() // £0.33

Format

To format and return Money as a string use Display().

money.New(123456789, money.EUR).Display() // €1,234,567.89

To format and return Money as a float64 representing the amount value in the currency's subunit use AsMajorUnits().

money.New(123456789, money.EUR).AsMajorUnits() // 1234567.89

Contributing

Thank you for considering contributing! Please use GitHub issues and Pull Requests for contributing.

License

The MIT License (MIT). Please see License File for more information.

forthebadge

Documentation

Index

Examples

Constants

View Source
const (
	AED = "AED"
	AFN = "AFN"
	ALL = "ALL"
	AMD = "AMD"
	ANG = "ANG"
	AOA = "AOA"
	ARS = "ARS"
	AUD = "AUD"
	AWG = "AWG"
	AZN = "AZN"
	BAM = "BAM"
	BBD = "BBD"
	BDT = "BDT"
	BGN = "BGN"
	BHD = "BHD"
	BIF = "BIF"
	BMD = "BMD"
	BND = "BND"
	BOB = "BOB"
	BRL = "BRL"
	BSD = "BSD"
	BTN = "BTN"
	BWP = "BWP"
	BYN = "BYN"
	BYR = "BYR"
	BZD = "BZD"
	CAD = "CAD"
	CDF = "CDF"
	CHF = "CHF"
	CLF = "CLF"
	CLP = "CLP"
	CNY = "CNY"
	COP = "COP"
	CRC = "CRC"
	CUC = "CUC"
	CUP = "CUP"
	CVE = "CVE"
	CZK = "CZK"
	DJF = "DJF"
	DKK = "DKK"
	DOP = "DOP"
	DZD = "DZD"
	EEK = "EEK"
	EGP = "EGP"
	ERN = "ERN"
	ETB = "ETB"
	EUR = "EUR"
	FJD = "FJD"
	FKP = "FKP"
	GBP = "GBP"
	GEL = "GEL"
	GGP = "GGP"
	GHC = "GHC"
	GHS = "GHS"
	GIP = "GIP"
	GMD = "GMD"
	GNF = "GNF"
	GTQ = "GTQ"
	GYD = "GYD"
	HKD = "HKD"
	HNL = "HNL"
	HRK = "HRK"
	HTG = "HTG"
	HUF = "HUF"
	IDR = "IDR"
	ILS = "ILS"
	IMP = "IMP"
	INR = "INR"
	IQD = "IQD"
	IRR = "IRR"
	ISK = "ISK"
	JEP = "JEP"
	JMD = "JMD"
	JOD = "JOD"
	JPY = "JPY"
	KES = "KES"
	KGS = "KGS"
	KHR = "KHR"
	KMF = "KMF"
	KPW = "KPW"
	KRW = "KRW"
	KWD = "KWD"
	KYD = "KYD"
	KZT = "KZT"
	LAK = "LAK"
	LBP = "LBP"
	LKR = "LKR"
	LRD = "LRD"
	LSL = "LSL"
	LTL = "LTL"
	LVL = "LVL"
	LYD = "LYD"
	MAD = "MAD"
	MDL = "MDL"
	MGA = "MGA"
	MKD = "MKD"
	MMK = "MMK"
	MNT = "MNT"
	MOP = "MOP"
	MUR = "MUR"
	MRU = "MRU"
	MVR = "MVR"
	MWK = "MWK"
	MXN = "MXN"
	MYR = "MYR"
	MZN = "MZN"
	NAD = "NAD"
	NGN = "NGN"
	NIO = "NIO"
	NOK = "NOK"
	NPR = "NPR"
	NZD = "NZD"
	OMR = "OMR"
	PAB = "PAB"
	PEN = "PEN"
	PGK = "PGK"
	PHP = "PHP"
	PKR = "PKR"
	PLN = "PLN"
	PYG = "PYG"
	QAR = "QAR"
	RON = "RON"
	RSD = "RSD"
	RUB = "RUB"
	RUR = "RUR"
	RWF = "RWF"
	SAR = "SAR"
	SBD = "SBD"
	SCR = "SCR"
	SDG = "SDG"
	SEK = "SEK"
	SGD = "SGD"
	SHP = "SHP"
	SKK = "SKK"
	SLE = "SLE"
	SLL = "SLL"
	SOS = "SOS"
	SRD = "SRD"
	SSP = "SSP"
	STD = "STD"
	STN = "STN"
	SVC = "SVC"
	SYP = "SYP"
	SZL = "SZL"
	THB = "THB"
	TJS = "TJS"
	TMT = "TMT"
	TND = "TND"
	TOP = "TOP"
	TRL = "TRL"
	TRY = "TRY"
	TTD = "TTD"
	TWD = "TWD"
	TZS = "TZS"
	UAH = "UAH"
	UGX = "UGX"
	USD = "USD"
	UYU = "UYU"
	UZS = "UZS"
	VEF = "VEF"
	VES = "VES"
	VND = "VND"
	VUV = "VUV"
	WST = "WST"
	XAF = "XAF"
	XAG = "XAG"
	XAU = "XAU"
	XCD = "XCD"
	XDR = "XDR"
	XOF = "XOF"
	XPF = "XPF"
	YER = "YER"
	ZAR = "ZAR"
	ZMW = "ZMW"
	ZWD = "ZWD"
	ZWL = "ZWL"
)

Constants for active currency codes according to the ISO 4217 standard.

View Source
const (
	// DefaultDBMoneyValueSeparator is the default value for DBMoneyValueSeparator; can be used to reset the
	// active separator value
	DefaultDBMoneyValueSeparator = "|"
)

Variables

View Source
var (
	// UnmarshalJSON is injection point of json.Unmarshaller for money.Money
	UnmarshalJSON = defaultUnmarshalJSON
	// MarshalJSON is injection point of json.Marshaller for money.Money
	MarshalJSON = defaultMarshalJSON

	// ErrCurrencyMismatch happens when two compared Money don't have the same currency.
	ErrCurrencyMismatch = errors.New("currencies don't match")

	// ErrInvalidJSONUnmarshal happens when the default money.UnmarshalJSON fails to unmarshal Money because of invalid data.
	ErrInvalidJSONUnmarshal = errors.New("invalid json unmarshal")
)

Injection points for backward compatibility. If you need to keep your JSON marshal/unmarshal way, overwrite them like below.

money.UnmarshalJSON = func (m *Money, b []byte) error { ... }
money.MarshalJSON = func (m Money) ([]byte, error) { ... }
View Source
var (
	// DBMoneyValueSeparator is used to join together the Amount and Currency components of money.Money instances
	// allowing them to be stored as strings (via the driver.Valuer interface) and unmarshalled as strings (via
	// the sql.Scanner interface); set this value to use a different separator.
	DBMoneyValueSeparator = DefaultDBMoneyValueSeparator
)

Functions

This section is empty.

Types

type Amount

type Amount = int64

Amount is a data structure that stores the amount being used for calculations.

type Currencies

type Currencies map[string]*Currency

func (Currencies) Add added in v1.0.5

func (c Currencies) Add(currency *Currency) Currencies

Add updates currencies list by adding a given Currency to it.

func (Currencies) CurrencyByCode added in v1.0.5

func (c Currencies) CurrencyByCode(code string) *Currency

CurrencyByCode returns the currency given the currency code defined as a constant.

func (Currencies) CurrencyByNumericCode added in v1.0.5

func (c Currencies) CurrencyByNumericCode(code string) *Currency

CurrencyByNumericCode returns the currency given the numeric code defined in ISO-4271.

type Currency

type Currency struct {
	Code        string
	NumericCode string
	Fraction    int
	Grapheme    string
	Template    string
	Decimal     string
	Thousand    string
}

Currency represents money currency information required for formatting.

func AddCurrency added in v0.2.0

func AddCurrency(code, Grapheme, Template, Decimal, Thousand string, Fraction int) *Currency

AddCurrency lets you insert or update currency in currencies list.

func GetCurrency added in v0.3.5

func GetCurrency(code string) *Currency

GetCurrency returns the currency given the code.

func (*Currency) Formatter added in v0.2.0

func (c *Currency) Formatter() *Formatter

Formatter returns currency formatter representing used currency structure.

func (*Currency) Scan added in v1.0.12

func (c *Currency) Scan(src interface{}) error

Scan implements sql.Scanner to deserialize a Currency from a string value read from a database

func (Currency) Value added in v1.0.12

func (c Currency) Value() (driver.Value, error)

Value implements driver.Valuer to serialize a Currency code into a string for saving to a database

type Formatter

type Formatter struct {
	Fraction int
	Decimal  string
	Thousand string
	Grapheme string
	Template string
}

Formatter stores Money formatting information.

func NewFormatter

func NewFormatter(fraction int, decimal, thousand, grapheme, template string) *Formatter

NewFormatter creates new Formatter instance.

func (*Formatter) Format

func (f *Formatter) Format(amount int64) string

Format returns string of formatted integer using given currency template.

func (*Formatter) ToMajorUnits added in v0.4.0

func (f *Formatter) ToMajorUnits(amount int64) float64

ToMajorUnits returns float64 representing the value in sub units using the currency data

type Money

type Money struct {
	// contains filtered or unexported fields
}

Money represents monetary value information, stores currency and amount value.

Example
pound := money.New(100, "GBP")
twoPounds, err := pound.Add(pound)

if err != nil {
	log.Fatal(err)
}

parties, err := twoPounds.Split(3)

if err != nil {
	log.Fatal(err)
}

fmt.Println(parties[0].Display())
fmt.Println(parties[1].Display())
fmt.Println(parties[2].Display())
Output:

£0.67
£0.67
£0.66
Example (Comparisons)
pound := money.New(100, "GBP")
twoPounds := money.New(200, "GBP")
twoEuros := money.New(200, "EUR")

gt, err := pound.GreaterThan(twoPounds)
fmt.Println(gt, err)

lt, err := pound.LessThan(twoPounds)
fmt.Println(lt, err)

eq, err := twoPounds.Equals(twoEuros)
fmt.Println(eq, err)
Output:

false <nil>
true <nil>
false currencies don't match

func New

func New(amount int64, code string) *Money

New creates and returns new instance of Money.

Example
pound := money.New(100, "GBP")

fmt.Println(pound.Display())
Output:

£1.00

func NewFromFloat added in v1.0.9

func NewFromFloat(amount float64, code string) *Money

NewFromFloat creates and returns new instance of Money from a float64. Always rounding trailing decimals down.

func (*Money) Absolute

func (m *Money) Absolute() *Money

Absolute returns new Money struct from given Money using absolute monetary value.

Example
pound := money.New(-100, "GBP")

result := pound.Absolute()
fmt.Println(result.Display())
Output:

£1.00

func (*Money) Add

func (m *Money) Add(ms ...*Money) (*Money, error)

Add returns new Money struct with value representing sum of Self and Other Money.

Example
pound := money.New(100, "GBP")
twoPounds := money.New(200, "GBP")

result, err := pound.Add(twoPounds)
fmt.Println(result.Display(), err)
Output:

£3.00 <nil>

func (*Money) Allocate

func (m *Money) Allocate(rs ...int) ([]*Money, error)

Allocate returns slice of Money structs with split Self value in given ratios. It lets split money by given ratios without losing pennies and as Split operations distributes leftover pennies amongst the parties with round-robin principle.

Example
pound := money.New(100, "GBP")
// Allocate is variadic function which can receive ratios as
// slice (int[]{33, 33, 33}...) or separated by a comma integers
parties, err := pound.Allocate(33, 33, 33)

if err != nil {
	log.Fatal(err)
}

fmt.Println(parties[0].Display())
fmt.Println(parties[1].Display())
fmt.Println(parties[2].Display())
Output:

£0.34
£0.33
£0.33

func (*Money) Amount

func (m *Money) Amount() int64

Amount returns a copy of the internal monetary value as an int64.

func (*Money) AsMajorUnits added in v0.4.0

func (m *Money) AsMajorUnits() float64

AsMajorUnits lets represent Money struct as subunits (float64) in given Currency value

Example
result := money.New(123456789, "EUR").AsMajorUnits()
fmt.Printf("%.2f", result)
Output:

1234567.89

func (*Money) Compare added in v1.0.10

func (m *Money) Compare(om *Money) (int, error)

Compare function compares two money of the same type

if m.amount > om.amount returns (1, nil)
if m.amount == om.amount returns (0, nil
if m.amount < om.amount returns (-1, nil)

If compare moneys from distinct currency, return (m.amount, ErrCurrencyMismatch)

func (*Money) Currency

func (m *Money) Currency() *Currency

Currency returns the currency used by Money.

func (*Money) Display added in v0.1.0

func (m *Money) Display() string

Display lets represent Money struct as string in given Currency value.

Example
fmt.Println(money.New(123456789, "EUR").Display())
Output:

€1,234,567.89

func (*Money) Equals

func (m *Money) Equals(om *Money) (bool, error)

Equals checks equality between two Money types.

func (*Money) GreaterThan

func (m *Money) GreaterThan(om *Money) (bool, error)

GreaterThan checks whether the value of Money is greater than the other.

func (*Money) GreaterThanOrEqual

func (m *Money) GreaterThanOrEqual(om *Money) (bool, error)

GreaterThanOrEqual checks whether the value of Money is greater or equal than the other.

func (*Money) IsNegative

func (m *Money) IsNegative() bool

IsNegative returns boolean of whether the value of Money is negative.

Example
pound := money.New(100, "GBP")
fmt.Println(pound.IsNegative())
Output:

false

func (*Money) IsPositive

func (m *Money) IsPositive() bool

IsPositive returns boolean of whether the value of Money is positive.

Example
pound := money.New(100, "GBP")
fmt.Println(pound.IsPositive())
Output:

true

func (*Money) IsZero

func (m *Money) IsZero() bool

IsZero returns boolean of whether the value of Money is equals to zero.

Example
pound := money.New(100, "GBP")
fmt.Println(pound.IsZero())
Output:

false

func (*Money) LessThan

func (m *Money) LessThan(om *Money) (bool, error)

LessThan checks whether the value of Money is less than the other.

func (*Money) LessThanOrEqual

func (m *Money) LessThanOrEqual(om *Money) (bool, error)

LessThanOrEqual checks whether the value of Money is less or equal than the other.

func (Money) MarshalJSON added in v1.0.0

func (m Money) MarshalJSON() ([]byte, error)

MarshalJSON is implementation of json.Marshaller

func (*Money) Multiply

func (m *Money) Multiply(muls ...int64) *Money

Multiply returns new Money struct with value representing Self multiplied value by multiplier.

Example
pound := money.New(100, "GBP")

result := pound.Multiply(2)
fmt.Println(result.Display())
Output:

£2.00

func (*Money) Negative

func (m *Money) Negative() *Money

Negative returns new Money struct from given Money using negative monetary value.

func (*Money) Round

func (m *Money) Round() *Money

Round returns new Money struct with value rounded to nearest zero.

func (*Money) SameCurrency

func (m *Money) SameCurrency(om *Money) bool

SameCurrency check if given Money is equals by currency.

func (*Money) Scan added in v1.0.12

func (m *Money) Scan(src interface{}) error

Scan implements sql.Scanner to deserialize a Money instance from a DBMoneyValueSeparator-separated string for example: "amount|currency_code"

func (*Money) Split

func (m *Money) Split(n int) ([]*Money, error)

Split returns slice of Money structs with split Self value in given number. After division leftover pennies will be distributed round-robin amongst the parties. This means that parties listed first will likely receive more pennies than ones that are listed later.

Example
pound := money.New(100, "GBP")
parties, err := pound.Split(3)

if err != nil {
	log.Fatal(err)
}

fmt.Println(parties[0].Display())
fmt.Println(parties[1].Display())
fmt.Println(parties[2].Display())
Output:

£0.34
£0.33
£0.33

func (*Money) Subtract

func (m *Money) Subtract(ms ...*Money) (*Money, error)

Subtract returns new Money struct with value representing difference of Self and Other Money.

Example
pound := money.New(100, "GBP")
twoPounds := money.New(200, "GBP")

result, err := pound.Subtract(twoPounds)
fmt.Println(result.Display(), err)
Output:

-£1.00 <nil>

func (*Money) UnmarshalJSON added in v1.0.0

func (m *Money) UnmarshalJSON(b []byte) error

UnmarshalJSON is implementation of json.Unmarshaller

func (*Money) Value added in v1.0.12

func (m *Money) Value() (driver.Value, error)

Value implements driver.Valuer to serialise a Money instance into a delimited string using the DBMoneyValueSeparator for example: "amount|currency_code"

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL