A calendar-relative duration — a list of {unit, amount}
pairs such as [year: 1, month: 6]. Produced by the ISO 8601
parser (P1Y6M), the RRULE encoder (as the FREQ + INTERVAL
cadence), and arithmetic helpers in Tempo.Math.
Summary
Functions
Construct a Tempo.Duration.t/0 from a keyword list of
{unit, amount} pairs.
Bang variant of new/1.
Express a duration as a single magnitude in unit, as a float.
Bang variant of to_unit/3 — returns the float or raises.
Types
@type t() :: %Tempo.Duration{time: [{unit(), integer() | Tempo.Microsecond.t()}]}
@type unit() ::
:year
| :month
| :week
| :day
| :hour
| :minute
| :second
| :microsecond
| :day_of_year
| :day_of_week
Functions
@spec new(keyword()) :: {:ok, t()} | {:error, Exception.t()}
Construct a Tempo.Duration.t/0 from a keyword list of
{unit, amount} pairs.
Components can be passed in any order; new/1 reorders them
coarse-to-fine before building the struct.
Arguments
componentsis a keyword list of duration units.
Options
Every value must be an integer. Negative values are permitted (reverse-direction duration).
:yearis the year count.:monthis the month count.:weekis the week count.:dayis the day count.:day_of_yearis a day-of-year offset (used by RRULE expansion).:day_of_weekis a day-of-week offset (used by RRULE expansion).:houris the hour count.:minuteis the minute count.:secondis the second count.
Returns
{:ok, t()}on success.{:error, reason}when a key is unknown or a value is not an integer.
Examples
iex> {:ok, d} = Tempo.Duration.new(year: 1, month: 6)
iex> d.time
[year: 1, month: 6]
iex> {:ok, d} = Tempo.Duration.new(month: 6, year: 1)
iex> d.time
[year: 1, month: 6]
Bang variant of new/1.
@spec to_unit(t(), unit(), keyword()) :: {:ok, float()} | {:error, Exception.t()}
Express a duration as a single magnitude in unit, as a float.
For a duration built only from fixed-length units (microsecond
through week, with day = 24 h and week = 7 d), the conversion
is exact and needs no context. A duration carrying :month or
:year has no fixed length, so it converts only against a
reference date supplied as :relative_to — the duration is applied
to that date and the elapsed time measured on the UTC time line
(DST-exact when the reference is zoned). Tempo never assumes a
nominal month or year; it returns an error instead.
Arguments
durationis at/0.unitis the target unit — one of:microsecond,:second,:minute,:hour,:day,:week. (:month/:yearare not fixed magnitudes and cannot be a target.)
Options
:relative_tois aTempo.t/0reference date. Required to convert a duration containing:monthor:year; optional otherwise, where a zoned reference makes:day/:weekDST-exact.
Returns
{:ok, magnitude}wheremagnitudeis afloat().{:error, reason}when the duration needs a:relative_toit was not given, the target unit is not fixed-length, or the reference is invalid.
Examples
iex> Tempo.Duration.to_unit(~o"PT90M", :hour)
{:ok, 1.5}
iex> Tempo.Duration.to_unit(~o"P2D", :hour)
{:ok, 48.0}
iex> Tempo.Duration.to_unit(~o"P1M", :day, relative_to: ~o"2026-02-01")
{:ok, 28.0}
Bang variant of to_unit/3 — returns the float or raises.
Examples
iex> Tempo.Duration.to_unit!(~o"PT8H", :hour)
8.0