Packages
timex
3.7.1
3.7.13
3.7.12
3.7.11
3.7.9
3.7.8
3.7.7
3.7.6
3.7.5
3.7.3
3.7.2
3.7.1
3.7.0
3.6.4
3.6.3
3.6.2
retired
3.6.1
3.6.0
3.5.0
3.4.2
3.4.1
3.3.0
3.2.2
3.2.1
3.2.0
3.1.25
retired
3.1.24
3.1.23
3.1.22
3.1.21
3.1.20
3.1.19
3.1.18
3.1.17
3.1.16
3.1.15
3.1.13
3.1.12
3.1.11
3.1.10
3.1.9
3.1.8
3.1.7
3.1.6
3.1.5
3.1.4
3.1.3
3.1.2
3.1.1
3.1.0
3.0.8
3.0.7
3.0.6
3.0.5
3.0.4
3.0.3
3.0.2
3.0.1
3.0.0
2.2.1
2.1.6
2.1.5
2.1.4
2.1.3
2.1.2
2.1.1
2.1.0
2.0.0
1.0.2
1.0.1
1.0.0
1.0.0-rc4
1.0.0-rc3
1.0.0-rc2
1.0.0-rc1
1.0.0-pre
0.19.5
0.19.4
0.19.3
0.19.2
0.19.1
0.19.0
0.18.2
0.18.1
0.18.0
0.17.0
0.16.2
0.16.1
0.16.0
0.15.0
0.14.3
0.14.2
0.14.1
0.14.0
0.13.5
0.13.4
0.13.3
0.13.2
0.13.1
0.13.0
0.12.9
0.12.8
0.12.7
0.12.6
0.12.5
0.12.4
0.12.3
0.12.2
0.12.1
0.12.0
0.11.0
0.10.2
0.10.1
0.10.0
0.9.0
0.8.0
0.7.1
0.6.0
0.5.0
0.4.8
0.4.7
0.4.6
Timex is a rich, comprehensive Date/Time library for Elixir projects, with full timezone support via the :tzdata package. If you need to manipulate dates, times, datetimes, timestamps, etc., then Timex is for you!
Current section
Files
Jump to
Current section
Files
lib/format/duration/formatters/humanized.ex
defmodule Timex.Format.Duration.Formatters.Humanized do
@moduledoc """
Handles formatting timestamp values as human readable strings.
For formatting timestamps as points in time rather than intervals,
use `Timex.format`
"""
use Timex.Format.Duration.Formatter
alias Timex.Translator
@minute 60
@hour @minute * 60
@day @hour * 24
@week @day * 7
@month @day * 30
@year @day * 365
@microsecond 1_000_000
@doc """
Return a human readable string representing the absolute value of duration (i.e. would
return the same output for both negative and positive representations of a given duration)
## Examples
iex> use Timex
...> Duration.from_erl({0, 1, 1_000_000}) |> #{__MODULE__}.format
"2 seconds"
iex> use Timex
...> Duration.from_erl({0, 1, 1_000_100}) |> #{__MODULE__}.format
"2 seconds, 100 microseconds"
iex> use Timex
...> Duration.from_erl({0, 65, 0}) |> #{__MODULE__}.format
"1 minute, 5 seconds"
iex> use Timex
...> Duration.from_erl({0, -65, 0}) |> #{__MODULE__}.format
"1 minute, 5 seconds"
iex> use Timex
...> Duration.from_erl({1435, 180354, 590264}) |> #{__MODULE__}.format
"45 years, 6 months, 5 days, 21 hours, 12 minutes, 34 seconds, 590.264 milliseconds"
"""
@spec format(Duration.t()) :: String.t() | {:error, term}
def format(%Duration{} = duration), do: lformat(duration, Translator.default_locale())
def format(_), do: {:error, :invalid_duration}
@doc """
Return a human readable string representing the time interval, translated to the given locale
## Examples
iex> use Timex
...> Duration.from_erl({0, 65, 0}) |> #{__MODULE__}.lformat("ru")
"1 минута, 5 секунд"
iex> use Timex
...> Duration.from_erl({1435, 180354, 590264}) |> #{__MODULE__}.lformat("ru")
"45 лет, 6 месяцев, 5 дней, 21 час, 12 минут, 34 секунды, 590.264 миллисекунд"
"""
@spec lformat(Duration.t(), String.t()) :: String.t() | {:error, term}
def lformat(%Duration{} = duration, locale) do
duration
|> deconstruct
|> do_format(locale)
end
def lformat(_, _locale), do: {:error, :invalid_duration}
defp do_format(components, locale),
do: do_format(components, <<>>, locale)
defp do_format([], str, _locale),
do: str
defp do_format([{unit, value} | rest], str, locale) do
unit = Atom.to_string(unit)
unit_with_value =
Translator.translate_plural(locale, "units", "%{count} #{unit}", "%{count} #{unit}s", value)
separator = Translator.translate(locale, "symbols", ",")
case str do
<<>> -> do_format(rest, "#{unit_with_value}", locale)
_ -> do_format(rest, str <> "#{separator} #{unit_with_value}", locale)
end
end
defp deconstruct(duration) do
micros = Duration.to_microseconds(duration) |> abs
deconstruct({div(micros, @microsecond), rem(micros, @microsecond)}, [])
end
defp deconstruct({0, 0}, []),
do: deconstruct({0, 0}, microsecond: 0)
defp deconstruct({0, 0}, components),
do: Enum.reverse(components)
defp deconstruct({seconds, us}, components) when seconds > 0 do
cond do
seconds >= @year ->
deconstruct({rem(seconds, @year), us}, [{:year, div(seconds, @year)} | components])
seconds >= @month ->
deconstruct({rem(seconds, @month), us}, [{:month, div(seconds, @month)} | components])
seconds >= @week ->
deconstruct({rem(seconds, @week), us}, [{:week, div(seconds, @week)} | components])
seconds >= @day ->
deconstruct({rem(seconds, @day), us}, [{:day, div(seconds, @day)} | components])
seconds >= @hour ->
deconstruct({rem(seconds, @hour), us}, [{:hour, div(seconds, @hour)} | components])
seconds >= @minute ->
deconstruct({rem(seconds, @minute), us}, [{:minute, div(seconds, @minute)} | components])
true ->
deconstruct({0, us}, [{:second, seconds} | components])
end
end
defp deconstruct({0, micro}, components) do
millis =
micro
|> Duration.from_microseconds()
|> Duration.to_milliseconds()
cond do
millis >= 1 -> deconstruct({0, 0}, [{:millisecond, millis} | components])
true -> deconstruct({0, 0}, [{:microsecond, micro} | components])
end
end
end