Cldr.DateTime.Relative (Cldr Dates & Times v2.25.1)

View Source

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"

Summary

Functions

Returns the default map of unit steps.

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

known_styles() deprecated

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

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

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

Functions

default_unit_steps()

(since 2.25.0)

Returns the default map of unit steps.

derive_unit_from(relative, relative_to, time_difference, atom)

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 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(time_difference, unit, derive_unit_from \\ %{day: 86400, hour: 3600, minute: 60, month: 2_629_743.83, second: 1, week: 604_800, year: 31_556_926})

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(relative, backend \\ Cldr.Date.default_backend(), options \\ [])

@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

Options

  • :locale is any valid locale name returned by Cldr.known_locale_names/0 or a 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:relativeis at:Calendar.datetime/0or * *or* the:atoption is set to at:Calendar.time/0*: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 baselinedateordatetimefrom which the difference fromrelativeis calculated whenrelativeis at:Calendar.date/0or at:Calendar.datetime/0. The default for at:Calendar.date/0isDate.utc_today/0; for at:Calendar.datetime/0it isDateTime.utc_now/0and for a t:Calendar.time/0 it is Time.utc_now/0.
  • :time is any 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 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:shortif:formatis either:shortor:narrow. Otherwise the default is:medium. *: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_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!(relative, backend \\ Cldr.Date.default_backend(), options \\ [])

@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

Options

  • :locale is any valid locale name returned by Cldr.known_locale_names/0 or a 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:relativeis at:Calendar.datetime/0or * *or* the:atoption is set to at:Calendar.time/0*: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 baselinedateordatetimefrom which the difference fromrelativeis calculated whenrelativeis at:Calendar.date/0or at:Calendar.datetime/0. The default for at:Calendar.date/0isDate.utc_today/0; for at:Calendar.datetime/0it isDateTime.utc_now/0and for a t:Calendar.time/0 it is Time.utc_now/0.
  • :time is any 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 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:shortif:formatis either:shortor:narrow. Otherwise the default is:medium. *: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_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

unit_from_relative_time(time_difference, unit \\ nil, derive_unit_from \\ %{day: 86400, hour: 3600, minute: 60, month: 2_629_743.83, second: 1, week: 604_800, year: 31_556_926})

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