Cldr.DateTime.Relative (Cldr Dates & Times v2.24.0)
View SourceFunctions to support the string formatting of relative time/datetime numbers.
This module provides formatting of numbers (as integers, floats, Dates or DateTimes) as "ago" or "in" with an appropriate time unit. For example, "2 days ago" or "in 10 seconds"
Summary
Functions
An example implementation of a function to derive an appropriate time unit for a relative time.
Returns a list of the valid unit keys for to_string/2
Calculates the time span in the given unit from the time given in seconds.
Returns a {:ok, string} representing a relative time (ago, in) for a given
number, Date or Datetime.  Returns {:error, reason} when errors are detected.
Returns a string representing a relative time (ago, in) for a given number, Date or Datetime or raises an exception on error.
Returns an estimate of the appropriate time unit for an integer of a given magnitude of seconds.
Functions
An example implementation of a function to derive an appropriate time unit for a relative time.
Arguments
relative, the first argument provided toto_string/3.relative_tothe value of option:relative_toprovided toto_string/3or its default value.time_differenceis the difference in seconds betweenrelativeandrelative_to.unitbeing the requested time unit which may benil. Ifnilthen the time unit must be derived and thetime_differencescaled to that time unit. If specified then thetime_differencemust be scaled to that time unit.
Returns
{relative, unit}whererelativeis the integer value of the derived and scaled time unit.unitis the derived or given time unit.
Notes
- In this implementation
the time difference is used to derive seconds, minutes, hours, days and weeks.
The 
:monthand:yearfields of the therelativestruct are used to derive months and years. 
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]
  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
  @spec to_string( integer() | float() | Date.t() | DateTime.t(), Cldr.backend(), Keyword.t() ) :: {:ok, String.t()} | {:error, {module(), String.t()}}
Returns a {:ok, string} representing a relative time (ago, in) for a given
number, Date or Datetime.  Returns {:error, reason} when errors are detected.
relativeis an integer orDateTime.t/0,Date.t/0orTime.t/0representing the time distance fromnowor fromoptions[:relative_to].backendis any module that includesuse Cldrand therefore is aCldrbackend module. The default isCldr.default_backend/0.optionsis aKeyword.t/0list of options.
Options
:localeis the locale in which the binary is formatted. The default isCldr.get_locale/0:formatis the format of the binary. Format may be:default,:narrowor:short.:unitis 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:unitis specified, one will be derived using the:derive_unit_fromoption.:relative_tois the baselinet:Date/0ort:Datetime.t/0from which the difference fromrelativeis calculated whenrelativeis a Date or a DateTime. The default for aDate.t/0isDate.utc_today/0, for aDateTime.t/0it isDateTime.utc_now/0.:derive_unit_fromis 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:yearwith 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_frommap 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_frommap that has a value ofnilis ignored. This has the result that any key set tonilwill never be represented in the output.Any entry in the
:derive_unit_frommap that has the value:infinitywill 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 toto_string/3.relative_tobeing the value of option:relative_toor its default value.time_differencebeing the difference in seconds betweenrelativeandrelative_to.unitbeing the requested time unit which may benil. Ifnilthen the time unit must be derived and thetime_differencescaled to that time unit. If specified then thetime_differencemust be scaled to that time unit.
The function must return a tuple of the form
{relative, unit}whererelativeis an integer value andunitis the appropriate time unit atom.See the
Cldr.DateTime.Relative.derive_unit_from/4function for an example.
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(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]"}}
  @spec to_string!( integer() | float() | Date.t() | DateTime.t(), Cldr.backend(), Keyword.t() ) :: String.t()
Returns a string representing a relative time (ago, in) for a given number, Date or Datetime or raises an exception on error.
Arguments
relativeis an integer orDateTime.t/0,Date.t/0orTime.t/0representing the time distance fromnowor fromoptions[:relative_to].backendis any module that includesuse Cldrand therefore is aCldrbackend module. The default isCldr.default_backend/0.optionsis aKeyword.t/0list of options.
Options
:localeis the locale in which the binary is formatted. The default isCldr.get_locale/0.:formatis the format of the binary. Format may be:default,:narrowor:short. The default is:default.:unitis 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:unitis specified, one will be derived using the:derive_unit_fromoption.:relative_tois the baselinet:Date/0ort:Datetime.t/0from which the difference fromrelativeis calculated whenrelativeis a Date or a DateTime. The default for aDate.t/0isDate.utc_today/0, for aDateTime.t/0it isDateTime.utc_now/0.:derive_unit_fromis 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:yearwith 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_frommap 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_frommap that has a value ofnilis ignored. This has the result that any key set tonilwill never be represented in the output.Any entry in the
:derive_unit_frommap that has the value:infinitywill 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 toto_string/3.relative_tobeing the value of option:relative_toor its default value.time_differencebeing the difference in seconds betweenrelativeandrelative_to.unitbeing the requested time unit which may benil. Ifnilthen the time unit must be derived and thetime_differencescaled to that time unit. If specified then thetime_differencemust be scaled to that time unit.
The function must return a tuple of the form
{relative, unit}whererelativeis an integer value andunitis the appropriate time unit atom.See the
Cldr.DateTime.Relative.derive_unit_from/4function for an example.
See to_string/3 for example usage.
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