kip

kip

ex_cldr Core Team

Ex_money - money with currency type

ex_money is a package to manage a money data type and provide localised formatting, arithmetic, exchange rates, basic financial calculations and serialization with a special attention on preserving precision.

CLDR data drives the localisation capabilities. As a result ex_money knows about each currencies precision, separators, grouping and symbols in any of about 500 locales.

Version 3.2.4 is out this week with a new ability to parse money strings. Some examples follow:

  # These are the strings available for a given currency
  # and locale that are recognised during parsing
  iex> Cldr.Currency.strings_for_currency :AUD, "de"
  ["aud", "au$", "australischer dollar", "australische dollar"]

  # Parsing can be localised
  iex> Money.parse "12 346 dollar australien", locale: "fr"
  #Money<:AUD, 12346>

  iex> Money.parse "A$ 12346", locale: "en"
  #Money<:AUD, 12346>

  # Note that the decimal separator in the "de" locale
  # is a `.`
  iex> Money.parse "AU$ 12346,45", locale: "de"
  #Money<:AUD, 12346.45>

  # Round trip formatting is supported
  iex> {:ok, string} = Cldr.Number.to_string 1234, Money.Cldr, currency: :AUD
  {:ok, "A$1,234.00"}
  iex> Money.parse string
  #Money<:AUD, 1234.00>

  # Fuzzy matching is possible
  iex> Money.parse("100 eurosports", fuzzy: 0.8)
  #Money<:EUR, 100>

  iex> Money.parse("100 eurosports", fuzzy: 0.9)
  {:error,
   {Money.Invalid, "Unable to create money from \"eurosports\" and \"100\""}}

  # Eligible currencies can be filtered by type
  iex> Money.parse("100 eurosports", fuzzy: 0.8, currency_filter: [:current, :tender])
  #Money<:EUR, 100>

Most Liked

kip

kip

ex_cldr Core Team

ex_money just hit a million downloads on hex.pm. Small beer in comparison to its older sibling money but still - thank you to everyone who has found value in it and given it your support.

First commit was June 19, 2016 so it’s been seven years in the making :slight_smile: The last release was 3 weeks ago and there have been no issues raised since March. So its in good shape, still under active support and feature requests are always welcome.

kip

kip

ex_cldr Core Team

ex_money 5.0.0 is released today. The main focus is supporting the new Elixir 1.10 Enum.sort/2 functionality that greatly helps express semantic sorting for structs like money, dates and so on.

Enum.sort/2 example

