Packages
timex
3.7.3
3.7.13
3.7.12
3.7.11
3.7.9
3.7.8
3.7.7
3.7.6
3.7.5
3.7.3
3.7.2
3.7.1
3.7.0
3.6.4
3.6.3
3.6.2
retired
3.6.1
3.6.0
3.5.0
3.4.2
3.4.1
3.3.0
3.2.2
3.2.1
3.2.0
3.1.25
retired
3.1.24
3.1.23
3.1.22
3.1.21
3.1.20
3.1.19
3.1.18
3.1.17
3.1.16
3.1.15
3.1.13
3.1.12
3.1.11
3.1.10
3.1.9
3.1.8
3.1.7
3.1.6
3.1.5
3.1.4
3.1.3
3.1.2
3.1.1
3.1.0
3.0.8
3.0.7
3.0.6
3.0.5
3.0.4
3.0.3
3.0.2
3.0.1
3.0.0
2.2.1
2.1.6
2.1.5
2.1.4
2.1.3
2.1.2
2.1.1
2.1.0
2.0.0
1.0.2
1.0.1
1.0.0
1.0.0-rc4
1.0.0-rc3
1.0.0-rc2
1.0.0-rc1
1.0.0-pre
0.19.5
0.19.4
0.19.3
0.19.2
0.19.1
0.19.0
0.18.2
0.18.1
0.18.0
0.17.0
0.16.2
0.16.1
0.16.0
0.15.0
0.14.3
0.14.2
0.14.1
0.14.0
0.13.5
0.13.4
0.13.3
0.13.2
0.13.1
0.13.0
0.12.9
0.12.8
0.12.7
0.12.6
0.12.5
0.12.4
0.12.3
0.12.2
0.12.1
0.12.0
0.11.0
0.10.2
0.10.1
0.10.0
0.9.0
0.8.0
0.7.1
0.6.0
0.5.0
0.4.8
0.4.7
0.4.6
Timex is a rich, comprehensive Date/Time library for Elixir projects, with full timezone support via the :tzdata package. If you need to manipulate dates, times, datetimes, timestamps, etc., then Timex is for you!
Current section
Files
Jump to
Current section
Files
lib/datetime/helpers.ex
defmodule Timex.DateTime.Helpers do
@moduledoc false
alias Timex.{Types, Timezone, TimezoneInfo, AmbiguousDateTime, AmbiguousTimezoneInfo}
@type precision :: -1 | 0..6
@doc """
Constructs an empty NaiveDateTime, for internal use only
"""
def empty(), do: Timex.NaiveDateTime.new!(0, 1, 1, 0, 0, 0)
@doc """
Constructs a DateTime from an Erlang date or datetime tuple and a timezone.
Intended for internal use only.
"""
@spec construct(Types.date(), Types.valid_timezone()) ::
DateTime.t() | AmbiguousDateTime.t() | {:error, term}
@spec construct(Types.datetime(), Types.valid_timezone()) ::
DateTime.t() | AmbiguousDateTime.t() | {:error, term}
@spec construct(Types.microsecond_datetime(), Types.valid_timezone()) ::
DateTime.t() | AmbiguousDateTime.t() | {:error, term}
@spec construct(Types.microsecond_datetime(), precision, Types.valid_timezone()) ::
DateTime.t() | AmbiguousDateTime.t() | {:error, term}
def construct({_, _, _} = date, timezone) do
construct({date, {0, 0, 0, 0}}, 0, timezone)
end
def construct({{_, _, _} = date, {h, mm, s}}, timezone) do
construct({date, {h, mm, s, 0}}, 0, timezone)
end
def construct({{_, _, _} = date, {_, _, _, _} = time}, timezone) do
construct({date, time}, -1, timezone)
end
def construct({{_, _, _} = date, {_, _, _, _} = time}, precision, timezone) do
construct({date, time}, precision, timezone, :wall)
end
def construct({{y, m, d} = date, {h, mm, s, us}}, precision, timezone, utc_or_wall) do
seconds_from_zeroyear = :calendar.datetime_to_gregorian_seconds({date, {h, mm, s}})
case Timezone.name_of(timezone) do
{:error, _} = err ->
err
tzname ->
case Timezone.resolve(tzname, seconds_from_zeroyear, utc_or_wall) do
{:error, _} = err ->
err
%TimezoneInfo{} = tz ->
%DateTime{
:year => y,
:month => m,
:day => d,
:hour => h,
:minute => mm,
:second => s,
:microsecond => construct_microseconds(us, precision),
:time_zone => tz.full_name,
:zone_abbr => tz.abbreviation,
:utc_offset => tz.offset_utc,
:std_offset => tz.offset_std
}
%AmbiguousTimezoneInfo{before: b, after: a} ->
bd = %DateTime{
:year => y,
:month => m,
:day => d,
:hour => h,
:minute => mm,
:second => s,
:microsecond => construct_microseconds(us, precision),
:time_zone => b.full_name,
:zone_abbr => b.abbreviation,
:utc_offset => b.offset_utc,
:std_offset => b.offset_std
}
ad = %DateTime{
:year => y,
:month => m,
:day => d,
:hour => h,
:minute => mm,
:second => s,
:microsecond => construct_microseconds(us, precision),
:time_zone => a.full_name,
:zone_abbr => a.abbreviation,
:utc_offset => a.offset_utc,
:std_offset => a.offset_std
}
%AmbiguousDateTime{before: bd, after: ad}
end
end
end
def construct_microseconds({us, p}) when is_integer(us) and is_integer(p) do
construct_microseconds(us, p)
end
def construct_microseconds(us) when is_integer(us) do
construct_microseconds(us, -1)
end
# Input precision of -1 means it should be recalculated based on the value
def construct_microseconds(0, -1), do: {0, 0}
def construct_microseconds(0, p), do: {0, p}
def construct_microseconds(n, -1), do: {n, precision(n)}
def construct_microseconds(n, p), do: {to_precision(n, p), p}
def to_precision(0, _p), do: 0
def to_precision(_, 0), do: 0
def to_precision(us, p) do
case precision(us) do
detected_p when detected_p > p ->
# Convert to lower precision
pow = trunc(:math.pow(10, detected_p - p))
Integer.floor_div(us, pow) * pow
_detected_p ->
# Already correct precision or less precise
us
end
end
def precision(0), do: 0
def precision(n) when is_integer(n) do
ns = Integer.to_string(n)
n_width = byte_size(ns)
trimmed = byte_size(String.trim_trailing(ns, "0"))
new_p = 6 - (n_width - trimmed)
if new_p >= 6 do
6
else
new_p
end
end
end