# `Intl.NumberFormat`
[🔗](https://github.com/elixir-localize/intl/blob/v1.1.0/lib/intl/number_format.ex#L1)

Locale-sensitive number formatting, modelled on
[`Intl.NumberFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat).

Formats numbers as decimals, currencies, percentages, or units
according to locale conventions.

Delegates to `Localize.Number` and `Localize.Unit` for the
underlying formatting.

# `format`

```elixir
@spec format(number() | Decimal.t(), Keyword.t()) ::
  {:ok, String.t()} | {:error, term()}
```

Formats a number according to locale conventions.

### Arguments

* `number` is an integer, float, or `Decimal`.

* `options` is a keyword list of options.

### Options

* `:locale` is a locale identifier string or atom. The default
  is the current process locale.

* `:style` is `:decimal`, `:currency`, `:percent`, or `:unit`.
  The default is `:decimal`.

* `:currency` is a currency code atom (for example, `:USD`,
  `:EUR`). Required when `:style` is `:currency`.

* `:unit` is a unit identifier string (for example, `"kilometer"`,
  `"liter"`). Required when `:style` is `:unit`.

* `:unit_display` is `:long`, `:short`, or `:narrow`. Controls
  how the unit is displayed. The default is `:short`.

* `:notation` is `:standard`, `:scientific`, `:engineering`,
  or `:compact`. When `:compact`, uses abbreviated number
  formatting (for example, "1.2K"). The default is `:standard`.

* `:compact_display` is `:short` or `:long`. Only used when
  `:notation` is `:compact`. The default is `:short`. Compact
  currency formatting always uses the short form since CLDR
  defines no long compact currency format.

* `:currency_display` is `:symbol`, `:narrow_symbol`, `:code`,
  or `:name`. Controls how the currency is presented. The
  default is `:symbol`.

* `:currency_sign` is `:standard` or `:accounting`. When
  `:accounting`, negative currency amounts render in the
  locale's accounting format (for example, "($1,234.50)").
  The default is `:standard`.

* `:use_grouping` is `:always`, `:auto`, `:min2`, `true`, or
  `false`. `:min2` groups only when there are at least two
  digits in a group; `false` disables grouping. The default
  is `:auto`.

* `:sign_display` is `:auto`, `:always`, `:except_zero`,
  `:negative`, or `:never`. Controls when the sign is
  displayed. The default is `:auto`.

* `:minimum_integer_digits` is an integer in `1..21`. The
  integer part is zero-padded to at least this many digits.

* `:minimum_fraction_digits` is a non-negative integer.

* `:maximum_fraction_digits` is a non-negative integer.

* `:minimum_significant_digits` is an integer in `1..21`.

* `:maximum_significant_digits` is an integer in `1..21`.
  When set, significant-digit precision overrides
  fraction-digit precision.

* `:numbering_system` is a CLDR numbering system name (for
  example, `:latn`, `:thai`). Any valid CLDR numbering system
  may be used with any locale, including algorithmic systems
  such as `:roman`.

* `:rounding_increment` is a positive integer. The formatted
  value is rounded to the nearest multiple of this increment.

* `:rounding_mode` is one of `:down`, `:half_up`, `:half_even`,
  `:ceiling`, `:floor`, `:half_down`, `:up`.

* `:rounding_priority` is `:auto`, `:more_precision`, or
  `:less_precision`. Resolves conflicts when both fraction-digit
  and significant-digit options are given. The default is
  `:auto` (significant digits win).

* `:trailing_zero_display` is `:auto` or `:strip_if_integer`.
  When `:strip_if_integer`, fraction digits are dropped if the
  rounded value is an integer. The default is `:auto`.

### Returns

* `{:ok, formatted_string}` on success.

* `{:error, reason}` if options or input are invalid.

### Examples

    iex> Intl.NumberFormat.format(1234.5, locale: :en)
    {:ok, "1,234.5"}

    iex> Intl.NumberFormat.format(0.56, locale: :en, style: :percent)
    {:ok, "56%"}

    iex> Intl.NumberFormat.format(1234.5, locale: :en, style: :currency, currency: :USD)
    {:ok, "$1,234.50"}

    iex> Intl.NumberFormat.format(1234.5, locale: :en, notation: :scientific)
    {:ok, "1.2345E3"}

    iex> Intl.NumberFormat.format(1234, locale: :en, style: :currency, currency: :USD, notation: :compact)
    {:ok, "$1.2K"}

    iex> Intl.NumberFormat.format(-1234.5, locale: :en, style: :currency, currency: :USD, currency_sign: :accounting)
    {:ok, "($1,234.50)"}

    iex> Intl.NumberFormat.format(1234567, locale: :en, use_grouping: false)
    {:ok, "1234567"}

    iex> Intl.NumberFormat.format(1234.5, locale: :en, maximum_significant_digits: 3)
    {:ok, "1,230"}

    iex> Intl.NumberFormat.format(1234.5, locale: :en, sign_display: :always)
    {:ok, "+1,234.5"}

    iex> Intl.NumberFormat.format(1234.5, locale: :en, numbering_system: :thai)
    {:ok, "๑,๒๓๔.๕"}

    iex> Intl.NumberFormat.format(5, locale: :en, minimum_integer_digits: 3)
    {:ok, "005"}

    iex> Intl.NumberFormat.format(1000, locale: :en, minimum_fraction_digits: 2, trailing_zero_display: :strip_if_integer)
    {:ok, "1,000"}

# `format!`

```elixir
@spec format!(number() | Decimal.t(), Keyword.t()) :: String.t() | no_return()
```

Formats a number, raising on error.

Same as `format/2` but returns the string directly or raises.

### Arguments

* `number` is an integer, float, or `Decimal`.

* `options` is a keyword list of options.

### Returns

* A formatted string.

### Examples

    iex> Intl.NumberFormat.format!(1234.5, locale: :en)
    "1,234.5"

# `format_range`

```elixir
@spec format_range(number(), number(), Keyword.t()) ::
  {:ok, String.t()} | {:error, term()}
```

Formats a range of numbers according to locale conventions.

### Arguments

* `number_start` is the start of the range.

* `number_end` is the end of the range.

* `options` is a keyword list of options. Accepts the same
  options as `format/2`, including `style: :unit` with `:unit`
  and `:unit_display` (the unit pattern is applied once to the
  range, "2–5 kilometers").

### Returns

* `{:ok, formatted_string}` on success.

* `{:error, reason}` if options or input are invalid.

### Examples

    iex> Intl.NumberFormat.format_range(100, 200, locale: :en)
    {:ok, "100–200"}

    iex> Intl.NumberFormat.format_range(100, 200, locale: :en, style: :currency, currency: :USD)
    {:ok, "$100.00–$200.00"}

# `format_range!`

```elixir
@spec format_range!(number(), number(), Keyword.t()) :: String.t() | no_return()
```

Formats a range of numbers, raising on error.

Same as `format_range/3` but returns the string directly or raises.

### Arguments

* `number_start` is the start of the range.

* `number_end` is the end of the range.

* `options` is a keyword list of options.

### Returns

* A formatted string.

### Examples

    iex> Intl.NumberFormat.format_range!(100, 200, locale: :en)
    "100–200"

# `format_range_to_parts`

```elixir
@spec format_range_to_parts(number(), number(), Keyword.t()) ::
  {:ok, [%{type: atom(), value: String.t(), source: atom()}]} | {:error, term()}
```

Formats a range of numbers into a list of typed parts.

Modelled on the JS `Intl.NumberFormat.formatRangeToParts()`. In
addition to `:type` and `:value`, each part carries a `:source`
key: `:start_range`, `:end_range`, or `:shared`.

### Arguments

* `number_start` is the start of the range.

* `number_end` is the end of the range.

* `options` is a keyword list of options. Accepts the same
  options as `format/2`, including `style: :unit` (the unit
  pattern text carries source `:shared`).

### Returns

* `{:ok, parts}` where `parts` is a list of
  `%{type: atom, value: String.t(), source: atom}` maps.

* `{:error, reason}` if options or input are invalid.

### Examples

    iex> Intl.NumberFormat.format_range_to_parts(3, 5, locale: :en)
    {:ok, [
      %{type: :integer, value: "3", source: :start_range},
      %{type: :literal, value: "–", source: :shared},
      %{type: :integer, value: "5", source: :end_range}
    ]}

# `format_range_to_parts!`

```elixir
@spec format_range_to_parts!(number(), number(), Keyword.t()) ::
  [%{type: atom(), value: String.t(), source: atom()}] | no_return()
```

Formats a range of numbers into typed parts, raising on error.

Same as `format_range_to_parts/3` but returns the parts directly or raises.

### Arguments

* `number_start` is the start of the range.

* `number_end` is the end of the range.

* `options` is a keyword list of options.

### Returns

* A list of `%{type: atom, value: String.t(), source: atom}` maps.

### Examples

    iex> Intl.NumberFormat.format_range_to_parts!(3, 5, locale: :en) |> length()
    3

# `format_to_parts`

```elixir
@spec format_to_parts(number() | Decimal.t(), Keyword.t()) ::
  {:ok, [%{type: atom(), value: String.t()}]} | {:error, term()}
```

Formats a number into a list of typed parts.

Modelled on the JS `Intl.NumberFormat.formatToParts()`. Each part
is a map with a `:type` and a `:value` key, allowing custom
rendering of individual segments (for example, styling the
currency symbol differently from the digits).

### Arguments

* `number` is an integer, float, or `Decimal`.

* `options` is a keyword list of options. Accepts the same
  options as `format/2`, including `style: :unit` (the unit
  text is a `:unit` part) and `currency_display: :name` (the
  currency name is a `:currency` part).

### Returns

* `{:ok, parts}` on success, where `parts` is a list of
  `%{type: atom, value: String.t()}` maps. Part types include
  `:integer`, `:group`, `:decimal`, `:fraction`, `:currency`,
  `:percent_sign`, `:minus_sign`, `:plus_sign`, `:compact`,
  `:exponent_separator`, `:exponent_integer`, and `:literal`.

* `{:error, reason}` if options or input are invalid.

### Examples

    iex> Intl.NumberFormat.format_to_parts(-1234.5, locale: :en)
    {:ok, [
      %{type: :minus_sign, value: "-"},
      %{type: :integer, value: "1"},
      %{type: :group, value: ","},
      %{type: :integer, value: "234"},
      %{type: :decimal, value: "."},
      %{type: :fraction, value: "5"}
    ]}

    iex> Intl.NumberFormat.format_to_parts(1_500_000, locale: :en, notation: :compact, compact_display: :long)
    {:ok, [
      %{type: :integer, value: "1"},
      %{type: :decimal, value: "."},
      %{type: :fraction, value: "5"},
      %{type: :literal, value: " "},
      %{type: :compact, value: "million"}
    ]}

# `format_to_parts!`

```elixir
@spec format_to_parts!(number() | Decimal.t(), Keyword.t()) ::
  [%{type: atom(), value: String.t()}] | no_return()
```

Formats a number into a list of typed parts, raising on error.

Same as `format_to_parts/2` but returns the parts directly or raises.

### Arguments

* `number` is an integer, float, or `Decimal`.

* `options` is a keyword list of options.

### Returns

* A list of `%{type: atom, value: String.t()}` maps.

### Examples

    iex> Intl.NumberFormat.format_to_parts!(56, locale: :en)
    [%{type: :integer, value: "56"}]

---

*Consult [api-reference.md](api-reference.md) for complete listing*
