Current section

Files

Jump to
exosql lib datetime.ex
Raw

lib/datetime.ex

require Logger
defmodule ExoSQL.DateTime do
@moduledoc """
Helpers for datetime
"""
def strftime(dt, format) do
dt = to_datetime(dt)
# Simplifications, %i from sqlite is supported
format = format
|> String.replace("%i", "%FT%T%z")
Timex.format!(dt, format, :strftime)
|> String.replace("+0000", "Z")
end
def to_datetime(n) when is_number(n) do
{:ok, dt} = DateTime.from_unix(n)
dt
end
def to_datetime(n) when is_binary(n) do
if String.contains?(n, "-") do
case String.length(n) do
10 ->
n = "#{n} 00:00:00Z"
{:ok, td, 0} = DateTime.from_iso8601(n)
td
16 ->
n = "#{n}:00Z"
{:ok, td, 0} = DateTime.from_iso8601(n)
td
19 ->
{:ok, td, 0} = DateTime.from_iso8601(n <> "Z")
td
20 ->
{:ok, td, 0} = DateTime.from_iso8601(n)
td
24 ->
{:ok, td, _} = DateTime.from_iso8601(n)
td
end
else
{:ok, unixtime} = ExoSQL.Utils.to_number(n)
# Logger.debug("To datetime #{inspect unixtime}")
to_datetime(unixtime)
end
end
def to_datetime(%DateTime{} = d), do: d
def to_datetime(other) do
raise ArgumentError, message: "cant convert #{inspect other} to date"
end
def to_datetime(dt, "-" <> mod) do
dt = to_datetime(dt)
mod = if String.starts_with?(mod, "P") do
mod
else
"P" <> mod
end
duration = Timex.Duration.parse!(mod)
Timex.subtract(dt, duration)
end
def to_datetime(dt, "+" <> mod) do
dt = to_datetime(dt)
mod = if String.starts_with?(mod, "P") do
mod
else
"P" <> mod
end
duration = Timex.Duration.parse!(mod)
Timex.add(dt, duration)
end
def to_datetime(dt, tz) do
dt = to_datetime(dt)
Timex.to_datetime(dt, tz)
end
@units %{
"minutes" => 60,
"hours" => 60 * 60,
"days" => 24 * 60 * 60,
"weeks" => 7 * 24 * 60 * 60,
}
def datediff({:range, start, end_}), do: datediff(start, end_, "days")
def datediff({:range, start, end_}, units), do: datediff(start, end_, units)
def datediff(start, end_), do: datediff(start, end_, "days")
def datediff(%DateTime{} = start, %DateTime{} = end_, "years") do
if start > end_ do
-datediff(end_, start, :years)
else
years = end_.year - start.year
if end_.month < start.month do
years - 1
else
years
end
end
end
def datediff(%DateTime{} = start, %DateTime{} = end_, "months") do
if start > end_ do
-datediff(end_, start, :months)
else
years = datediff(start, end_, "years")
months = if start.month < end_.month do
end_.month - start.month
else
end_.month + 12 - start.month
end
years * 12 + months
end
end
def datediff(%DateTime{} = start, %DateTime{} = end_, "seconds") do
DateTime.diff(end_, start, :second)
end
def datediff(%DateTime{} = start, %DateTime{} = end_, unit) do
div( DateTime.diff(end_, start, :second), Map.get(@units, unit))
end
def datediff(start, end_, unit) do
start = to_datetime(start)
end_ = to_datetime(end_)
datediff(start, end_, unit)
end
end