iex> list = [Money.new(:USD, 100), Money.new(:USD, 200)]
[#Money<:USD, 100>, #Money<:USD, 200>]
iex> Enum.sort list, Money
[#Money<:USD, 100>, #Money<:USD, 200>]
iex> Enum.sort list, {:asc, Money}
[#Money<:USD, 100>, #Money<:USD, 200>]
iex> Enum.sort list, {:desc, Money}
[#Money<:USD, 200>, #Money<:USD, 100>]

Breaking Changes

In order to support the new Enum.sort/2, the Money.compare/2 function needs to return :lt, :gt or :eq. Previous releases of Money.compare/2 return 1, 0 or -1 following the model set by Decimal.

In ex_money version 5.0.0, the returns from Money.compare/2 and Money.cmp/2 are swapped to now align with what Elixir expects.

Users of ex_money will need to replace calls to Money.cmp/2 with calls to Money.compare/2. Similarly, calls to Money.compare/2 should be replaced with calls to Money.cmp/2.

Relationship to the Decimal library

decimal is going through the same transition with its releases 1.9 and 2.0. The changes to ex_money have been tested on all releases of decimal from 1.6 up to 1.9.0-rc.0 and on decimal master branch which is 2.0.0-dev. The plan is that no new releases of ex_money should be required to support any modern decimal release.

Links

kip

kip

ex_cldr Core Team

ex_money version 5.11.0 has been published. This release adds support for ISO 24165 digital tokens (crypto currencies. The changelog entry is:

Money Enhancements

  • Adds support for ISO 24165 Digital Tokens (crypto currency). Digital Token-based money behaves the same as currency-based money with the following exceptions due to limited data availability:

    • Digital token names are not localized (there is no localised data available in CLDR)
    • Digital token names are not pluralized (also because there is no localised data available)
    • Digital token amounts are never rounded (there is no data available to standardise on rounding rules or the number of fractional digits to round to)

ex_money version 2.11.0 depends on ex_cldr_numbers 2.27.0 that provides the support for formatting numbers and currencies. The changelog entry is:

Cldr Numbers Enhancements

  • Add support for formatting numbers representing ISO 24165 Digital Tokens (aka crypto currencies). The behaviour follows that for currency formatting. Given that the digital token registry does not contain fraction precision data or pluralised or localised token names, the formatting of digital tokens amounts is not localized beyond formatting the number itself.
peerreynders

peerreynders

I think money_sql is a great example of an Ecto custom type working in concert with a DB-side user defined type (in this case a composite type).

https://github.com/kipcole9/money_sql/blob/master/lib/money/ecto/money_ecto_composite_type.ex

kip

kip

ex_cldr Core Team

ex_money version 5.1.0 is out today with a primary focus on parsing strings that have a money amount and a currency. In addition, exchange rate HTTPS requests now properly verify the certificate.

In prior versions, parsing a string that had no currency detected would error:

iex> Money.parse("100")
{:error, {Money.Invalid,
  "A currency code, symbol or description must be specified but was not found in \"100\""}}

In this version, the locale of the current process or the provided locale will be used to derive the currency in use for that locale if no currency is detected in the string. For example:

# Specifying a locale will derive the
# currency if none if detected in the
# string
iex> Money.parse("100", locale: "en")
#Money<:USD, 100>

# If no `:locale` is specified the locale of the current
# process is used which should simplify a lot
# of workflows
iex> Money.parse("100")
#Money<:USD, 100>

iex> Money.parse("100", locale: "en-AU")
#Money<:AUD, 100>

iex> assert Money.parse("100", locale: "de")
#Money<:EUR, 100>

# Traditional Chinese in HK implies HK dollars
hex> Money.parse("100", locale: "zh-Hant-hk")                                                                  
#Money<:HKD, 100>

# Traditional Chinese implies New Taiwan dollars
iex> Money.parse("100", locale: "zh-Hant")   
#Money<:TWD, 100>

# Simplified Chinese implies Chinese RMB
iex> Money.parse("100", locale: "zh-Hans")
#Money<:CNH, 100>

# of course detecting the currency in the
# string still applies
iex> Money.parse("12346.45 Australian dollars")
#Money<:AUD, 12346.45>

# Using the locale to derive the currency can be
# disabled by setting `default_currency: false`
# ie the actual `false`, not `nil`
iex> Money.parse("100", default_currency: false) ==
{:error, {Money.Invalid,
  "A currency code, symbol or description must be specified but was not found in \"100\""}}

Bonus content

If you got this far, then thanks! Here’s how the regional override and currency in a more complex language tag interacts with currency parsing:

# A locale that has a regional override. The regional override
# takes precedence and hence the currency is USD
iex> Money.parse("100", locale: "zh-Hans-u-rg-uszzzz")    
#Money<:USD, 100>

# A locale that has a regional override and a currency
# override uses the currency override as precedent over
# the regional override. In this case, EUR
iex> Money.parse("100", locale: "zh-Hans-u-rg-uszzzz-cu-eur") 
#Money<:EUR, 100>

Where Next?

Popular in Libraries Top

gjaldon
As the title states, EctoEnum has just been updated after some time of hardly any activity in the repo. Here’s the latest release: https:...
New
deadtrickster
I’ve just released stable versions of my Prometheus Elixir libs: Elixir client [docs]; Ecto collector [docs]; Plugs instrumenter/Export...
New
tmbb
I’ve published the first version of my Makeup library. It’s a syntax highlighter for Elixir in the spirit of Pygments, Currently it highl...
New
martinthenth
Hello everybody :wave: Recently, some of my colleagues talked about database ids and uuids and their problems, and I remembered the pain...
New
mattludwigs
Grizzly is a library for working with Z-Wave devices. Z-Wave is a low-frequency radio protocol for controlling smart home devices on a me...
New
anshuman23
Hello all, I have been working on my proposed project called Tensorflex as part of Google Summer of Code 2018.. Tensorflex can be used f...
New
wojtekmach
Hey everyone! Req is an HTTP client for Elixir that I’ve been working on for quite some time. There is already a lot of HTTP clients out...
New
ostinelli
Let’s write a database! Well not really, but I think it’s a little sad that there doesn’t seem to be a simple in-memory distributed KV da...
New
mplatts
With HEEX released we decided to start a components library using Tailwind CSS - check it out here: Petal Components. We also have a boi...
New
New

Other popular topics Top

lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list....
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: https://hexdocs.pm/ecto/Ecto.Schema.html#module-...
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
AstonJ
by Lance Halvorsen Elixir and Phoenix are generating tremendous excitement as an unbeatable platform for building modern web application...
460 27162 124
New

Sub Categories:

We're in Beta

About us Mission Statement