Current section

Files

Jump to
timex lib datetime naivedatetime.ex
Raw

lib/datetime/naivedatetime.ex

defimpl Timex.Protocol, for: NaiveDateTime do
@moduledoc """
This module implements Timex functionality for NaiveDateTime
"""
alias Timex.AmbiguousDateTime
import Timex.Macros
@epoch_seconds :calendar.datetime_to_gregorian_seconds({{1970, 1, 1}, {0, 0, 0}})
def now(), do: NaiveDateTime.utc_now()
def to_julian(%NaiveDateTime{year: y, month: m, day: d}) do
Timex.Calendar.Julian.julian_date(y, m, d)
end
def to_gregorian_seconds(date) do
with {s, _} <- Timex.NaiveDateTime.to_gregorian_seconds(date), do: s
end
def to_gregorian_microseconds(%NaiveDateTime{} = date) do
with {s, us} <- Timex.NaiveDateTime.to_gregorian_seconds(date) do
s * (1_000 * 1_000) + us
end
end
def to_unix(date) do
with {s, _} <- Timex.NaiveDateTime.to_gregorian_seconds(date) do
s - @epoch_seconds
end
end
def to_date(date), do: NaiveDateTime.to_date(date)
def to_datetime(%NaiveDateTime{} = naive, timezone) do
with %DateTime{} = datetime <- Timex.Timezone.convert(naive, timezone) do
datetime
else
%AmbiguousDateTime{} = datetime ->
datetime
{:error, _} = err ->
err
end
end
def to_naive_datetime(%NaiveDateTime{} = date), do: date
def to_erl(%NaiveDateTime{} = d), do: NaiveDateTime.to_erl(d)
def century(%NaiveDateTime{:year => year}), do: Timex.century(year)
def is_leap?(%NaiveDateTime{year: year}), do: :calendar.is_leap_year(year)
def beginning_of_day(%NaiveDateTime{:microsecond => {_, precision}} = datetime) do
%{datetime | :hour => 0, :minute => 0, :second => 0, :microsecond => {0, precision}}
end
def end_of_day(%NaiveDateTime{microsecond: {_, precision}} = datetime) do
us = Timex.DateTime.Helpers.construct_microseconds(999_999, precision)
%{datetime | :hour => 23, :minute => 59, :second => 59, :microsecond => us}
end
def beginning_of_week(%NaiveDateTime{microsecond: {_, precision}} = date, weekstart) do
with ws when is_atom(ws) <- Timex.standardize_week_start(weekstart) do
date = Timex.Date.beginning_of_week(date, ws)
Timex.NaiveDateTime.new!(date.year, date.month, date.day, 0, 0, 0, {0, precision})
end
end
def end_of_week(%NaiveDateTime{microsecond: {_, precision}} = date, weekstart) do
with ws when is_atom(ws) <- Timex.standardize_week_start(weekstart) do
date = Timex.Date.end_of_week(date, ws)
us = Timex.DateTime.Helpers.construct_microseconds(999_999, precision)
Timex.NaiveDateTime.new!(date.year, date.month, date.day, 23, 59, 59, us)
end
end
def beginning_of_year(%NaiveDateTime{year: year, microsecond: {_, precision}}) do
Timex.NaiveDateTime.new!(year, 1, 1, 0, 0, 0, {0, precision})
end
def end_of_year(%NaiveDateTime{year: year, microsecond: {_, precision}}) do
us = Timex.DateTime.Helpers.construct_microseconds(999_999, precision)
Timex.NaiveDateTime.new!(year, 12, 31, 23, 59, 59, us)
end
def beginning_of_quarter(%NaiveDateTime{month: month} = date) do
month = 1 + 3 * (Timex.quarter(month) - 1)
beginning_of_month(%{date | :month => month, :day => 1})
end
def end_of_quarter(%NaiveDateTime{month: month} = date) do
month = 3 * Timex.quarter(month)
end_of_month(%{date | :month => month, :day => 1})
end
def beginning_of_month(%NaiveDateTime{year: year, month: month, microsecond: {_, precision}}),
do: Timex.NaiveDateTime.new!(year, month, 1, 0, 0, 0, {0, precision})
def end_of_month(%NaiveDateTime{year: year, month: month, microsecond: {_, precision}} = date) do
day = days_in_month(date)
us = Timex.DateTime.Helpers.construct_microseconds(999_999, precision)
Timex.NaiveDateTime.new!(year, month, day, 23, 59, 59, us)
end
def quarter(%NaiveDateTime{year: y, month: m, day: d}),
do: Calendar.ISO.quarter_of_year(y, m, d)
def days_in_month(%NaiveDateTime{year: y, month: m}), do: Timex.days_in_month(y, m)
def week_of_month(%NaiveDateTime{year: y, month: m, day: d}),
do: Timex.week_of_month(y, m, d)
def weekday(%NaiveDateTime{year: y, month: m, day: d}),
do: :calendar.day_of_the_week({y, m, d})
def weekday(%NaiveDateTime{} = date, weekstart),
do: Timex.Date.day_of_week(date, weekstart)
def day(%NaiveDateTime{} = date), do: Date.day_of_year(date)
def is_valid?(%NaiveDateTime{
:year => y,
:month => m,
:day => d,
:hour => h,
:minute => min,
:second => sec
}) do
:calendar.valid_date({y, m, d}) and Timex.is_valid_time?({h, min, sec})
end
def iso_week(%NaiveDateTime{:year => y, :month => m, :day => d}),
do: Timex.iso_week(y, m, d)
def from_iso_day(%NaiveDateTime{year: year} = date, day) when is_day_of_year(day) do
{year, month, day_of_month} = Timex.Helpers.iso_day_to_date_tuple(year, day)
%{date | :year => year, :month => month, :day => day_of_month}
end
def set(%NaiveDateTime{} = date, options) do
validate? = Keyword.get(options, :validate, true)
Enum.reduce(options, date, fn
_option, {:error, _} = err ->
err
option, result ->
case option do
{:validate, _} ->
result
{:datetime, {{y, m, d}, {h, min, sec}}} ->
if validate? do
%{
result
| :year => Timex.normalize(:year, y),
:month => Timex.normalize(:month, m),
:day => Timex.normalize(:day, {y, m, d}),
:hour => Timex.normalize(:hour, h),
:minute => Timex.normalize(:minute, min),
:second => Timex.normalize(:second, sec)
}
else
%{
result
| :year => y,
:month => m,
:day => d,
:hour => h,
:minute => min,
:second => sec
}
end
{:date, {y, m, d}} ->
if validate? do
{yn, mn, dn} = Timex.normalize(:date, {y, m, d})
%{result | :year => yn, :month => mn, :day => dn}
else
%{result | :year => y, :month => m, :day => d}
end
{:date, %Date{} = d} ->
Timex.set(result, date: {d.year, d.month, d.day})
{:time, {h, m, s}} ->
if validate? do
%{
result
| :hour => Timex.normalize(:hour, h),
:minute => Timex.normalize(:minute, m),
:second => Timex.normalize(:second, s)
}
else
%{result | :hour => h, :minute => m, :second => s}
end
{:time, {h, m, s, ms}} ->
if validate? do
%{
result
| :hour => Timex.normalize(:hour, h),
:minute => Timex.normalize(:minute, m),
:second => Timex.normalize(:second, s),
:microsecond => Timex.normalize(:microsecond, ms)
}
else
%{result | :hour => h, :minute => m, :second => s, :microsecond => ms}
end
{:time, %Time{} = t} ->
Timex.set(result, time: {t.hour, t.minute, t.second, t.microsecond})
{:day, d} ->
if validate? do
%{result | :day => Timex.normalize(:day, {result.year, result.month, d})}
else
%{result | :day => d}
end
{name, val} when name in [:year, :month, :hour, :minute, :second, :microsecond] ->
if validate? do
Map.put(result, name, Timex.normalize(name, val))
else
Map.put(result, name, val)
end
{name, _} when name in [:timezone] ->
result
{option_name, _} ->
{:error, {:bad_option, option_name}}
end
end)
end
def shift(%NaiveDateTime{} = datetime, shifts) when is_list(shifts) do
with {:ok, dt} <- DateTime.from_naive(datetime, "Etc/UTC", Timex.tzdb()) do
case Timex.shift(dt, shifts) do
{:error, _} = err ->
err
%AmbiguousDateTime{after: datetime} ->
DateTime.to_naive(datetime)
%DateTime{} = datetime ->
DateTime.to_naive(datetime)
end
end
end
end