Packages
timex
3.1.1
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/comparable/diff.ex
defmodule Timex.Comparable.Diff do
@moduledoc false
alias Timex.Types
alias Timex.Duration
alias Timex.Comparable
@units [:years, :months, :weeks, :calendar_weeks, :days,
:hours, :minutes, :seconds, :milliseconds, :microseconds,
:duration]
@spec diff(Types.microseconds, Types.microseconds, Comparable.granularity) :: integer
def diff(a, a, granularity) when is_integer(a), do: zero(granularity)
def diff(a, b, granularity) when is_integer(a) and is_integer(b) and is_atom(granularity) do
do_diff(a, b, granularity)
end
defp do_diff(a, a, type), do: zero(type)
defp do_diff(a, b, :duration), do: Duration.from_seconds(do_diff(a,b,:seconds))
defp do_diff(a, b, :microseconds), do: a - b
defp do_diff(a, b, :milliseconds), do: div(a - b, 1_000)
defp do_diff(a, b, :seconds), do: div(a - b, 1_000*1_000)
defp do_diff(a, b, :minutes), do: div(a - b, 1_000*1_000*60)
defp do_diff(a, b, :hours), do: div(a - b, 1_000*1_000*60*60)
defp do_diff(a, b, :days), do: div(a - b, 1_000*1_000*60*60*24)
defp do_diff(a, b, :weeks), do: div(a - b, 1_000*1_000*60*60*24*7)
defp do_diff(a, b, :calendar_weeks) do
adate = :calendar.gregorian_seconds_to_datetime(div(a, 1_000*1_000))
bdate = :calendar.gregorian_seconds_to_datetime(div(b, 1_000*1_000))
days = cond do
a > b ->
ending = Timex.end_of_week(adate)
start = Timex.beginning_of_week(bdate)
endu = Timex.to_gregorian_microseconds(ending)
startu = Timex.to_gregorian_microseconds(start)
do_diff(endu, startu, :days)
:else ->
ending = Timex.end_of_week(bdate)
start = Timex.beginning_of_week(adate)
endu = Timex.to_gregorian_microseconds(ending)
startu = Timex.to_gregorian_microseconds(start)
do_diff(startu, endu, :days)
end
cond do
days >= 0 && rem(days, 7) != 0 -> div(days, 7) + 1
days <= 0 && rem(days, 7) != 0 -> div(days, 7) - 1
:else -> div(days, 7)
end
end
defp do_diff(a, b, :months) do
{ly,lm,ld,ey,em,ed,sign} = cond do
a > b ->
{{ly,lm,ld},_} = :calendar.gregorian_seconds_to_datetime(div(a, 1_000*1_000))
{{ey,em,ed},_} = :calendar.gregorian_seconds_to_datetime(div(b, 1_000*1_000))
{ly,lm,ld,ey,em,ed,1}
:else ->
{{ey,em,ed},_} = :calendar.gregorian_seconds_to_datetime(div(a, 1_000*1_000))
{{ly,lm,ld},_} = :calendar.gregorian_seconds_to_datetime(div(b, 1_000*1_000))
{ly,lm,ld,ey,em,ed,-1}
end
x = cond do
ld >= ed -> 0
:else -> -1
end
y = ly - ey
z = lm - em
(x+y*12+z)*sign
end
defp do_diff(a, b, :years) do
div(do_diff(a, b, :months), 12)
end
defp do_diff(_, _, granularity) when not granularity in @units,
do: {:error, {:invalid_granularity, granularity}}
defp zero(:duration), do: Duration.zero
defp zero(_type), do: 0
end