# `Cldr.DateTime.Relative`
[🔗](https://github.com/elixir-cldr/cldr_dates_times/blob/v2.25.6/lib/cldr/datetime/relative.ex#L1)

Functions to support the string formatting of relative date/time/datetime numbers.

This module provides formatting of numbers (as integers, floats, Dates, Times or DateTimes)
as "ago" or "in" with an appropriate time unit.  For example, "2 days ago" or
"in 10 seconds"

# `default_unit_steps`
*since 2.25.0* 

Returns the default map of unit steps.

# `derive_unit_from`

An example implementation of a function to derive an appropriate
time unit for a relative time.

### Arguments

* `relative`, the first argument provided to `to_string/3`.

* `relative_to` the value of option `:relative_to` provided to `to_string/3`
  or its default value.

* `time_difference` is the difference in seconds between `relative`
  and `relative_to`.

* `unit` being the requested time unit which may be `nil`. If `nil` then
  the time unit must be derived and the `time_difference` scaled to that
  time unit. If specified then the `time_difference` must be scaled to
  that time unit.

### Returns

* `{relative, unit}` where `relative` is the integer value of the
  derived and scaled time unit. `unit` is the derived or given time unit.

### Notes

* In [this implementation](https://github.com/elixir-cldr/cldr_dates_times/blob/main/lib/cldr/datetime/relative.ex#L390-L467)
  the time difference is used to derive seconds, minutes, hours, days and weeks.
  The `:month` and `:year` fields of the the `relative` struct are used to derive months
  and years.

# `known_formats`

# `known_styles`

> This function is deprecated. Use known_formats/0.

# `known_units`

Returns a list of the valid unit keys for `to_string/2`

## Example

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

# `scale_relative`

Calculates the time span in the given `unit` from the time given in seconds.

## Examples

    iex> Cldr.DateTime.Relative.scale_relative(1234, :second)
    1234

    iex> Cldr.DateTime.Relative.scale_relative(1234, :minute)
    21

    iex> Cldr.DateTime.Relative.scale_relative(1234, :hour)
    0

# `to_string`

```elixir
@spec to_string(
  integer() | float() | Date.t() | DateTime.t(),
  Cldr.backend(),
  Keyword.t()
) ::
  {:ok, String.t()} | {:error, {module(), String.t()}}
```

Returns a string representing a relative time (ago, in) for a given
number, date, time or datetime.

### Arguments

* `relative` is an integer or `t:Calendar.datetime/0`, `t:Calendar.date/0`, or
  `t:Calendar.time/0` representing the time distance from `now` or from
  `options[:relative_to]`.

* `backend` is any module that includes `use Cldr` and therefore
  is a `Cldr` backend module. The default is `Cldr.default_backend/0`.

* `options` is a `t:Keyword.t/0` list of options.

### Options

* `:locale` is any valid locale name returned by `Cldr.known_locale_names/0`
  or a `t:Cldr.LanguageTag.t/0` struct.  The default is `Cldr.get_locale/0`.

* `:format` is the type of the formatted string.  Allowable values are `:standard`,
  `:narrow` or `:short`. The default is `:standard`.

* `:style` determines whether to return a standard relative string ("tomorrow") or
  an "at" string ("tomorrow at 3:00 PM"). The supported values are `:standard` (the default)
  or `:at`.  Note that `style: :at` is only applied when:

  * `:unit` is not a time unit (ie not `:hour`, `:minute` or :second`)
  * *and* when `:relative` is a `t:Calendar.datetime/0` or
  * *or* the `:at` option is set to a `t:Calendar.time/0`

* `:unit` is the time unit for the formatting.  The allowable units are `:second`, `:minute`,
  `:hour`, `:day`, `:week`, `:month`, `:year`, `:mon`, `:tue`, `:wed`, `:thu`, `:fri`, `:sat`,
  `:sun`, `:quarter`. If no `:unit` is specified, one will be derived using the
  `:derive_unit_from` option.

* `:relative_to` is the baseline `date` or `datetime` from which the difference
  from `relative` is calculated when `relative` is a `t:Calendar.date/0` or a
  `t:Calendar.datetime/0`. The default for a `t:Calendar.date/0` is `Date.utc_today/0`;
  for a `t:Calendar.datetime/0` it is `DateTime.utc_now/0` and for a t:Calendar.time/0` it
  is `Time.utc_now/0`.

* `:time` is any `t:Calendar.time/0` that is used when `style: :at` is being applied. The
  default is to use the time component of `relative`.

* `:time_format` is the format option to be passed to `Cldr.Time.to_string/3` if the `:style`
  option is `:at` and `relative` is a `t:Calendar.datetime/0` or the `:time` option is set.
  The default is `:short`.

* `:at_format` is one of `:short`, `:medium`, `:long` or `:full`. It is used to determine the
  format joining together the `relative` string and the `:time` string when `:style` is `:at.
  The default is `:short` if `:format` is either `:short` or `:narrow`. Otherwise the
  default is `:medium`.

* `:derive_unit_from` is used to derive the most appropriate time unit if none is provided.
  There are two ways to specify `:derive_unit_from`.

  * The first option is a map. The map is required to have the keys `:second`, `:minute`, `:hour`,
    `:day`, `:week`, `:month`, and `:year` with the values being the number of seconds below
    which the key defines the time unit difference. This is the default and its value is:

    %{second: 1, month: 2629743.83, day: 86400, year: 31556926, minute: 60, hour: 3600, week: 604800}

  * The second option is to specify a function reference. The function must take four
    arguments as described below.

#### The :derive_unit_from` *map*

* Any `:derive_unit_from` map is first merged into the default map. This means that developers
  can use the default values and override only specific entries by providing a sparse map.

* Any entry in the `:derive_unit_from` map that has a value of `nil` is ignored. This has the
  result that any key set to `nil` will never be represented in the output.

* Any entry in the `:derive_unit_from` map that has the value `:infinity` will always be the
  largest time unit used to represent the relative time.

#### The :derive_unit_from *function*

* The function must take four arguments:
  * `relative`, being the first argument to `to_string/3`.
  * `relative_to` being the value of option `:relative_to` or its default value.
  * `time_difference` being the difference in seconds between `relative`
    and `relative_to`.
  * `unit` being the requested time unit which may be `nil`. If `nil` then
    the time unit must be derived and the `time_difference` scaled to that
    time unit. If specified then the `time_difference` must be scaled to
    the specified time unit.

* The function must return a tuple of the form `{relative, unit}` where
  `relative` is an integer value and `unit` is the appropriate time unit atom.

* See the `Cldr.DateTime.Relative.derive_unit_from/4` function for an example.

### Returns

* `{:ok, formatted_string}` or

* `{:error, {exception, reason}}`

### Examples

    iex> Cldr.DateTime.Relative.to_string(-1, MyApp.Cldr)
    {:ok, "1 second ago"}

    iex> Cldr.DateTime.Relative.to_string(1, MyApp.Cldr)
    {:ok, "in 1 second"}

    iex> Cldr.DateTime.Relative.to_string(1, MyApp.Cldr, unit: :day)
    {:ok, "tomorrow"}

    iex> Cldr.DateTime.Relative.to_string(1, MyApp.Cldr, unit: :day, locale: :fr)
    {:ok, "demain"}

    iex> Cldr.DateTime.Relative.to_string(2, MyApp.Cldr, unit: :day, locale: :de)
    {:ok, "übermorgen"}

    iex> Cldr.DateTime.Relative.to_string(-2, MyApp.Cldr, unit: :day, locale: :de)
    {:ok, "vorgestern"}

    iex> Cldr.DateTime.Relative.to_string(1, MyApp.Cldr, unit: :day, format: :narrow)
    {:ok, "tomorrow"}

    iex> Cldr.DateTime.Relative.to_string(1234, MyApp.Cldr, unit: :year)
    {:ok, "in 1,234 years"}

    iex> Cldr.DateTime.Relative.to_string(1234, MyApp.Cldr, unit: :year, locale: :fr)
    {:ok, "dans 1 234 ans"}

    iex> Cldr.DateTime.Relative.to_string(31, MyApp.Cldr)
    {:ok, "in 31 seconds"}

    iex> Cldr.DateTime.Relative.to_string(~D[2017-04-29], MyApp.Cldr, relative_to: ~D[2017-04-26])
    {:ok, "in 3 days"}

    iex> Cldr.DateTime.Relative.to_string(310, MyApp.Cldr, format: :short, locale: :fr)
    {:ok, "dans 5 min"}

    iex> Cldr.DateTime.Relative.to_string(310, MyApp.Cldr, format: :narrow, locale: :fr)
    {:ok, "+5 min"}

    iex> Cldr.DateTime.Relative.to_string(2, MyApp.Cldr, unit: :wed, format: :short, locale: :en)
    {:ok, "in 2 Wed."}

    iex> Cldr.DateTime.Relative.to_string(1, MyApp.Cldr, unit: :wed, format: :short)
    {:ok, "next Wed."}

    iex> Cldr.DateTime.Relative.to_string(-1, MyApp.Cldr, unit: :wed, format: :short)
    {:ok, "last Wed."}

    iex> Cldr.DateTime.Relative.to_string(-1, MyApp.Cldr, unit: :wed)
    {:ok, "last Wednesday"}

    iex> Cldr.DateTime.Relative.to_string(-1, MyApp.Cldr, unit: :quarter)
    {:ok, "last quarter"}

    iex> Cldr.DateTime.Relative.to_string(-1, MyApp.Cldr, unit: :mon, locale: :fr)
    {:ok, "lundi dernier"}

    iex> Cldr.DateTime.Relative.to_string(~D[2017-04-29], MyApp.Cldr, unit: :ziggeraut)
    {:error, {Cldr.DateTime.UnknownTimeUnit,
     "Unknown time unit :ziggeraut.  Valid time units are [:day, :fri, :hour, :minute, :mon, :month, :quarter, :sat, :second, :sun, :thu, :tue, :wed, :week, :year]"}}

# `to_string!`

```elixir
@spec to_string!(
  number() | Date.t() | DateTime.t(),
  Cldr.backend() | Keyword.t(),
  Keyword.t()
) ::
  String.t() | no_return()
```

Returns a string representing a relative time (ago, in) for a given
number, date, time or datetime or raises an exception.

### Arguments

* `relative` is an integer or `t:Calendar.datetime/0`, `t:Calendar.date/0`, or
  `t:Calendar.time/0` representing the time distance from `now` or from
  `options[:relative_to]`.

* `backend` is any module that includes `use Cldr` and therefore
  is a `Cldr` backend module. The default is `Cldr.default_backend/0`.

* `options` is a `t:Keyword.t/0` list of options.

### Options

* `:locale` is any valid locale name returned by `Cldr.known_locale_names/0`
  or a `t:Cldr.LanguageTag.t/0` struct.  The default is `Cldr.get_locale/0`.

* `:format` is the type of the formatted string.  Allowable values are `:standard`,
  `:narrow` or `:short`. The default is `:standard`.

* `:style` determines whether to return a standard relative string ("tomorrow") or
  an "at" string ("tomorrow at 3:00 PM"). The supported values are `:standard` (the default)
  or `:at`.  Note that `style: :at` is only applied when:

  * `:unit` is not a time unit (ie not `:hour`, `:minute` or :second`)
  * *and* when `:relative` is a `t:Calendar.datetime/0` or
  * *or* the `:at` option is set to a `t:Calendar.time/0`

* `:unit` is the time unit for the formatting.  The allowable units are `:second`, `:minute`,
  `:hour`, `:day`, `:week`, `:month`, `:year`, `:mon`, `:tue`, `:wed`, `:thu`, `:fri`, `:sat`,
  `:sun`, `:quarter`. If no `:unit` is specified, one will be derived using the
  `:derive_unit_from` option.

* `:relative_to` is the baseline `date` or `datetime` from which the difference
  from `relative` is calculated when `relative` is a `t:Calendar.date/0` or a
  `t:Calendar.datetime/0`. The default for a `t:Calendar.date/0` is `Date.utc_today/0`;
  for a `t:Calendar.datetime/0` it is `DateTime.utc_now/0` and for a t:Calendar.time/0` it
  is `Time.utc_now/0`.

* `:time` is any `t:Calendar.time/0` that is used when `style: :at` is being applied. The
  default is to use the time component of `relative`.

* `:time_format` is the format option to be passed to `Cldr.Time.to_string/3` if the `:style`
  option is `:at` and `relative` is a `t:Calendar.datetime/0` or the `:time` option is set.
  The default is `:short`.

* `:at_format` is one of `:short`, `:medium`, `:long` or `:full`. It is used to determine the
  format joining together the `relative` string and the `:time` string when `:style` is `:at.
  The default is `:short` if `:format` is either `:short` or `:narrow`. Otherwise the
  default is `:medium`.

* `:derive_unit_from` is used to derive the most appropriate time unit if none is provided.
  There are two ways to specify `:derive_unit_from`.

  * The first option is a map. The map is required to have the keys `:second`, `:minute`, `:hour`,
    `:day`, `:week`, `:month`, and `:year` with the values being the number of seconds below
    which the key defines the time unit difference. This is the default and its value is:

    %{second: 1, month: 2629743.83, day: 86400, year: 31556926, minute: 60, hour: 3600, week: 604800}

  * The second option is to specify a function reference. The function must take four
    arguments as described below.

#### The :derive_unit_from` *map*

* Any `:derive_unit_from` map is first merged into the default map. This means that developers
  can use the default values and override only specific entries by providing a sparse map.

* Any entry in the `:derive_unit_from` map that has a value of `nil` is ignored. This has the
  result that any key set to `nil` will never be represented in the output.

* Any entry in the `:derive_unit_from` map that has the value `:infinity` will always be the
  largest time unit used to represent the relative time.

#### The :derive_unit_from *function*

* The function must take four arguments:
  * `relative`, being the first argument to `to_string/3`.
  * `relative_to` being the value of option `:relative_to` or its default value.
  * `time_difference` being the difference in seconds between `relative`
    and `relative_to`.
  * `unit` being the requested time unit which may be `nil`. If `nil` then
    the time unit must be derived and the `time_difference` scaled to that
    time unit. If specified then the `time_difference` must be scaled to
    the specified time unit.

* The function must return a tuple of the form `{relative, unit}` where
  `relative` is an integer value and `unit` is the appropriate time unit atom.

* See the `Cldr.DateTime.Relative.derive_unit_from/4` function for an example.

### Returns

* `{:ok, formatted_string}` or

* `{:error, {exception, reason}}`

### Examples

* See `Cldr.DateTime.Relative.to_string/3` for example usage.

# `unit_from_relative_time`

Returns an estimate of the appropriate time unit for an integer of a given
magnitude of seconds.

## Examples

    iex> Cldr.DateTime.Relative.unit_from_relative_time(1234)
    :minute

    iex> Cldr.DateTime.Relative.unit_from_relative_time(12345)
    :hour

    iex> Cldr.DateTime.Relative.unit_from_relative_time(123456)
    :day

    iex> Cldr.DateTime.Relative.unit_from_relative_time(1234567)
    :week

    iex> Cldr.DateTime.Relative.unit_from_relative_time(12345678)
    :month

    iex> Cldr.DateTime.Relative.unit_from_relative_time(123456789)
    :year

---

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