Feel.Value.DaysAndTimeDuration (feel v0.1.0)

Copy Markdown View Source

The FEEL type days and time duration (DMN 1.6, section 10.3.2.3.7).

A number of seconds, positive or negative, with a fractional part. A day is exactly 86,400 seconds; there are no calendar or daylight-saving effects. This type never mixes with years and months duration.

The components FEEL exposes (days, hours, minutes, seconds) are computed from the total when read; they are not stored.

Fields

Summary

Functions

Builds a duration from a total number of seconds.

Parses a duration string of days and time, as duration("...") and @"..." read it: the lexical space of the XPath dayTimeDuration (DMN 1.6, section 10.3.4.1).

Returns the type descriptor of days and time duration.

Returns true for a t/0 with a finite number of seconds.

Types

t()

@type t() :: %Feel.Value.DaysAndTimeDuration{seconds: Feel.Value.Number.t()}

Functions

new(seconds)

@spec new(Feel.Value.Number.t() | integer()) :: t()

Builds a duration from a total number of seconds.

Accepts an integer or a Feel.Value.Number. Raises FunctionClauseError for anything else, including a non-finite decimal.

iex> Feel.Value.DaysAndTimeDuration.new(90_000).seconds |> Decimal.to_integer()
90000

parse(text)

@spec parse(String.t()) :: {:ok, t()} | :error

Parses a duration string of days and time, as duration("...") and @"..." read it: the lexical space of the XPath dayTimeDuration (DMN 1.6, section 10.3.4.1).

It is P, then days (nD), then T with hours (nH), minutes (nM) and seconds (nS, which may have a fraction), in that order, with a leading - for a negative duration. Every part is optional, but one is needed, and T needs one of the parts after it. The parts are not limited to their usual range: P0DT25H is one day and one hour. White space around the string is ignored. Returns :error for anything else, which includes a years or months part (P1Y is a years and months duration), and a number of seconds beyond 34 digits.

The seconds are exact: the parts are added as integers, so the 28 digits that the Decimal context rounds to do not matter.

iex> Feel.Value.DaysAndTimeDuration.parse("P1DT2H")
{:ok, Feel.Value.DaysAndTimeDuration.new(93_600)}
iex> Feel.Value.DaysAndTimeDuration.parse("-PT5H30M")
{:ok, Feel.Value.DaysAndTimeDuration.new(-19_800)}
iex> {:ok, duration} = Feel.Value.DaysAndTimeDuration.parse("PT1.50S")
iex> Decimal.to_string(duration.seconds)
"1.50"
iex> Feel.Value.DaysAndTimeDuration.parse("P0DT25H") ==
...>   Feel.Value.DaysAndTimeDuration.parse("P1DT1H")
true
iex> Feel.Value.DaysAndTimeDuration.parse("P1Y")
:error
iex> Feel.Value.DaysAndTimeDuration.parse("PT")
:error

type()

@spec type() :: Feel.Type.t()

Returns the type descriptor of days and time duration.

value?(arg1)

@spec value?(term()) :: boolean()

Returns true for a t/0 with a finite number of seconds.