View Source Tempus.Slot (Tempus v0.15.0)

Declares a timeslot and exports functions to check whether the given date and/or datetime is covered by this slot or not.

This module probably should not be called directly.

Summary

Types

The origin used in comparisons and calculations

t()

A timeslot to be used in Tempus

Functions

Compares two slot structs.

Checks whether to Slot covers the data/datetime passed as a second argument.

Returns true if two slots are disjoined, false otherwise.

Calculates the duration of a slot in units given as a second parameter (default: :second.)

Identity element, void slot ~I[nil → nil]

Intersects slots to the minimal covered timeslice.

Joins slots to the maximal covered timeslice.

Joins two slots to the maximal covered timeslice.

Returns true if two slots are neighbours, false otherwise.

Creates new slot using arg[:from] as a starting origin and arg[:to] and an ending origin.

Creates new slot using from as a starting origin and to and an ending origin. See new/1 for more readable implementation.

Creates new slot using from as a starting origin and to and an ending origin. Unlike new/1, this function raises on malformed input.

Compares two slot structs. The same as compare/2, but returns :joint if the slots are overlapped.

Checks whether the Slot is valid (to > from) or not.

Helper macro to pattern-match void slots.

Wraps the argument into a slot. For DateTime it’d be a single microsecond. For a Date, it would be the whole day, starting at 00:00:00.000000 and

Splits the slot given asa first argument to two on borders given as a second slot.

Types

@type origin() :: t() | Date.t() | DateTime.t() | nil

The origin used in comparisons and calculations

@type t() :: %Tempus.Slot{from: nil | DateTime.t(), to: nil | DateTime.t()}

A timeslot to be used in Tempus

Functions

Link to this function

compare(s1, s2, strict \\ false)

View Source
@spec compare(s1 :: origin(), s2 :: origin(), strict :: boolean()) ::
  :lt | :gt | :eq | :joint

Compares two slot structs.

Returns :gt if first slot is strictly later than the second and :lt for vice versa. NB :eq is returned not only if slots are equal, but also when they are overlapped.

Might be used in Enum.sort/2.

Examples

iex> slot = %Tempus.Slot{from: ~U[2020-09-30 00:00:00.000000Z], to: ~U[2020-10-02 23:59:59.999999Z]}
iex> slot1 = %Tempus.Slot{from: nil, to: ~U[2020-09-30 00:00:00.000000Z]}
iex> slot2 = %Tempus.Slot{from: nil, to: DateTime.utc_now()}
iex> slot3 = %Tempus.Slot{from: ~U[2020-09-30 00:00:00.000000Z], to: nil}
iex> slot4 = %Tempus.Slot{from: DateTime.utc_now(), to: nil}
iex> Tempus.Slot.compare(Tempus.Slot.id(), Tempus.Slot.id(), true)
:eq
iex> Tempus.Slot.compare(slot1, slot2, false)
:eq
iex> Tempus.Slot.compare(slot1, slot2, true)
:joint
iex> Tempus.Slot.compare(slot3, slot4, false)
:eq
iex> Tempus.Slot.compare(slot3, slot4, true)
:joint
iex> Tempus.Slot.compare(slot, slot, true)
:eq
iex> Tempus.Slot.compare(slot, DateTime.utc_now(), true)
:lt
iex> Tempus.Slot.compare(slot, ~D|2000-01-01|, true)
:gt
iex> Tempus.Slot.compare(slot, slot.from, true)
:joint
Link to this function

cover?(slot, dt, strict? \\ false)

View Source
@spec cover?(slot :: t(), dt :: origin(), strict? :: boolean()) :: boolean()

Checks whether to Slot covers the data/datetime passed as a second argument.

Examples

iex> dt_between = ~U|2015-09-30 01:00:00Z|
...> dt_from = ~U|2015-09-30 00:00:00Z|
...> dt_to = ~U|2015-10-01 01:00:00Z|
...> d_from = Date.from_iso8601!("2015-09-30")
...> d_to = Date.from_iso8601!("2015-10-01")
iex> slot = %Tempus.Slot{from: dt_from, to: dt_to}
iex> Tempus.Slot.cover?(slot, dt_between)
true
iex> Tempus.Slot.cover?(slot, dt_to)
true
iex> Tempus.Slot.cover?(slot, dt_to, true)
false
iex> Tempus.Slot.cover?(slot, d_from)
true
iex> Tempus.Slot.cover?(slot, d_from, true)
false
iex> Tempus.Slot.cover?(slot, ~U|2000-01-01 00:00:00Z|)
false
iex> Tempus.Slot.cover?(slot, d_to)
false
@spec disjoint?(s1 :: origin(), s2 :: origin()) :: boolean()

Returns true if two slots are disjoined, false otherwise.

