Packages

ex_cldr

0.3.0
2.47.5 2.47.4 2.47.3 2.47.2 2.47.1 2.47.0 2.46.0 2.45.2 2.45.1 2.45.0 2.44.1 2.44.0 2.43.2 2.43.1 2.43.0 2.42.0 2.41.1 2.41.0 2.40.4 2.40.3 2.40.2 2.40.1 2.40.0 2.39.2 2.39.1 2.39.0 2.38.1 2.38.0 2.37.5 2.37.4 2.37.3 retired 2.37.2 2.37.1 2.37.0 2.36.0 2.35.1 2.35.0 retired 2.34.2 2.34.1 2.34.0 2.33.2 2.33.1 2.33.1-rc.0 2.33.0 2.32.1 2.32.0 2.31.0 2.30.0 2.29.0 2.28.0 2.27.1 2.27.0 retired 2.26.3 2.26.2 2.26.1 2.26.0 2.25.0 2.24.2 2.24.1 2.24.0 2.24.0-rc.6 2.24.0-rc.5 2.24.0-rc.4 2.24.0-rc.3 2.24.0-rc.2 2.24.0-rc.1 2.24.0-rc.0 2.23.2 2.23.1 2.23.0 2.22.1 2.22.0 2.21.0 2.20.0 2.20.0-rc.3 2.20.0-rc.2 2.20.0-rc.1 2.20.0-rc.0 2.19.1 2.19.0 2.18.2 2.18.1 2.18.0 2.18.0-rc.0 2.17.2 2.17.1 2.17.0 2.16.2 2.16.1 2.16.1-rc.0 2.16.0 2.15.0 2.14.1 2.14.0 2.14.0-rc.0 2.13.0 2.12.1 2.12.0 2.11.1 2.11.0 2.10.2 2.10.1 2.10.0 retired 2.9.0 2.8.1 2.8.0 2.7.2 2.7.1 2.7.0 2.6.2 2.6.1 2.6.0 2.5.0 2.4.3 2.4.2 2.4.1 2.4.0 2.3.2 2.3.1 2.3.0 2.2.7 2.2.6 2.2.5 2.2.4 2.2.3 2.2.2 2.2.1 2.2.0 2.1.0 2.0.4 2.0.3 2.0.2 2.0.1 2.0.0 2.0.0-rc.3 retired 2.0.0-rc.2 retired 2.0.0-rc.1 retired 2.0.0-rc.0 retired 1.8.2 1.8.1 1.8.0 1.7.1 1.7.0 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.2 1.5.1 1.5.0 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 retired 1.4.0-rc.3 retired 1.4.0-rc.2 retired 1.4.0-rc.1 retired 1.4.0-rc.0 retired 1.3.2 1.3.1 1.3.0 1.2.0 1.1.0 1.0.0 1.0.0-rc.3 retired 1.0.0-rc.2 retired 1.0.0-rc.1 retired 1.0.0-rc.0 retired 0.13.1 0.13.0 0.12.2 retired 0.12.1 retired 0.12.0 retired 0.11.0 retired 0.10.0 retired 0.9.0 retired 0.8.3 retired 0.8.2 retired 0.8.1 retired 0.8.0 retired 0.7.0 retired 0.6.2 retired 0.6.1 retired 0.6.0 retired 0.5.2 retired 0.5.1 retired 0.5.0 retired 0.4.2 retired 0.4.1 retired 0.4.0 retired 0.3.0 retired 0.2.1 retired 0.2.0 retired 0.1.3 retired 0.1.2 retired 0.1.1 retired 0.1.0 retired 0.0.20 retired 0.0.19 retired 0.0.18 retired 0.0.17 retired 0.0.16 retired 0.0.15 retired 0.0.14 retired 0.0.13 retired 0.0.12 retired 0.0.11 retired 0.0.10 retired 0.0.8 retired 0.0.7 retired 0.0.6 retired 0.0.5 retired 0.0.4 retired 0.0.3 retired

Common Locale Data Repository (CLDR) functions for Elixir to localize and format numbers, dates, lists, messages, languages, territories and units with support for over 700 locales for internationalized (i18n) and localized (L10N) applications.

