# `Localize.Duration`
[🔗](https://github.com/elixir-localize/localize/blob/v0.39.0/lib/localize/duration.ex#L1)

Functions to create and format durations — the difference
between two dates, times, or datetimes expressed in calendar
units.

A duration is represented as years, months, days, hours,
minutes, seconds, and microseconds. This is useful for
producing human-readable strings like "11 months and 30 days"
or numeric patterns like "37:48:12".

## Creating durations

* `new/2` — calculates the duration between two dates, times,
  or datetimes.

* `new_from_seconds/1` — creates a duration from a number of
  seconds.

## Formatting durations

* `to_string/2` — formats a duration as a localized string
  using unit names (e.g., "11 months and 30 days") via
  `Localize.Unit` and `Localize.List`.

* `to_time_string/2` — formats the time portion of a duration
  using a pattern like `"hh:mm:ss"`. Hours are unbounded
  (e.g., "37:48:12" for 37 hours).

# `date_or_time_or_datetime`

```elixir
@type date_or_time_or_datetime() ::
  Calendar.date()
  | Calendar.time()
  | Calendar.datetime()
  | Calendar.naive_datetime()
```

A date, time, naive datetime, or datetime.

# `t`

```elixir
@type t() :: %Localize.Duration{
  day: non_neg_integer(),
  hour: non_neg_integer(),
  microsecond: {integer(), 1..6},
  minute: non_neg_integer(),
  month: non_neg_integer(),
  second: non_neg_integer(),
  year: non_neg_integer()
}
```

Duration in calendar units.

# `new`

# `new`

```elixir
@spec new(from :: date_or_time_or_datetime(), to :: date_or_time_or_datetime()) ::
  {:ok, t()} | {:error, Exception.t() | atom()}
```

Calculates the calendar duration between two dates, times, or
datetimes.

### Arguments

* `from` is a date, time, or datetime representing the start.

* `to` is a date, time, or datetime representing the end.

### Returns

* `{:ok, duration}` where `duration` is a `t:t/0` struct.

* `{:error, exception}` if the arguments are incompatible.

### Examples

    iex> {:ok, d} = Localize.Duration.new(~D[2019-01-01], ~D[2019-12-31])
    iex> d.month
    11

    iex> {:ok, d} = Localize.Duration.new(~T[10:00:00], ~T[12:30:45])
    iex> {d.hour, d.minute, d.second}
    {2, 30, 45}

# `new!`

```elixir
@spec new!(from :: date_or_time_or_datetime(), to :: date_or_time_or_datetime()) ::
  t() | no_return()
```

Same as `new/2` but raises on error.

### Examples

    iex> d = Localize.Duration.new!(~D[2019-01-01], ~D[2019-12-31])
    iex> d.month
    11

# `new_from_seconds`

```elixir
@spec new_from_seconds(seconds :: number()) :: t()
```

Creates a duration from a number of seconds.

The duration will contain only hours, minutes, seconds,
and microseconds (year/month/day will be zero).

### Arguments

* `seconds` is a number of seconds (integer or float).

### Returns

* A `t:t/0` struct.

### Examples

    iex> d = Localize.Duration.new_from_seconds(136_092)
    iex> {d.hour, d.minute, d.second}
    {37, 48, 12}

    iex> d = Localize.Duration.new_from_seconds(90.5)
    iex> {d.minute, d.second}
    {1, 30}

# `to_string`

```elixir
@spec to_string(t(), Keyword.t()) :: {:ok, String.t()} | {:error, Exception.t()}
```

Formats a duration as a localized string using unit names.

Non-zero duration parts are formatted as units and joined
with the locale's list conjunction (e.g., "11 months and
30 days").

### Arguments

* `duration` is a `t:t/0` struct.

* `options` is a keyword list of options.

### Options

* `:except` is a list of time unit atoms to omit from
  the output (e.g., `[:microsecond]`). The default is
  `[:microsecond]`.

* `:locale` is a locale identifier. The default is
  `Localize.get_locale()`.

* `:style` is one of `:long`, `:short`, or `:narrow`.
  The default is `:long`.

### Returns

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

* `{:error, exception}` if formatting fails.

### Examples

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

# `to_string!`

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

Same as `to_string/2` but raises on error.

# `to_time_string`

```elixir
@spec to_time_string(t(), Keyword.t()) :: {:ok, String.t()}
```

Formats the time portion of a duration using a numeric
pattern like `"hh:mm:ss"`.

Hours are unbounded — a duration of 37 hours, 48 minutes,
and 12 seconds formats as `"37:48:12"`.

### Arguments

* `duration` is a `t:t/0` struct.

* `options` is a keyword list of options.

### Options

* `:format` is a format pattern string. The default is
  `"hh:mm:ss"`. Use `"h:mm:ss"` for no zero-padding on
  hours, or `"mm:ss"` for minutes and seconds only.

### Returns

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

### Examples

    iex> d = Localize.Duration.new_from_seconds(136_092)
    iex> Localize.Duration.to_time_string(d)
    {:ok, "37:48:12"}

    iex> d = Localize.Duration.new_from_seconds(65)
    iex> Localize.Duration.to_time_string(d, format: "m:ss")
    {:ok, "1:05"}

# `to_time_string!`

```elixir
@spec to_time_string!(t(), Keyword.t()) :: String.t()
```

Same as `to_time_string/2` but raises on error.

---

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