Examples

iex> slot = %Tempus.Slot{from: ~U|2015-09-01 00:00:00Z|, to: ~U|2015-10-01 00:00:00Z|}
iex> inner = %Tempus.Slot{from: ~U|2015-09-01 00:00:00Z|, to: ~U|2015-09-01 01:00:00Z|}
iex> Tempus.Slot.disjoint?(slot, inner)
false
iex> inner = %Tempus.Slot{from: ~U|2015-09-01 00:00:00Z|, to: ~U|2015-10-01 01:00:00Z|}
iex> Tempus.Slot.disjoint?(slot, inner)
false
iex> outer = %Tempus.Slot{from: ~U|2015-10-01 00:00:01Z|, to: ~U|2015-10-01 01:00:00Z|}
iex> Tempus.Slot.disjoint?(slot, outer)
true
iex> Tempus.Slot.disjoint?(~D|2000-01-01|, ~U|2015-10-01 00:00:01Z|)
true
Link to this function

duration(slot, unit \\ :second)

View Source
@spec duration(slot :: origin(), unit :: System.time_unit()) ::
  non_neg_integer() | :infinity

Calculates the duration of a slot in units given as a second parameter (default: :second.)

Example

iex> Tempus.Slot.duration(~D|2020-09-03|)
86400
iex> Tempus.Slot.duration(Tempus.Slot.id())
0
iex> Tempus.Slot.duration(%Tempus.Slot{from: nil, to: DateTime.utc_now()})
:infinity
iex> Tempus.Slot.duration(%Tempus.Slot{from: DateTime.utc_now(), to: nil})
:infinity
@spec id() :: t()

Identity element, void slot ~I[nil → nil]

@spec intersect(slots :: Enum.t()) :: t() | nil

Intersects slots to the minimal covered timeslice.

Example

iex> Tempus.Slot.intersect([Tempus.Slot.id(), Tempus.Slot.id()])
Tempus.Slot.id()

iex> Tempus.Slot.intersect([%Tempus.Slot{from: nil, to: ~U[2020-09-30 23:00:00Z]},
...>   %Tempus.Slot{from: nil, to: ~U[2020-09-30 23:00:00Z]}])
%Tempus.Slot{from: nil, to: ~U[2020-09-30 23:00:00Z]}

iex> Tempus.Slot.intersect([%Tempus.Slot{from: ~U[2020-09-30 23:00:00Z], to: nil},
...>   %Tempus.Slot{from: ~U[2020-09-30 23:00:00Z], to: nil}])
%Tempus.Slot{from: ~U[2020-09-30 23:00:00Z], to: nil}

iex> Tempus.Slot.intersect([~D|2020-09-30|, Tempus.Slot.id()])
%Tempus.Slot{from: ~U[2020-09-30 00:00:00.000000Z], to: ~U[2020-09-30 23:59:59.999999Z]}

iex> Tempus.Slot.intersect([Tempus.Slot.id(), ~D|2020-09-30|])
%Tempus.Slot{from: ~U[2020-09-30 00:00:00.000000Z], to: ~U[2020-09-30 23:59:59.999999Z]}

iex> Tempus.Slot.intersect([~D|2020-09-30|,
...>   %Tempus.Slot{from: ~U[2020-09-30 23:00:00Z], to: nil}])
%Tempus.Slot{from: ~U[2020-09-30 23:00:00Z], to: ~U[2020-09-30 23:59:59.999999Z]}

iex> Tempus.Slot.intersect([~D|2020-09-30|,
...>   %Tempus.Slot{from: nil, to: ~U[2020-09-30 23:00:00Z]}])
%Tempus.Slot{from: ~U[2020-09-30 00:00:00.000000Z], to: ~U[2020-09-30 23:00:00Z]}

iex> Tempus.Slot.intersect([
...>   %Tempus.Slot{from: ~U[2020-09-30 23:00:00Z], to: nil}, ~D|2020-09-30|])
%Tempus.Slot{from: ~U[2020-09-30 23:00:00Z], to: ~U[2020-09-30 23:59:59.999999Z]}

iex> Tempus.Slot.intersect([
...>   %Tempus.Slot{from: nil, to: ~U[2020-09-30 23:00:00Z]}, ~D|2020-09-30|])
%Tempus.Slot{from: ~U[2020-09-30 00:00:00.000000Z], to: ~U[2020-09-30 23:00:00Z]}

iex> Tempus.Slot.intersect([Tempus.Slot.wrap(~D|2020-09-30|),
...>   %Tempus.Slot{from: ~U|2020-09-30 23:00:00Z|, to: ~U|2020-10-02 00:00:00Z|}])
%Tempus.Slot{from: ~U[2020-09-30 23:00:00Z], to: ~U[2020-09-30 23:59:59.999999Z]}

