Tempo.Duration (Tempo v0.20.0)

Copy Markdown View Source

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

t()

@type t() :: %Tempo.Duration{time: [{unit(), integer() | Tempo.Microsecond.t()}]}

unit()

@type unit() ::
  :year
  | :month
  | :week
  | :day
  | :hour
  | :minute
  | :second
  | :microsecond
  | :day_of_year
  | :day_of_week

Functions

new(components)

@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

  • components is a keyword list of duration units.

Options

Every value must be an integer. Negative values are permitted (reverse-direction duration).

  • :year is the year count.

  • :month is the month count.

  • :week is the week count.

  • :day is the day count.

  • :day_of_year is a day-of-year offset (used by RRULE expansion).

  • :day_of_week is a day-of-week offset (used by RRULE expansion).

  • :hour is the hour count.

  • :minute is the minute count.

  • :second is 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]

new!(components)

@spec new!(keyword()) :: t()

Bang variant of new/1.

to_unit(duration, unit, options \\ [])

@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

  • duration is a t/0.

  • unit is the target unit — one of :microsecond, :second, :minute, :hour, :day, :week. (:month/:year are not fixed magnitudes and cannot be a target.)

Options

  • :relative_to is a Tempo.t/0 reference date. Required to convert a duration containing :month or :year; optional otherwise, where a zoned reference makes :day/:week DST-exact.

Returns

  • {:ok, magnitude} where magnitude is a float().

  • {:error, reason} when the duration needs a :relative_to it 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}

to_unit!(duration, unit, options \\ [])

@spec to_unit!(t(), unit(), keyword()) :: float()

Bang variant of to_unit/3 — returns the float or raises.

Examples

iex> Tempo.Duration.to_unit!(~o"PT8H", :hour)
8.0