Packages
timex
2.1.3
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/time/formatters/humanized.ex
defmodule Timex.Format.Time.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.Time.Formatter
alias Timex.Translator
@minute 60
@hour @minute * 60
@day @hour * 24
@week @day * 7
@month @day * 30
@year @day * 365
@doc """
Return a human readable string representing the time interval.
## Examples
iex> {1435, 180354, 590264} |> #{__MODULE__}.format
"45 years, 6 months, 5 days, 21 hours, 12 minutes, 34 seconds, 590.264 milliseconds"
iex> {0, 65, 0} |> #{__MODULE__}.format
"1 minute, 5 seconds"
"""
@spec format(Types.timestamp) :: String.t | {:error, term}
def format({_,_,_} = timestamp), do: lformat(timestamp, Translator.default_locale)
def format(_), do: {:error, :invalid_timestamp}
@doc """
Return a human readable string representing the time interval, translated to the given locale
## Examples
iex> {1435, 180354, 590264} |> #{__MODULE__}.lformat("ru")
"45 года 6 месяца 5 днем 21 час 12 минуты 34 секунды 590.264 миллисекунды"
iex> {0, 65, 0} |> #{__MODULE__}.lformat("ru")
"1 минута 5 секунды"
"""
@spec lformat(Types.timestamp, String.t) :: String.t | {:error, term}
def lformat({_,_,_} = timestamp, locale) do
timestamp
|> deconstruct
|> do_format(locale)
end
def lformat(_, _locale), do: {:error, :invalid_timestamp}
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({_, _, micro} = ts), do: deconstruct({ts |> Time.to_seconds |> trunc, micro}, [])
defp deconstruct({0, 0}, components), do: components |> Enum.reverse
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({seconds, micro}, components) when seconds < 0, do: deconstruct({seconds * -1, micro}, components)
defp deconstruct({0, micro}, components) do
msecs = {0, 0, micro} |> Time.abs |> Time.to_milliseconds
cond do
msecs >= 1.0 -> deconstruct({0, 0}, [{:millisecond, msecs} | components])
true -> deconstruct({0, 0}, [{:microsecond, micro} | components])
end
end
end