Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/bojanz/currency
Currency handling for Go.
https://github.com/bojanz/currency
Last synced: 13 days ago
JSON representation
Currency handling for Go.
- Host: GitHub
- URL: https://github.com/bojanz/currency
- Owner: bojanz
- License: mit
- Created: 2020-04-16T15:34:39.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2024-04-19T16:17:28.000Z (7 months ago)
- Last Synced: 2024-07-31T20:51:29.100Z (3 months ago)
- Language: Go
- Homepage: https://pkg.go.dev/github.com/bojanz/currency
- Size: 104 KB
- Stars: 518
- Watchers: 6
- Forks: 41
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-go - currency - Handles currency amounts, provides currency information and formatting. (Financial / Search and Analytic Databases)
- awesome-tech-list - bojanz/currency - Handles currency amounts, provides currency information and formatting. Powered by CLDR v42, in just ~30kb of data (Golang)
- awesome-go-extra - currency - 04-16T15:34:39Z|2022-07-14T12:25:03Z| (Financial / Advanced Console UIs)
README
# currency [![Build](https://github.com/bojanz/currency/actions/workflows/build.yml/badge.svg)](https://github.com/bojanz/currency/actions/workflows/build.yml) [![Coverage Status](https://coveralls.io/repos/github/bojanz/currency/badge.svg?branch=master)](https://coveralls.io/github/bojanz/currency?branch=master) [![Go Report Card](https://goreportcard.com/badge/github.com/bojanz/currency)](https://goreportcard.com/report/github.com/bojanz/currency) [![PkgGoDev](https://pkg.go.dev/badge/github.com/bojanz/currency)](https://pkg.go.dev/github.com/bojanz/currency)
Handles currency amounts, provides currency information and formatting.
Powered by CLDR v45, in just ~30kb of data.
Backstory: https://bojanz.github.io/price-currency-handling-go/
## Features
1. All currency codes, their numeric codes and fraction digits.
2. Currency symbols and formats for all locales.
3. Country mapping (country code => currency code).
4. Amount struct, with value semantics (Fowler's Money pattern)
5. Formatter, for formatting amounts and parsing formatted amounts.```go
amount, _ := currency.NewAmount("275.98", "EUR")
total, _ := amount.Mul("4")locale := currency.NewLocale("fr")
formatter := currency.NewFormatter(locale)
fmt.Println(formatter.Format(total)) // 1 103,92 €// Convert the amount to Iranian rial and show it in Farsi.
total, _ = total.Convert("IRR", "45.538")
total = total.Round()
locale = currency.NewLocale("fa")
formatter = currency.NewFormatter(locale)
fmt.Println(formatter.Format(total)) // ریال ۵۰٬۲۷۰
```## Design goals
### Real decimal implementation under the hood.
Currency amounts can't be floats. Storing integer minor units (2.99 => 299)
becomes problematic once there are multiple currencies (difficult to sort in the
DB), or there is a need for sub-minor-unit precision (due to merchant or tax
requirements, etc). A real arbitrary-precision decimal type is required. Since
Go doesn't have one natively, a userspace implementation is used, provided by
the [cockroachdb/apd](https://github.com/cockroachdb/apd) package. The Amount struct provides an easy to use
abstraction on top of it, allowing the underlying implementation to be replaced
in the future without a backwards compatibility break.### Smart filtering of CLDR data.
The "modern" subset of CLDR locales is used, reducing the list from ~560 to ~370 locales.
Once gathered, locales are filtered to remove all data not used by this package,
and then deduplicated by parent (e.g. don't keep `fr-CH` if `fr` has the
same data).Currency symbols are grouped together to avoid repetition. For example:
"ARS": {
{"ARS", []string{"en", "fr-CA"}},
{"$", []string{"es-AR"}},
{"$AR", []string{"fr"}},
}Currency names are not included because they are rarely shown, but need
significant space. Instead, they can be fetched on the frontend via [Intl.DisplayNames](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DisplayNames).### Easy to compare.
Amount structs can be compared via [google/go-cmp](https://github.com/google/go-cmp) thanks to the built-in Equal() method.
### Usable with a PostgreSQL composite type.
Thanks to the driver.Valuer and sql.Scanner interfaces, applications using the [pgx](https://github.com/jackc/pgx) driver can store amounts in a composite type.
Example schema:
```
CREATE TYPE price AS (
number NUMERIC,
currency_code TEXT
);CREATE TABLE products (
id CHAR(26) PRIMARY KEY,
name TEXT NOT NULL,
price price NOT NULL,
created_at TIMESTAMPTZ NOT NULL,
updated_at TIMESTAMPTZ
);
```
Note that the number and currency_code columns can have any name, only their ordering matters.Example struct:
```go
type Product struct {
ID string
Name string
Price currency.Amount
CreatedAt time.Time
UpdatedAt time.Time
}
```Example scan:
```go
p := Product{}
row := tx.QueryRow(ctx, `SELECT id, name, price, created_at, updated_at FROM products WHERE id = $1`, id)
err := row.Scan(&p.ID, &p.Name, &p.Price, &p.CreatedAt, &p.UpdatedAt)
```See our [database integration notes](https://github.com/bojanz/currency/wiki/Database-integration-notes) for other examples (MySQL/MariaDB, SQLite).