Feel.Value.DateTime (feel v0.1.0)

Copy Markdown View Source

The FEEL type date and time (DMN 1.6, section 10.3.2.3.6): a date together with a time of day.

It is a Feel.Value.Date plus a Feel.Value.Time. Elixir's DateTime is not used because it has microsecond precision and needs a time zone database to normalize values, while FEEL needs nanosecond precision and has to keep the original zone form (floating, offset, or IANA) to compare and format values correctly.

Fields

Summary

Functions

Combines a date and a time.

Parses a date and time string, as date and time("...") and @"..." read it: a date string, optionally followed by T and a time string (DMN 1.6, section 10.3.4.1).

Returns the type descriptor of date and time.

Returns true for a t/0 whose date and time are both valid.

Types

t()

@type t() :: %Feel.Value.DateTime{
  date: Feel.Value.Date.t(),
  time: Feel.Value.Time.t()
}

Functions

new(date, time)

@spec new(Feel.Value.Date.t(), Feel.Value.Time.t()) :: {:ok, t()} | :error

Combines a date and a time.

Returns :error when the date or the time is not a valid FEEL value, such as a year outside the FEEL range.

iex> {:ok, time} = Feel.Value.Time.new(0, 0, 0, {:offset, 0})
iex> {:ok, date_time} = Feel.Value.DateTime.new(~D[2026-10-12], time)
iex> date_time.date
~D[2026-10-12]
iex> Feel.Value.DateTime.new(Date.new!(1_000_000_000, 1, 1), time)
:error

parse(text)

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

Parses a date and time string, as date and time("...") and @"..." read it: a date string, optionally followed by T and a time string (DMN 1.6, section 10.3.4.1).

The time string is read as Feel.Value.Time.parse/1 reads it, so the value has the zone that the string gives: none (floating), an offset, or an IANA zone id; and a time of 24:00:00 is the start of the next day. A date alone is midnight with no zone, as the TCK has it (date and time("2012-12-24") is 2012-12-24T00:00:00, case 1117#007), and not the UTC midnight that the conversion of a date to a date and time in an operation gives (notes 06, AE-12; D-54). A date followed by a zone is midnight in that zone, with the forms of a time string: Z, an offset, @ and the id of a zone. It is the one example of the specification for the properties, date and time("2012-03-07Z").year (Table 65, printed 2012-0307Z; D-68). Returns :error for anything else.

iex> {:ok, date_time} = Feel.Value.DateTime.parse("2012-12-24T23:59:00")
iex> {date_time.date, date_time.time.hour, date_time.time.zone}
{~D[2012-12-24], 23, :floating}
iex> {:ok, date_time} = Feel.Value.DateTime.parse("2012-12-25T11:00:00Z")
iex> date_time.time.zone
{:offset, 0}
iex> {:ok, date_time} = Feel.Value.DateTime.parse("2024-12-24T23:59:00@America/Costa_Rica")
iex> date_time.time.zone
{:iana, "America/Costa_Rica"}
iex> {:ok, date_time} = Feel.Value.DateTime.parse("2012-12-24")
iex> {date_time.time.hour, date_time.time.zone}
{0, :floating}
iex> {:ok, date_time} = Feel.Value.DateTime.parse("2012-03-07Z")
iex> {date_time.date, date_time.time.hour, date_time.time.zone}
{~D[2012-03-07], 0, {:offset, 0}}
iex> {:ok, date_time} = Feel.Value.DateTime.parse("2012-03-07-05:00")
iex> date_time.time.zone
{:offset, -18000}
iex> Feel.Value.DateTime.parse("2012-03-07 Z")
:error
iex> {:ok, date_time} = Feel.Value.DateTime.parse("2012-12-24T24:00:00")
iex> {date_time.date, date_time.time.hour}
{~D[2012-12-25], 0}
iex> Feel.Value.DateTime.parse("2012-12-24T")
:error
iex> Feel.Value.DateTime.parse("2012-12-24T 10:00:00")
:error

type()

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

Returns the type descriptor of date and time.

value?(arg1)

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

Returns true for a t/0 whose date and time are both valid.