1defprotocol Timex.Comparable do 2 @moduledoc """ 3 This protocol is used for comparing and diffing different date/time representations 4 """ 5 alias Timex.Types 6 7 @type granularity :: :years | :months | :weeks | :calendar_weeks | :days | 8 :hours | :minutes | :seconds | :milliseconds | :microseconds | 9 :duration 10 @type constants :: :epoch | :zero | :distant_past | :distant_future 11 @type comparable :: Date.t | DateTime.t | NaiveDateTime.t | Types.date | Types.datetime 12 @type compare_result :: -1 | 0 | 1 | {:error, term} 13 @type diff_result :: Timex.Duration.t | integer | {:error, term} 14 15 @doc """ 16 Compare two date or datetime types. 17 18 You can optionally specify a comparison granularity, any of the following: 19 20 - :years 21 - :months 22 - :weeks 23 - :calendar_weeks (weeks of the calendar as opposed to actual weeks in terms of days) 24 - :days 25 - :hours 26 - :minutes 27 - :seconds 28 - :milliseconds 29 - :microseconds (default) 30 - :duration 31 32 and the dates will be compared with the cooresponding accuracy. 33 The default granularity is :microseconds. 34 35 - 0: when equal 36 - -1: when the first date/time comes before the second 37 - 1: when the first date/time comes after the second 38 - {:error, reason}: when there was a problem comparing, 39 perhaps due to a value being passed which is not a valid date/datetime 40 41 ## Examples 42 43 iex> use Timex 44 iex> date1 = ~D[2014-03-04] 45 iex> date2 = ~D[2015-03-04] 46 iex> Timex.compare(date1, date2, :years) 47 -1 48 iex> Timex.compare(date2, date1, :years) 49 1 50 iex> Timex.compare(date1, date1) 51 0 52 """ 53 @spec compare(comparable, comparable, granularity) :: compare_result 54 def compare(a, b, granularity \\ :microseconds) 55 56 @doc """ 57 Get the difference between two date or datetime types. 58 59 You can optionally specify a diff granularity, any of the following: 60 61 - :years 62 - :months 63 - :calendar_weeks (weeks of the calendar as opposed to actual weeks in terms of days) 64 - :weeks 65 - :days 66 - :hours 67 - :minutes 68 - :seconds 69 - :milliseconds 70 - :microseconds (default) 71 - :duration 72 73 and the result will be an integer value of those units or a Duration struct. 74 The diff value will be negative if `a` comes before `b`, and positive if `a` comes 75 after `b`. This behaviour mirrors `compare/3`. 76 77 When using granularity of :months, the number of days in the month varies. This 78 behavior mirrors `Timex.shift/2`. 79 80 ## Examples 81 82 iex> use Timex 83 iex> date1 = ~D[2015-01-28] 84 iex> date2 = ~D[2015-02-28] 85 iex> Timex.diff(date1, date2, :months) 86 -1 87 iex> Timex.diff(date2, date1, :months) 88 1 89 90 iex> use Timex 91 iex> date1 = ~D[2015-01-31] 92 iex> date2 = ~D[2015-02-28] 93 iex> Timex.diff(date1, date2, :months) 94 -1 95 iex> Timex.diff(date2, date1, :months) 96 0 97 """ 98 @spec diff(comparable, comparable, granularity) :: diff_result 99 def diff(a, b, granularity \\ :microseconds) 100end 101