Formats relative times such as "3 days ago", "tomorrow" or "in 1.5 hours".
A relative time is a number of units, or the difference between a Date.t/0, Time.t/0, NaiveDateTime.t/0 or DateTime.t/0 and a baseline. The number is formatted with the locale's digits and grouping, and the plural category of the number as displayed selects the unit's pattern. to_string/2 returns the string and to_parts/2 the same result as typed parts.
A difference is counted with the arithmetic of the value's own calendar, in the calendar periods between the two: the years, quarters, months, weeks and days between their dates on the value's wall clock, and the hours, minutes and seconds between them on the value's clock at its UTC offset, so an hour that a change of offset skips or repeats is counted as the time that passes. It is never a number of seconds divided by a mean length, so a month is a month of the value's calendar whatever its length, and a Hebrew leap year has thirteen of them.
Summary
Functions
Returns the list of known time units.
Formats a relative time into typed parts, mirroring ECMA-402's formatToParts for Intl.RelativeTimeFormat.
Same as to_parts/2 but raises on error.
Returns a string representing a relative time for a given number, date, time, or datetime.
Same as to_string/2 but raises on error.
Functions
@spec known_units() :: [atom(), ...]
Returns the list of known time units.
Returns
- The unit atoms the
:unitoption accepts.
Examples
iex> Localize.DateTime.Relative.known_units()
[:day, :fri, :hour, :minute, :mon, :month, :quarter, :sat, :second, :sun, :thu, :tue, :wed, :week, :year]
@spec to_parts( number() | Date.t() | Time.t() | NaiveDateTime.t() | DateTime.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. A named form ("yesterday") is a single :literal part. A pattern form places the number's parts from Localize.Number.to_parts/2 (:integer, :group, :decimal, :fraction), each carrying a :unit key, between :literal parts, as ECMA-402 does: "in 1,000 days" is :literal "in ", :integer "1", :group ",", :integer "000" and :literal " days".
Arguments
relativeis a number, or aDate.t/0,Time.t/0,NaiveDateTime.t/0orDateTime.t/0.optionsis a keyword list of options.
Options
See to_string/2 for the supported options.
Returns
{:ok, parts}wherepartsis a list of%{type: atom(), value: String.t()}maps; the number's parts also carry a:unitkey.{:error, exception}ifrelativeor 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(1000, unit: :day, locale: :en)
{:ok,
[
%{type: :literal, value: "in "},
%{type: :integer, value: "1", unit: :day},
%{type: :group, value: ",", unit: :day},
%{type: :integer, value: "000", unit: :day},
%{type: :literal, value: " days"}
]}
@spec to_parts!( number() | Date.t() | Time.t() | NaiveDateTime.t() | DateTime.t(), Keyword.t() ) :: [ %{type: atom(), value: String.t()} ]
Same as to_parts/2 but raises on error.
Arguments
relativeis a number, or aDate.t/0,Time.t/0,NaiveDateTime.t/0orDateTime.t/0. Seeto_string/2.optionsis a keyword list of options. Seeto_parts/2.
Returns
- A list of
%{type: atom(), value: String.t()}maps.
Raises
- Raises an exception if
relativeor the options are invalid.
Examples
iex> Localize.DateTime.Relative.to_parts!(-1, unit: :day, locale: :en)
[%{type: :literal, value: "yesterday"}]
@spec to_string( number() | Date.t() | Time.t() | NaiveDateTime.t() | DateTime.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
relativeis a number of:units, which may be fractional, or a number of seconds when there is no:unit. It may instead be aDate.t/0,Time.t/0,NaiveDateTime.t/0orDateTime.t/0, whose difference from:relative_tois formatted.optionsis a keyword list of options.
Options
:localeis a locale identifier. The number is formatted with the locale's digits and grouping, in the number system a-u-nu-extension names if it has one. The default isLocalize.get_locale/0.:formatis:standard,:narrow, or:short. The default is:standard.:unitis the time unit for formatting. One of:second,:minute,:hour,:day,:week,:month,:quarter,:year,:mon,:tue,:wed,:thu,:fri,:sator:sun. A difference is the number of the unit's calendar periods from the baseline to the value: 1 February is "next month" from 31 January, and 00:01 is "in 1 hour" from 23:59 the day before. A week and a weekday unit count calendar weeks, each starting on the locale's first day of the week, so "next Monday" is the Monday of the week after the baseline's. Two times have no date, so no days or longer periods lie between them. If omitted, the unit is the largest of which a whole one lies between the two, from a year down to a day for dates and to a second for times. A whole day, week, month or year is reckoned as ECMA-262 Temporal reckons it: across a change of UTC offset, a day is whole once the wall clock is at or past its time on the next day and that time has passed, a skipped time being taken at the offset before the gap, and in a lunisolar calendar a year is whole on the month of the same name, a leap month's year on the ordinary month it doubles. A number with no unit is a number of seconds, which has no calendar: it is counted, to the nearest, in the largest of weeks, days, hours, minutes and seconds it reaches, and never in months, quarters or years.:numericis:autoor:always, mirroring ECMA-402'snumericoption. With:auto(the default), a whole offset of -2 to 2 takes the unit's named form, such as "yesterday" or "tomorrow", where the locale has one; an offset that is no whole number, such as 1.5, is always the number. With:always, output is always numeric: "1 day ago" instead of "yesterday".:relative_tois the baseline from which the difference is calculated. ADate.t/0orTime.t/0is measured against a value of its own type, aNaiveDateTime.t/0or aDateTime.t/0, aNaiveDateTime.t/0against aNaiveDateTime.t/0or aDateTime.t/0, and aDateTime.t/0against aDateTime.t/0. The baseline is converted into the value's calendar, and aDateTime.t/0baseline of aDateTime.t/0is moved into the value's time zone, so the two are compared on the value's wall clock. Any other pairing, or a baseline that cannot be converted, returns an error. The default isDateTime.utc_now/0.
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(-3, unit: :day, locale: :en)
{:ok, "3 days ago"}
iex> Localize.DateTime.Relative.to_string(1.5, unit: :hour, locale: :en)
{:ok, "in 1.5 hours"}
iex> Localize.DateTime.Relative.to_string(-1000, unit: :day, locale: :de)
{:ok, "vor 1.000 Tagen"}
iex> Localize.DateTime.Relative.to_string(-1, unit: :day, locale: :en, numeric: :always)
{:ok, "1 day ago"}
iex> Localize.DateTime.Relative.to_string(~D[2024-02-01], relative_to: ~D[2024-01-31], unit: :month, locale: :en)
{:ok, "next month"}
@spec to_string!( number() | Date.t() | Time.t() | NaiveDateTime.t() | DateTime.t(), Keyword.t() ) :: String.t()
Same as to_string/2 but raises on error.
Arguments
relativeis a number, or aDate.t/0,Time.t/0,NaiveDateTime.t/0orDateTime.t/0. Seeto_string/2.optionsis a keyword list of options.
Options
- See
to_string/2for the supported options.
Returns
- The localized relative time as a string.
Raises
- Raises an exception if the relative time cannot be formatted.
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"