Retired package: Deprecated

Current section

Files

Jump to
ex_cldr lib cldr datetime datetime_relative.ex
Raw

lib/cldr/datetime/datetime_relative.ex

defmodule Cldr.DateTime.Relative do
@moduledoc """
Functions to support the string formatting of relative time/datetime numbers.
This allows for the 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"
"""
@default_options [locale: Cldr.get_locale(), format: :default]
@second 1
@minute 60
@hour 3600
@day 86400
@week 604800
@month 2629743.83
@year 31556926
@unit %{
second: @second,
minute: @minute,
hour: @hour,
day: @day,
week: @week,
month: @month,
year: @year
}
@other_units [:mon, :tue, :wed, :thu, :fri, :sat, :sun, :quarter]
@unit_keys Map.keys(@unit) ++ @other_units
@doc """
Returns a string representing a relative time (ago, in) for a given
number, Date or Datetime.
* `relative` is a number or Date/Datetime representing the time distance from `now` or from
options[:relative_to]
* `options` is a `Keyword` list of options which are:
* `:locale` is the locale in which the binary is formatted. The default is `Cldr.get_locale/0`
* `:format` is the format of the binary. Format may be `:default`, `:narrow` or `:short`
* `: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`
* `:relative_to` is the baseline Date or Datetime from which the difference from `relative` is
calculated when `relative` is a Date or a DateTime. The default for a Date is `Date.utc_today`,
for a DateTime it is `DateTime.utc_now`
## Examples
iex> Cldr.DateTime.Relative.to_string(-1)
"1 second ago"
iex> Cldr.DateTime.Relative.to_string(1)
"in 1 second"
iex> Cldr.DateTime.Relative.to_string(1, unit: :day)
"tomorrow"
iex> Cldr.DateTime.Relative.to_string(1, unit: :day, locale: "fr")
"demain"
iex> Cldr.DateTime.Relative.to_string(1, unit: :day, format: :narrow)
"tomorrow"
iex> Cldr.DateTime.Relative.to_string(1234, unit: :year)
"in 1,234 years"
iex> Cldr.DateTime.Relative.to_string(1234, unit: :year, locale: "fr")
"dans 1 234 ans"
iex> Cldr.DateTime.Relative.to_string(31)
"in 31 seconds"
iex> Cldr.DateTime.Relative.to_string(~D[2017-04-29], relative_to: ~D[2017-04-26])
"in 3 days"
iex> Cldr.DateTime.Relative.to_string(310, format: :short, locale: "fr")
"dans 5 min"
iex> Cldr.DateTime.Relative.to_string(310, format: :narrow, locale: "fr")
"+5 min"
iex> Cldr.DateTime.Relative.to_string 2, unit: :wed, format: :short
"in 2 Wed."
iex> Cldr.DateTime.Relative.to_string 1, unit: :wed, format: :short
"next Wed."
iex> Cldr.DateTime.Relative.to_string -1, unit: :wed, format: :short
"last Wed."
iex> Cldr.DateTime.Relative.to_string -1, unit: :wed
"last Wednesday"
iex> Cldr.DateTime.Relative.to_string -1, unit: :quarter
"last quarter"
iex> Cldr.DateTime.Relative.to_string -1, unit: :mon, locale: "fr"
"lundi dernier"
iex> Cldr.DateTime.Relative.to_string(~D[2017-04-29], unit: :ziggeraut)
{:error,
"Unknown time unit :ziggeraut. Valid time units are [:day, :hour, :minute, :month, :second, :week, :year, :mon, :tue, :wed, :thu, :fri, :sat, :sun, :quarter]"}
## Notes
When `options[:unit]` is not specified, `Cldr.DateTime.Relative.to_string/2` attempts to identify
the appropriate unit based upon the magnitude of `relative`. For example, given a parameter
of less than `60`, then `to_string/2` will assume `:seconds` as the unit.
"""
@spec to_string(integer | float | Date.t | DateTime.t, []) :: binary
def to_string(relative, options \\ []) do
options = Keyword.merge(@default_options, options)
unit = Keyword.get(options, :unit)
options = Keyword.delete(options, :unit)
to_string(relative, unit, options)
end
defp to_string(relative, nil, options)
when is_integer(relative) and relative in [-1, 0, +1] do
unit = unit_from_seconds(relative)
binary = to_string(relative, unit, options)
if is_nil(binary) do
to_string(relative * 1.0, unit, options)
else
binary
end
end
defp to_string(relative, unit, options)
when is_integer(relative) and relative in [-1, 0, +1] do
options[:locale]
|> Cldr.Locale.get_locale
|> get_in([:date_fields, unit, options[:format], :relative_ordinal])
|> Enum.at(relative + 1)
end
defp to_string(relative, unit, options)
when is_number(relative) and unit in @unit_keys do
direction = if relative > 0, do: :relative_future, else: :relative_past
rules = options[:locale]
|> Cldr.Locale.get_locale
|> get_in([:date_fields, unit, options[:format], direction])
rule = Cldr.Number.Cardinal.pluralize(trunc(relative), options[:locale], rules)
relative
|> abs
|> Cldr.Number.to_string(locale: options[:locale])
|> Cldr.Substitution.substitute(rule)
|> Enum.join
end
defp to_string(%DateTime{} = relative, unit, options) do
now = (options[:relative_to] || DateTime.utc_now) |> DateTime.to_unix
then = DateTime.to_unix(relative)
seconds = then - now
do_to_string(seconds, unit, options)
end
defp to_string(%Date{} = relative, unit, options) do
today = (options[:relative_to] || Date.utc_today)
|> Date.to_erl
|> :calendar.date_to_gregorian_days
|> Kernel.*(@day)
then = relative
|> Date.to_erl
|> :calendar.date_to_gregorian_days
|> Kernel.*(@day)
seconds = then - today
do_to_string(seconds, unit, options)
end
defp to_string(span, unit, options) do
do_to_string(span, unit, options)
end
defp do_to_string(seconds, nil, options) do
do_to_string(seconds, unit_from_seconds(seconds), options)
end
defp do_to_string(seconds, unit, options) when unit in @unit_keys do
seconds
|> calculate_unit(unit)
|> to_string(unit, options)
end
defp do_to_string(_, unit, _) do
{:error, "Unknown time unit #{inspect unit}. Valid time units are #{inspect @unit_keys}"}
end
@doc """
Returns an estimate of the appropriate time unit for an integer of a given
magnitude of seconds.
## Examples
iex> Cldr.DateTime.Relative.unit_from_seconds(1234)
:minute
iex> Cldr.DateTime.Relative.unit_from_seconds(12345)
:hour
iex> Cldr.DateTime.Relative.unit_from_seconds(123456)
:day
iex> Cldr.DateTime.Relative.unit_from_seconds(1234567)
:week
iex> Cldr.DateTime.Relative.unit_from_seconds(12345678)
:month
iex> Cldr.DateTime.Relative.unit_from_seconds(123456789)
:year
"""
def unit_from_seconds(seconds) do
case abs(seconds) do
i when i < @minute -> :second
i when i < @hour -> :minute
i when i < @day -> :hour
i when i < @week -> :day
i when i < @month -> :week
i when i < @year -> :month
_ -> :year
end
end
@doc """
Calculates the time span in the given `unit` from the time given in seconds.
## Examples
iex> Cldr.DateTime.Relative.calculate_unit(1234, :second)
1234
iex> Cldr.DateTime.Relative.calculate_unit(1234, :minute)
21
iex> Cldr.DateTime.Relative.calculate_unit(1234, :hour )
0
"""
def calculate_unit(seconds, unit) do
(seconds / @unit[unit])
|> Float.round
|> trunc
end
@doc """
Returns a list of the valid unit keys for `to_string/2`
## Example
iex> Cldr.DateTime.Relative.known_units
[:day, :hour, :minute, :month, :second, :week, :year, :mon, :tue, :wed, :thu,
:fri, :sat, :sun, :quarter]
"""
def known_units do
@unit_keys
end
end