Tempo.Network.TimePeriod (Tempo Network v1.0.0)

Copy Markdown View Source

A single time-period in a chronological network — a reign, era, or the time-span of a stratum.

Following the ChronoLog data model (Levy et al. 2020), a period carries independent bounds on three quantities, each of which may be unknown (nil), known, lower-bounded, upper-bounded, or known within a range:

  • its start — earliest_start..latest_start;

  • its end — earliest_end..latest_end;

  • its duration — min_duration..max_duration.

Duration is modelled separately from the start/end pair (it is not forced to equal end - start at construction time); the solver reconciles all three through the constraint end - start ∈ [min_duration, max_duration].

Start/end bounds are Tempo.t/0 values (so they carry their own calendar and resolution); duration bounds are Duration.t/0. An EDTF/ISO 8601 string or a bare integer year is accepted by the constructor and normalised to the corresponding Tempo value.

Summary

Types

A start/end bound: a Tempo value, or nil when unknown.

A duration bound: a Tempo duration, or nil when unknown.

t()

Functions

Build a time-period.

Build a time-period, raising on an error.

The integer year of a date bound, or nil.

Types

date_bound()

@type date_bound() :: Tempo.t() | nil

A start/end bound: a Tempo value, or nil when unknown.

duration_bound()

@type duration_bound() :: Tempo.Duration.t() | nil

A duration bound: a Tempo duration, or nil when unknown.

t()

@type t() :: %Tempo.Network.TimePeriod{
  earliest_end: date_bound(),
  earliest_start: date_bound(),
  id: term(),
  latest_end: date_bound(),
  latest_start: date_bound(),
  max_duration: duration_bound(),
  metadata: map(),
  min_duration: duration_bound(),
  name: String.t() | nil
}

Functions

new(id, options \\ [])

@spec new(term(), keyword()) :: {:ok, t()} | {:error, Exception.t()}

Build a time-period.

Arguments

  • id is any term uniquely identifying the period within its network (commonly an atom such as :k1 or a string).

  • options is a keyword list of options.

Options

  • :name is a human-readable label.

  • :from constrains when the period starts. It accepts an exact value, a {lower, upper} range, {:not_before, value}, or {:not_after, value} (see "Bound specifications").

  • :to constrains when the period ends, with the same shapes as :from.

  • :duration constrains the duration. It accepts an exact duration, a {min, max} range, {:at_least, duration}, or {:at_most, duration}.

  • :metadata is an arbitrary map carried with the period (EDTF qualifiers, provenance, notes). It does not affect the solver.

Bound specifications

A date value is a Tempo.t/0 — idiomatically a sigil literal such as ~o"1200Y", ~o"-664Y", or ~o"1200-06-15". As a year-grained convenience an EDTF/ISO 8601 string ("1200Y") or a bare integer year (1200, -664 for BCE) is also accepted and normalised to the corresponding Tempo value.

A duration value is a Duration.t/0 (~o"P20Y"); an ISO 8601 duration string ("P20Y") or a bare integer number of years is likewise accepted.

All bounds are stored, and returned, as Tempo values.

Returns

  • {:ok, period}.

  • {:error, reason} for an option new/2 does not take — 1.x's :start and :end included, now :from and :to — or a bound that is not a date or a duration.

Examples

iex> {:ok, period} = Tempo.Network.TimePeriod.new(:k1, name: "King 1", from: {:not_before, ~o"1200Y"})
iex> {period.id, period.name, period.earliest_start}
{:k1, "King 1", ~o"1200Y"}

iex> {:ok, period} = Tempo.Network.TimePeriod.new(:s1, duration: {:at_least, ~o"P20Y"})
iex> period.min_duration
~o"P20Y"

iex> {:error, %ArgumentError{} = error} = Tempo.Network.TimePeriod.new(:k1, start: ~o"1200Y")
iex> Exception.message(error)
"Tempo.Network.TimePeriod.new/2 takes :from where 1.x took :start."

new!(id, options \\ [])

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

Build a time-period, raising on an error.

Arguments

  • id is any term uniquely identifying the period.

  • options is a keyword list of options, as for new/2.

Options

Returns

  • A t/0, or raises the error new/2 returns.

Examples

iex> Tempo.Network.TimePeriod.new!(:k1, to: {:not_after, 1300}).latest_end
~o"1300Y"

year(value)

@spec year(date_bound()) :: integer() | nil

The integer year of a date bound, or nil.

A convenience for tests and traces; the solver works at the network's finest unit rather than always in years.

Arguments

  • bound is a date bound of a period, a Tempo.t/0, or nil.

Returns

  • The bound's year as an integer.

  • nil when the bound is nil.

Examples

iex> Tempo.Network.TimePeriod.year(~o"1200Y")
1200

iex> Tempo.Network.TimePeriod.year(nil)
nil