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

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

Formats durations as human-readable strings such as
"11 months, 30 days" or "2 hours, 30 minutes, 45 seconds". Parts
are joined with the CLDR unit list pattern matching the format
width, per ECMA-402, not with an "and" conjunction.

Delegates to `Localize.Duration` for the underlying formatting.

Accepts either a `Localize.Duration` struct or a plain map with
duration component keys (matching the JS `DurationFormat` input
shape).

# `format`

```elixir
@spec format(Localize.Duration.t() | map(), Keyword.t()) ::
  {:ok, String.t()} | {:error, term()}
```

Formats a duration according to locale conventions.

### Arguments

* `duration` is a `Localize.Duration` struct or a map with
  any of the keys `:years`, `:months`, `:days`, `:hours`,
  `:minutes`, `:seconds` (plural, matching the JS API), or
  the singular Elixir equivalents `:year`, `:month`, `:day`,
  `:hour`, `:minute`, `:second`.

* `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 `:long`, `:short`, or `:narrow`. The default
  is `:long`.

* Per-unit style options — `:years`, `:months`, `:days`,
  `:hours`, `:minutes`, `:seconds`, `:microseconds` — each
  accept `:long`, `:short`, or `:narrow`, overriding `:style`
  for that unit (JS `hours: "narrow"`).

* Per-unit display options — `:years_display`,
  `:months_display`, `:days_display`, `:hours_display`,
  `:minutes_display`, `:seconds_display`,
  `:microseconds_display` — each accept `:auto` (omit when
  zero, the default) or `:always` (JS `hoursDisplay`).

### Returns

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

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

### Examples

    iex> {:ok, d} = Localize.Duration.new(~D[2019-01-01], ~D[2019-12-31])
    iex> Intl.DurationFormat.format(d, locale: :en)
    {:ok, "11 months, 30 days"}

    iex> Intl.DurationFormat.format(%{hours: 2, minutes: 30}, locale: :en)
    {:ok, "2 hours, 30 minutes"}

    iex> Intl.DurationFormat.format(%{hours: 2}, locale: :en, minutes_display: :always)
    {:ok, "2 hours, 0 minutes"}

    iex> Intl.DurationFormat.format(%{hours: 2, minutes: 30}, locale: :en, hours: :narrow)
    {:ok, "2h, 30 minutes"}

# `format!`

```elixir
@spec format!(Localize.Duration.t() | map(), Keyword.t()) :: String.t() | no_return()
```

Formats a duration, raising on error.

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

### Arguments

* `duration` is a `Localize.Duration` struct or a map.

* `options` is a keyword list of options.

### Returns

* A formatted string.

### Examples

    iex> Intl.DurationFormat.format!(%{hours: 2, minutes: 30}, locale: :en)
    "2 hours, 30 minutes"

# `format_to_parts`

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

Formats a duration into a list of typed parts.

Modelled on the JS `Intl.DurationFormat.formatToParts()`. Each
duration field contributes its unit parts, with the numeric
segments carrying a `:unit` key naming the field; the separators
between fields are `:literal` parts.

### Arguments

* `duration` is a `Localize.Duration` struct or a map with
  duration component keys.

* `options` is a keyword list of options. Accepts the same
  options as `format/2`, including the per-unit style and
  display options.

### Returns

* `{:ok, parts}` where `parts` is a list of
  `%{type: atom, value: String.t()}` maps; numeric parts also
  carry a `:unit` key.

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

### Examples

    iex> Intl.DurationFormat.format_to_parts(%{hours: 2, minutes: 30}, locale: :en)
    {:ok, [
      %{type: :integer, value: "2", unit: :hour},
      %{type: :literal, value: " "},
      %{type: :unit, value: "hours"},
      %{type: :literal, value: ", "},
      %{type: :integer, value: "30", unit: :minute},
      %{type: :literal, value: " "},
      %{type: :unit, value: "minutes"}
    ]}

# `format_to_parts!`

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

Formats a duration into typed parts, raising on error.

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

### Arguments

* `duration` is a `Localize.Duration` struct or a map.

* `options` is a keyword list of options.

### Returns

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

### Examples

    iex> Intl.DurationFormat.format_to_parts!(%{hours: 2}, locale: :en) |> length()
    3

---

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