towerops/lib/towerops_web/helpers/time_helpers.ex
Graham McIntire ae16acf016
Add build timestamp to footer with shared time formatting helpers
- Add compile-time @build_timestamp to Application module
- Create ToweropsWeb.TimeHelpers module for shared time formatting
- Update footer to display 'Last deployed Xm ago · YYYY-MM-DD HH:MM:SS UTC'
- Refactor AgentLive.Helpers to delegate to shared TimeHelpers
- Consolidate duplicate time formatting logic into single module
- Timestamp updates automatically on each build/deploy
2026-01-17 11:10:50 -06:00

106 lines
2.5 KiB
Elixir

defmodule ToweropsWeb.TimeHelpers do
@moduledoc """
Helper functions for formatting time and date values.
"""
@doc """
Formats a DateTime into a human-readable "time ago" string.
Supports short time periods (seconds, minutes, hours, days) and
long time periods (months, years) for things like build timestamps.
## Examples
iex> datetime = DateTime.add(DateTime.utc_now(), -65, :second)
iex> ToweropsWeb.TimeHelpers.format_time_ago(datetime)
"1m ago"
iex> datetime = DateTime.add(DateTime.utc_now(), -7200, :second)
iex> ToweropsWeb.TimeHelpers.format_time_ago(datetime)
"2h ago"
"""
@spec format_time_ago(DateTime.t() | nil) :: String.t()
def format_time_ago(nil), do: "Never"
def format_time_ago(datetime) do
now = DateTime.utc_now()
diff = DateTime.diff(now, datetime, :second)
cond do
diff < 60 ->
"#{diff}s ago"
diff < 3600 ->
minutes = div(diff, 60)
"#{minutes}m ago"
diff < 86_400 ->
hours = div(diff, 3600)
"#{hours}h ago"
diff < 2_592_000 ->
days = div(diff, 86_400)
"#{days}d ago"
diff < 31_536_000 ->
months = div(diff, 2_592_000)
"#{months}mo ago"
true ->
years = div(diff, 31_536_000)
"#{years}y ago"
end
end
@doc """
Formats a DateTime into a full date and time string.
## Examples
iex> datetime = ~U[2026-01-15 14:34:00Z]
iex> ToweropsWeb.TimeHelpers.format_datetime(datetime)
"Jan 15, 2026 at 02:34 PM UTC"
"""
@spec format_datetime(DateTime.t() | nil) :: String.t()
def format_datetime(nil), do: "Never"
def format_datetime(datetime) do
Calendar.strftime(datetime, "%b %d, %Y at %I:%M %p %Z")
end
@doc """
Formats a DateTime into a short date string.
## Examples
iex> datetime = ~U[2026-01-15 14:34:00Z]
iex> ToweropsWeb.TimeHelpers.format_date(datetime)
"Jan 15, 2026"
"""
@spec format_date(DateTime.t() | nil) :: String.t()
def format_date(nil), do: "Never"
def format_date(datetime) do
Calendar.strftime(datetime, "%b %d, %Y")
end
@doc """
Formats a DateTime into ISO 8601 format with UTC timezone.
## Examples
iex> datetime = ~U[2026-01-15 14:34:00Z]
iex> ToweropsWeb.TimeHelpers.format_iso8601(datetime)
"2026-01-15 14:34:00 UTC"
"""
@spec format_iso8601(DateTime.t() | nil) :: String.t()
def format_iso8601(nil), do: "Never"
def format_iso8601(datetime) do
Calendar.strftime(datetime, "%Y-%m-%d %H:%M:%S UTC")
end
end