Files
bDS2/lib/bds/persistence.ex

86 lines
1.9 KiB
Elixir

defmodule BDS.Persistence do
@moduledoc false
def now_ms, do: System.system_time(:millisecond)
def normalize_unix_timestamp(nil), do: nil
def normalize_unix_timestamp(value) when is_integer(value) do
if abs(value) < 100_000_000_000 do
value * 1000
else
value
end
end
def normalize_unix_timestamp(value) when is_binary(value) do
value
|> String.trim()
|> case do
"" -> nil
trimmed ->
case Integer.parse(trimmed) do
{integer, ""} -> normalize_unix_timestamp(integer)
_ -> nil
end
end
end
def normalize_unix_timestamp(_value), do: nil
def from_unix_ms!(value) when is_integer(value) do
value
|> normalize_unix_timestamp()
|> DateTime.from_unix!(:millisecond)
end
def timestamp_to_iso8601(nil), do: nil
def timestamp_to_iso8601(value) when is_integer(value) do
value
|> from_unix_ms!()
|> DateTime.to_iso8601()
end
def parse_timestamp(nil), do: nil
def parse_timestamp(value) when is_integer(value), do: normalize_unix_timestamp(value)
def parse_timestamp(value) when is_binary(value) do
trimmed = String.trim(value)
cond do
trimmed == "" ->
nil
Regex.match?(~r/^-?\d+$/, trimmed) ->
normalize_unix_timestamp(trimmed)
true ->
case DateTime.from_iso8601(trimmed) do
{:ok, datetime, _offset} -> DateTime.to_unix(datetime, :millisecond)
_ -> nil
end
end
end
def parse_timestamp(_value), do: nil
def atomic_write(path, contents) when is_binary(path) and is_binary(contents) do
:ok = File.mkdir_p(Path.dirname(path))
temp_path = path <> ".tmp"
with :ok <- File.write(temp_path, contents),
:ok <- File.rename(temp_path, path) do
:ok
else
{:error, _reason} = error ->
_ = File.rm(temp_path)
error
error ->
_ = File.rm(temp_path)
error
end
end
end