# `Localize.DateTime.Relative`
[🔗](https://github.com/elixir-localize/localize/blob/v1.2.0/lib/localize/datetime/relative.ex#L1)

Formats relative time strings such as "3 days ago", "tomorrow",
or "in 10 seconds".

Supports integer offsets (in seconds), `Date`, `DateTime`,
`NaiveDateTime`, and `Time` structs.

# `known_units`

```elixir
@spec known_units() :: [atom(), ...]
```

Returns the list of known time units.

### Examples

    iex> Localize.DateTime.Relative.known_units()
    [:day, :fri, :hour, :minute, :mon, :month, :quarter, :sat, :second, :sun, :thu, :tue, :wed, :week, :year]

# `to_parts`

```elixir
@spec to_parts(integer() | Date.t() | DateTime.t() | Time.t(), Keyword.t()) ::
  {:ok, [%{type: atom(), value: String.t()}]} | {:error, Exception.t()}
```

Formats a relative time into typed parts, mirroring ECMA-402's `formatToParts` for `Intl.RelativeTimeFormat`.

The parts concatenate to exactly the string `to_string/2` produces with the same options. Named forms ("yesterday") are a single `:literal` part; pattern forms tag the number as an `:integer` part carrying a `:unit` key ("3 days ago" is `:integer` "3" plus `:literal` " days ago"), matching the JS part shape.

### Arguments

* `relative` is an integer, float, `Date`, `Time`, `DateTime`, or `NaiveDateTime`.

* `options` is a keyword list of options.

### Options

See `to_string/2` for the supported options.

### Returns

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

* `{:error, exception}` if the options are invalid.

### Examples

    iex> Localize.DateTime.Relative.to_parts(-1, unit: :day, locale: :en)
    {:ok, [%{type: :literal, value: "yesterday"}]}

    iex> Localize.DateTime.Relative.to_parts(-3, unit: :day, locale: :en)
    {:ok,
     [
       %{type: :integer, value: "3", unit: :day},
       %{type: :literal, value: " days ago"}
     ]}

    iex> Localize.DateTime.Relative.to_parts(1, unit: :day, locale: :en, numeric: :always)
    {:ok,
     [
       %{type: :literal, value: "in "},
       %{type: :integer, value: "1", unit: :day},
       %{type: :literal, value: " day"}
     ]}

# `to_parts!`

```elixir
@spec to_parts!(integer() | Date.t() | DateTime.t() | Time.t(), Keyword.t()) :: [
  %{type: atom(), value: String.t()}
]
```

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

### Arguments

* `relative` is an integer, float, `Date`, `Time`, `DateTime`, or `NaiveDateTime`.

* `options` is a keyword list of options. See `to_parts/2`.

### Returns

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

### Raises

* Raises an exception if the options are invalid.

### Examples

    iex> Localize.DateTime.Relative.to_parts!(-1, unit: :day, locale: :en)
    [%{type: :literal, value: "yesterday"}]

# `to_string`

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

Returns a string representing a relative time for a given
number, date, time, or datetime.

### Arguments

* `relative` is an integer (seconds from now), or a `Date`,
  `DateTime`, `NaiveDateTime`, or `Time` struct.

* `options` is a keyword list of options.

### Options

* `:locale` is a locale identifier. The default is `:en`.

* `:format` is `:standard`, `:narrow`, or `:short`.
  The default is `:standard`.

* `:unit` is the time unit for formatting. One of `:second`,
  `:minute`, `:hour`, `:day`, `:week`, `:month`, `:year`,
  `:mon`, `:tue`, `:wed`, `:thu`, `:fri`, `:sat`, `:sun`,
  `:quarter`. If omitted, a unit is derived automatically.

* `:numeric` is `:auto` or `:always`, mirroring ECMA-402's
  `numeric` option. With `:auto` (the default), named forms
  such as "yesterday" and "tomorrow" are used when the locale
  defines them. With `:always`, output is always numeric:
  "1 day ago" instead of "yesterday".

* `:relative_to` is the baseline date/datetime from which
  the difference is calculated. Defaults to now.

### Returns

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

* `{:error, exception}` on failure.

### Examples

    iex> Localize.DateTime.Relative.to_string(-1, unit: :day, locale: :en)
    {:ok, "yesterday"}

    iex> Localize.DateTime.Relative.to_string(1, unit: :day, locale: :en)
    {:ok, "tomorrow"}

    iex> Localize.DateTime.Relative.to_string(-3, unit: :day, locale: :en)
    {:ok, "3 days ago"}

    iex> Localize.DateTime.Relative.to_string(2, unit: :hour, locale: :en)
    {:ok, "in 2 hours"}

    iex> Localize.DateTime.Relative.to_string(-1, unit: :day, locale: :en, numeric: :always)
    {:ok, "1 day ago"}

    iex> Localize.DateTime.Relative.to_string(1, unit: :day, locale: :en, numeric: :always)
    {:ok, "in 1 day"}

# `to_string!`

```elixir
@spec to_string!(integer() | Date.t() | DateTime.t() | Time.t(), Keyword.t()) ::
  String.t()
```

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

### Options

See `to_string/2` for the supported options.

### Examples

    iex> Localize.DateTime.Relative.to_string!(-3, unit: :day, locale: :en)
    "3 days ago"

    iex> Localize.DateTime.Relative.to_string!(~D[2024-06-14], relative_to: ~D[2024-06-15], locale: :en)
    "yesterday"

---

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