iex> Tempus.Slot.intersect([~D|2020-09-30|, ~D|2000-09-30|,
...>   %Tempus.Slot{from: ~U|2020-09-30 23:00:00Z|, to: ~U|2020-10-02 00:00:00Z|}])
nil
@spec join(slots :: Enum.t()) :: t()

Joins slots to the maximal covered timeslice.

Example

iex> Tempus.Slot.join([])
Tempus.Slot.id()

iex> Tempus.Slot.join([Tempus.Slot.wrap(~D|2020-09-30|), Tempus.Slot.wrap(~D|2020-10-02|)])
%Tempus.Slot{from: ~U[2020-09-30 00:00:00.000000Z], to: ~U[2020-10-02 23:59:59.999999Z]}

iex> Tempus.Slot.join([~D|2020-09-30|, ~D|2020-10-02|])
%Tempus.Slot{from: ~U[2020-09-30 00:00:00.000000Z], to: ~U[2020-10-02 23:59:59.999999Z]}
@spec join(t(), t()) :: t()

Joins two slots to the maximal covered timeslice.

Example

iex> Tempus.Slot.join(Tempus.Slot.wrap(~D|2020-09-30|), Tempus.Slot.wrap(~D|2020-10-02|))
%Tempus.Slot{from: ~U[2020-09-30 00:00:00.000000Z], to: ~U[2020-10-02 23:59:59.999999Z]}

iex> Tempus.Slot.join(~D|2020-09-30|, ~D|2020-10-02|)
%Tempus.Slot{from: ~U[2020-09-30 00:00:00.000000Z], to: ~U[2020-10-02 23:59:59.999999Z]}
@spec neighbour?(s1 :: origin(), s2 :: origin()) :: boolean()

Returns true if two slots are neighbours, false otherwise.

Examples

iex> slot = %Tempus.Slot{from: ~U|2015-09-01 00:00:00Z|, to: ~U|2015-10-01 23:59:59Z|}
iex> Tempus.Slot.neighbour?(slot, Tempus.Slot.wrap(~D|2015-10-02|))
true
iex> Tempus.Slot.neighbour?(slot, Tempus.Slot.wrap(~D|2015-08-31|))
true
iex> Tempus.Slot.neighbour?(slot, Tempus.Slot.wrap(~D|2015-10-01|))
false
iex> Tempus.Slot.neighbour?(slot, Tempus.Slot.wrap(~D|2015-10-03|))
false
@spec new(from: origin(), to: origin()) :: {:ok, t()} | {:error, any()}

Creates new slot using arg[:from] as a starting origin and arg[:to] and an ending origin.

Examples

iex> Tempus.Slot.new(from: ~U|2015-09-30 00:00:00Z|, to: ~U|2015-10-01 01:00:00Z|)
{:ok, %Tempus.Slot{from: ~U|2015-09-30 00:00:00Z|, to: ~U|2015-10-01 01:00:00Z|}}
iex> Tempus.Slot.new(%{from: ~D|2015-09-30|, to: ~U|2015-10-01T12:00:00Z|})
{:ok, %Tempus.Slot{from: ~U|2015-09-30 00:00:00.000000Z|, to: ~U|2015-10-01 12:00:00Z|}}
@spec new(from :: origin(), to :: origin()) :: {:ok, t()} | {:error, any()}

Creates new slot using from as a starting origin and to and an ending origin. See new/1 for more readable implementation.

Examples

iex> import Tempus.Sigils
iex> Tempus.Slot.new(~U|2015-09-30 00:00:00Z|, ~U|2015-10-01 01:00:00Z|)
{:ok, %Tempus.Slot{from: ~U|2015-09-30 00:00:00Z|, to: ~U|2015-10-01 01:00:00Z|}}
iex> Tempus.Slot.new(~D|2015-09-30|, ~U|2015-10-01T12:00:00Z|)
{:ok, %Tempus.Slot{from: ~U|2015-09-30 00:00:00.000000Z|, to: ~U|2015-10-01 12:00:00Z|}}
iex> Tempus.Slot.new(nil, nil)
{:ok, Tempus.Slot.id()}
iex> Tempus.Slot.new(~D|2015-09-30|, nil)
{:ok, ~I(2015-09-30T00:00:00.000000Z → ∞)un}
iex> Tempus.Slot.new(nil, ~D|2015-09-30|)
{:ok, ~I(∞ → 2015-09-30T23:59:59.999999Z)nu}
iex> Tempus.Slot.new(:ok, :ok)
{:error, :invalid_input}
@spec new!(from :: origin(), to :: origin()) :: t() | no_return()

Creates new slot using from as a starting origin and to and an ending origin. Unlike new/1, this function raises on malformed input.

