Localize.Number.Parser (Localize v1.2.0)

Copy Markdown View Source

Functions for parsing numbers and currencies from strings in a locale-aware manner.

The parser handles locale-specific digit transliteration, grouping separators, and decimal separators to convert localized number strings back into Elixir numeric values.

Summary

Functions

Finds and replaces substrings from a map at the beginning and/or end of a string.

Parses a string in a locale-aware manner and returns a number.

Maps a list applying a resolver function to each binary element.

Resolves currencies from strings within a list.

Resolves a currency from the beginning and/or end of a string.

Resolves percent or permille from a string.

Resolves percent and permille symbols from strings within a list.

Scans a string in a locale-aware manner and returns a list of strings and numbers.

Types

per()

@type per() :: :percent | :permille

Functions

find_and_replace(string_map, string, fuzzy \\ nil)

@spec find_and_replace(map(), String.t(), float() | nil) ::
  {:ok, list()} | {:error, Exception.t()}

Finds and replaces substrings from a map at the beginning and/or end of a string.

Arguments

  • string_map is a map of %{search_string => replacement}.

  • string is the string to search.

  • fuzzy is an optional float for fuzzy matching.

Returns

  • {:ok, list} with replacements applied.

  • {:error, exception} if no match found.

Examples

iex> Localize.Number.Parser.find_and_replace(%{"usd" => :USD}, "USD 100")
{:ok, [:USD, " 100"]}

iex> Localize.Number.Parser.find_and_replace(%{"%" => :percent}, "11%")
{:ok, ["11", :percent]}

parse(string, options \\ [])

@spec parse(String.t(), Keyword.t()) ::
  {:ok, integer() | float() | Decimal.t()} | {:error, Exception.t()}

Parses a string in a locale-aware manner and returns a number.

Arguments

  • string is any string.

  • options is a keyword list of options.

Options

  • :number is one of :integer, :float, :decimal, or nil. The default is nil (auto-detect).

  • :locale is a locale identifier. The default is :en.

  • :number_system is a number system name or type.

  • :lenient governs how strictly grouping separators must be positioned. true, the default, requires each group to be at least two digits, which is ICU's lenient rule and is what keeps "3 4 5" three numbers rather than one. false requires each group to be exactly the locale's grouping size, so fr takes "1 234 567" and refuses "1 23".

Returns

  • {:ok, number} on success.

  • {:error, exception} if parsing fails.

Examples

iex> Localize.Number.Parser.parse("-1_000_000.34")
{:ok, -1000000.34}

resolve(list, resolver, options)

@spec resolve(list(), (String.t(), Keyword.t() -> term()), Keyword.t()) :: list()

Maps a list applying a resolver function to each binary element.

Arguments

  • list is a list of terms.

  • resolver is a function that takes a string and options.

  • options is a keyword list passed to the resolver.

Options

  • The options are passed through unchanged to resolver for each binary element. See the resolver function (for example resolve_currency/2 or resolve_per/2) for the options it supports.

Returns

  • The list with binary elements resolved.

Examples

iex> resolver = &Localize.Number.Parser.resolve_currency/2
iex> Localize.Number.Parser.resolve(["100", "USD"], resolver, locale: :en)
["100", :USD]

resolve_currencies(list, options \\ [])

@spec resolve_currencies([String.t() | number()], Keyword.t()) :: [
  atom() | String.t() | number()
]

Resolves currencies from strings within a list.

Arguments

  • list is a list of strings and numbers.

  • options is a keyword list of options.

Options

  • :locale is a locale identifier. The default is :en.

  • :only is a filter for currencies to include.

  • :except is a filter for currencies to exclude.

  • :fuzzy is a float for fuzzy matching via String.jaro_distance/2.

Returns

  • A list with currency strings replaced by currency code atoms.

Examples

iex> Localize.Number.Parser.scan("100 US dollars")
...> |> Localize.Number.Parser.resolve_currencies()
[100, :USD]

resolve_currency(string, options \\ [])

@spec resolve_currency(String.t(), Keyword.t()) ::
  [atom() | String.t()] | {:error, Exception.t()}

Resolves a currency from the beginning and/or end of a string.

Arguments

  • string is a string potentially containing a currency name or symbol.

  • options is a keyword list of options.

Options

  • :locale is a locale identifier. The default is :en.

  • :only is a filter for currencies to include.

  • :except is a filter for currencies to exclude.

  • :fuzzy is a float for fuzzy matching.

Returns

  • A list with the currency code and remainder, or {:error, exception}.

Examples

iex> Localize.Number.Parser.resolve_currency("US dollars")
[:USD]

iex> Localize.Number.Parser.resolve_currency("$100")
[:USD, "100"]

resolve_per(string, options \\ [])

@spec resolve_per(String.t(), Keyword.t()) ::
  [per() | String.t()] | {:error, Exception.t()}

Resolves percent or permille from a string.

Arguments

  • string is a string potentially containing percent or permille symbols.

  • options is a keyword list of options.

Options

  • :locale is a locale identifier atom, string, or a Localize.LanguageTag.t/0. The default is Localize.get_locale().

  • :number_system is a number system name or type atom. The default is the number system of :locale.

Returns

  • A list with the symbol replaced by :percent or :permille.

  • {:error, exception} if no symbol found.

Examples

iex> Localize.Number.Parser.resolve_per("11%")
["11", :percent]

resolve_pers(list, options \\ [])

@spec resolve_pers([String.t() | number()], Keyword.t()) :: [
  per() | String.t() | number()
]

Resolves percent and permille symbols from strings within a list.

Arguments

  • list is a list of strings and numbers.

  • options is a keyword list of options.

Options

  • :locale is a locale identifier atom, string, or a Localize.LanguageTag.t/0. The default is Localize.get_locale().

  • :number_system is a number system name or type atom. The default is the number system of :locale.

Returns

  • A list with percent/permille strings replaced by :percent or :permille atoms.

Examples

iex> Localize.Number.Parser.scan("100%")
...> |> Localize.Number.Parser.resolve_pers()
[100, :percent]

scan(string, options \\ [])

@spec scan(String.t(), Keyword.t()) ::
  [String.t() | integer() | float() | Decimal.t()] | {:error, Exception.t()}

Scans a string in a locale-aware manner and returns a list of strings and numbers.

In a locale that groups with a space, a space between digits is read as a grouping separator, which is what lets "1 234,5" be found as one number under fr. The consequence is that adjacent numbers separated by a space can be read as a single number when each run is two digits or more — a list of room numbers or the parts of a phone number among them. Pass lenient: false to require exact grouping sizes, which reads those as separate numbers again:

iex> Localize.Number.Parser.scan("chambres 12 14 16", locale: "fr")
["chambres ", 121416]

iex> Localize.Number.Parser.scan("chambres 12 14 16", locale: "fr", lenient: false)
["chambres ", 12, " ", 14, " ", 16]

Arguments

  • string is any string.

  • options is a keyword list of options.

Options

  • :number is one of :integer, :float, :decimal, or nil. The default is nil (auto-detect).

  • :locale is a locale identifier. The default is :en.

  • :number_system is a number system name or type.

  • :lenient governs how strictly grouping separators must be positioned. true, the default, requires each group to be at least two digits, which is ICU's lenient rule and is what keeps "3 4 5" three numbers rather than one. false requires each group to be exactly the locale's grouping size, so fr takes "1 234 567" and refuses "1 23".

Returns

  • A list of strings and numbers.

Examples

iex> Localize.Number.Parser.scan("The prize is 23")
["The prize is ", 23]

iex> Localize.Number.Parser.scan("1kg")
[1, "kg"]