Packages

fnord

0.9.36

AI code archaeology

Current section

Files

Jump to
fnord lib util duration.ex
Raw

lib/util/duration.ex

defmodule Util.Duration do
@moduledoc """
Human-friendly duration formatting utilities.
Modes:
- :natural (default): "H hours, M minutes, S seconds" with proper pluralization.
- :compact : "H:MM:SS" / "M:SS" / "Ss" (reserved for future use).
"""
@type mode :: :natural | :compact
@spec format(non_neg_integer(), mode()) :: String.t()
def format(seconds, mode \\ :natural) when is_integer(seconds) and seconds >= 0 do
case mode do
:natural -> format_natural(seconds)
:compact -> format_compact(seconds)
end
end
@spec format_natural(non_neg_integer()) :: String.t()
defp format_natural(seconds) do
h = div(seconds, 3600)
m = div(rem(seconds, 3600), 60)
s = rem(seconds, 60)
parts =
[{h, "hour"}, {m, "minute"}, {s, "second"}]
|> Enum.filter(fn {count, _unit} -> count > 0 end)
|> Enum.map(fn {count, unit} -> pluralize(count, unit) end)
if parts == [] do
pluralize(0, "second")
else
Enum.join(parts, ", ")
end
end
@spec format_compact(non_neg_integer()) :: String.t()
defp format_compact(seconds) do
h = div(seconds, 3600)
m = div(rem(seconds, 3600), 60)
s = rem(seconds, 60)
cond do
h > 0 -> "#{h}:#{pad2(m)}:#{pad2(s)}"
m > 0 -> "#{m}:#{pad2(s)}"
true -> "#{s}s"
end
end
defp pluralize(0, unit), do: "0 #{unit}s"
defp pluralize(1, unit), do: "1 #{unit}"
defp pluralize(n, unit), do: "#{n} #{unit}s"
defp pad2(n) when is_integer(n), do: String.pad_leading(Integer.to_string(n), 2, "0")
end