Examples

iex> Tempus.Slot.new!(~U|2015-09-30 00:00:00Z|, ~U|2015-10-01 01:00:00Z|)
%Tempus.Slot{from: ~U|2015-09-30 00:00:00Z|, to: ~U|2015-10-01 01:00:00Z|}
iex> Tempus.Slot.new!(~D|2015-09-30|, ~U|2015-10-01T12:00:00Z|)
%Tempus.Slot{from: ~U|2015-09-30 00:00:00.000000Z|, to: ~U|2015-10-01 12:00:00Z|}
iex> Tempus.Slot.new!(:ok, :ok)
** (ArgumentError) malformed from/to argument, expected `origin`
Link to this function

shift_tz(slot, tz \\ "Etc/UTC", tz_db \\ Calendar.get_time_zone_database())

View Source
@spec shift_tz(
  slot :: t(),
  tz :: Calendar.time_zone(),
  tz_db :: Calendar.time_zone_database()
) :: t()

Shifts both from and to values to UTC zone.

Examples

slot = %Tempus.Slot{
   from: DateTime.from_naive!(~N|2018-01-05 21:00:00|, "America/New_York"),
   to: DateTime.from_naive!(~N|2018-01-08 08:59:59|, "Australia/Sydney")
}
#⇒ %Tempus.Slot{from: ~U[2018-01-06 02:00:00Z], to: ~U[2018-01-07 21:59:59Z]}
@spec strict_compare(s1 :: origin(), s2 :: origin()) :: :eq | :lt | :gt | :joint

Compares two slot structs. The same as compare/2, but returns :joint if the slots are overlapped.

Examples

iex> Tempus.Slot.strict_compare(~D|2020-01-01|, DateTime.utc_now())
:lt
@spec valid?(slot :: t()) :: boolean()

Checks whether the Slot is valid (to > from) or not.

Examples

iex> slot = %Tempus.Slot{from: ~U|2015-09-30 00:00:00Z|, to: ~U|2015-10-01 01:00:00Z|}
iex> Tempus.Slot.valid?(slot)
true
iex> Tempus.Slot.valid?(%Tempus.Slot{from: slot.to, to: slot.from})
false
iex> slot = %Tempus.Slot{from: nil, to: ~U|2015-10-01 01:00:00Z|}
...> Tempus.Slot.valid?(slot)
true
iex> slot = %Tempus.Slot{from: ~U|2015-09-30 00:00:00Z|, to: nil}
...> Tempus.Slot.valid?(slot)
true
iex> Tempus.Slot.valid?(:ok)
false

Helper macro to pattern-match void slots.

Link to this function

wrap(moment \\ nil, origin \\ DateTime.utc_now())

View Source
@spec wrap(origin(), DateTime.t()) :: t()

Wraps the argument into a slot. For DateTime it’d be a single microsecond. For a Date, it would be the whole day, starting at 00:00:00.000000 and

ending at `23:59:59:999999`.

Examples

iex> Tempus.Slot.wrap(~D|2020-08-06|)
%Tempus.Slot{from: ~U[2020-08-06 00:00:00.000000Z], to: ~U[2020-08-06 23:59:59.999999Z]}
iex> Tempus.Slot.wrap(:ok)
Tempus.Slot.id()
@spec xor(outer :: t(), inner :: t()) :: [t()]

Splits the slot given asa first argument to two on borders given as a second slot.

Examples

iex> outer = Tempus.Slot.wrap(~D[2023-04-12])
...> {:ok, inner} = Tempus.Slot.new(~U[2023-04-12 12:00:00Z], ~U[2023-04-12 13:00:00Z])
iex> Tempus.Slot.xor(outer, inner)
[%Tempus.Slot{from: ~U[2023-04-12 00:00:00.000000Z], to: ~U[2023-04-12 12:00:00Z]},
 %Tempus.Slot{from: ~U[2023-04-12 13:00:00Z], to: ~U[2023-04-12 23:59:59.999999Z]}]
iex> Tempus.Slot.xor(outer, inner) == Tempus.Slot.xor(inner, outer)
true
iex> {:ok, past} = Tempus.Slot.new(~U[2020-04-12 12:00:00Z], ~U[2020-04-12 13:00:00Z])
...> Tempus.Slot.xor(past, inner)
[past, inner]
...> Tempus.Slot.xor(inner, past)
[past, inner]
iex> {:ok, border} = Tempus.Slot.new(~U[2023-04-12 11:00:00Z], ~U[2023-04-12 12:00:00Z])
...> Tempus.Slot.xor(border, inner)
[Tempus.Slot.new!(~U[2023-04-12 11:00:00Z], ~U[2023-04-12 13:00:00Z])]