Tempo.Interval.Steps (Tempo v0.20.0)

Copy Markdown View Source

Closed-form step arithmetic for interval enumeration.

Backs the Enumerable protocol implementation for Tempo.Interval.t/0 — specifically its count/1, slice/1, and member?/2 callbacks — with O(1) (or near-O(1)) implementations driven by the calendar's date algebra rather than walking the interval one step at a time.

Each function takes the iteration unit and the calendar in addition to the endpoints:

  • count_steps/4 — how many unit-wide steps fit in [from, to).

  • nth_step/4 — the n-th element from from at unit granularity.

  • on_step?/4 — whether element falls on a unit-step boundary anchored at from.

Phase 1 covers :year, :month, and :day. Sub-day units (:hour, :minute, :second, :microsecond) are added in subsequent phases.

Summary

Functions

Count the number of unit-wide steps in the half-open span [from, to).

Return the Tempo at step n from from at unit granularity.

Return true when element falls on a unit-step boundary anchored at from.

Functions

count_steps(from, to, arg3, calendar)

@spec count_steps(Tempo.t(), Tempo.t(), atom(), module()) ::
  non_neg_integer() | :not_supported

Count the number of unit-wide steps in the half-open span [from, to).

Arguments

  • from is the lower-bound Tempo.t/0.

  • to is the exclusive upper-bound Tempo.t/0.

  • unit is one of :year, :month, :day (Phase 1 scope).

  • calendar is the shared calendar module of both endpoints.

Returns

  • A non-negative integer count, or

  • :not_supported when the unit / calendar combination has no closed-form path. Callers should fall back to walking.

Examples

iex> from = Tempo.from_iso8601!("2026Y")
iex> to = Tempo.from_iso8601!("2030Y")
iex> Tempo.Interval.Steps.count_steps(from, to, :year, Calendrical.Gregorian)
4

iex> from = Tempo.from_iso8601!("2026-01")
iex> to = Tempo.from_iso8601!("2027-03")
iex> Tempo.Interval.Steps.count_steps(from, to, :month, Calendrical.Gregorian)
14

iex> from = Tempo.from_iso8601!("2026-01-01")
iex> to = Tempo.from_iso8601!("2026-02-01")
iex> Tempo.Interval.Steps.count_steps(from, to, :day, Calendrical.Gregorian)
31

nth_step(tempo, n, arg3, calendar)

@spec nth_step(Tempo.t(), non_neg_integer(), atom(), module()) ::
  Tempo.t() | :not_supported

Return the Tempo at step n from from at unit granularity.

Arguments

  • from is the anchor Tempo.t/0.

  • n is a non-negative integer step count (0 returns from).

  • unit is one of :year, :month, :day (Phase 1 scope).

  • calendar is the calendar module.

Returns

  • The Tempo at step n, or

  • :not_supported for unhandled units.

Examples

iex> from = Tempo.from_iso8601!("2026-01-01")
iex> Tempo.Interval.Steps.nth_step(from, 30, :day, Calendrical.Gregorian)
~o"2026Y1M31D"

iex> from = Tempo.from_iso8601!("2026-01")
iex> Tempo.Interval.Steps.nth_step(from, 14, :month, Calendrical.Gregorian)
~o"2027Y3M"

on_step?(element, from, unit, calendar)

@spec on_step?(Tempo.t(), Tempo.t(), atom(), module()) :: boolean() | :not_supported

Return true when element falls on a unit-step boundary anchored at from.

Arguments

  • element is any Tempo.t/0.

  • from is the anchor Tempo.t/0.

  • unit is one of :year, :month, :day (Phase 1 scope).

  • calendar is the calendar module.

Returns

  • true if element equals from advanced by some non-negative integer number of unit steps, false otherwise, or :not_supported.

Examples

iex> from = Tempo.from_iso8601!("2026-01-01")
iex> elt = Tempo.from_iso8601!("2026-01-31")
iex> Tempo.Interval.Steps.on_step?(elt, from, :day, Calendrical.Gregorian)
true