Feel.Value.Temporal.Spellings (feel v0.1.0)

Copy Markdown View Source

Other spellings of the text of a time and of a date and time, and how DMN 1.6 writes them (D-81).

The strings that time(...), date and time(...) and @"..." read are those of XML Schema (DMN 1.6, section 10.3.4.1): a time has hours, minutes and seconds (13:30:00), and the zone of a date and time is a Z, an offset (+02:00) or the id of a zone after an @ (@Europe/Paris). The engines that run FEEL read more than that, most of all the text that Java writes: 2015-09-18T10:31:10+02:00[Europe/Paris], or a time without seconds. candidates/1 says what DMN 1.6 writes for a text that is one of these spellings.

It is used in two places, and they are not the same thing:

  • A function or a literal that fails to read its text says in the hint of its error how DMN 1.6 writes it (fix/2), whether or not any extension is on. The library tells; it does not accept.
  • An extension that reads the spelling hands the candidates to the library as Feel.Extension.temporal_text/1 (Feel.Extension.Camunda.TemporalFormats does), which uses the first that reads, and says so (D-81).

The rules are these, and a text that none of them applies to has no candidate:

TextDMN 1.6 writes it
13:30, 13:30Z, 13:30+02:00, 13:30@Europe/Paris13:30:00 with the same zone: no seconds
T23:59:00, T13:3023:59:00, 13:30:00: a T before a time
2020-01-01T10:30, 2020-01-01T00:00Zthe same with :00 seconds: a date and time without seconds
2018-04-29T09:30:00+02:00[Europe/Berlin]2018-04-29T09:30:00@Europe/Berlin: Java's text of a date and time in a zone

The last is the only one that says more than one thing, the offset and the zone, and it is read as the zone only if the offset is the one the zone has at that time: +02:00[Europe/Berlin] in the summer is @Europe/Berlin, and +05:00[Europe/Berlin] is not read. A local time that happens twice, where the clocks go back, is read as the earlier of the two (Feel.Value.Zone), so the text of the later has no candidate.

iex> Feel.Value.Temporal.Spellings.candidates("13:30")
["13:30:00"]
iex> Feel.Value.Temporal.Spellings.candidates("T23:59:00+01:00")
["23:59:00+01:00"]
iex> Feel.Value.Temporal.Spellings.candidates("2018-04-29T09:30:00+02:00[Europe/Berlin]")
["2018-04-29T09:30:00@Europe/Berlin"]
iex> Feel.Value.Temporal.Spellings.candidates("2018-04-29T09:30:00+05:00[Europe/Berlin]")
[]
iex> Feel.Value.Temporal.Spellings.candidates("13:30:00")
[]

Summary

Types

What reads the text of a temporal value as DMN 1.6 writes it: Feel.Value.Time.parse/1, Feel.Value.Temporal.parse/1.

Functions

The ways that DMN 1.6 writes text, if it is one of the other spellings above: none, or one.

Reads text with parse as DMN 1.6 writes it, if it is one of the other spellings: the first of the candidates/1 that parse reads, with the value and the text it read.

The hint of the error of a text that parse does not read: how DMN 1.6 writes it if it is one of the other spellings and parse reads that, and nil otherwise. at? is for the text of a literal, @"...".

Types

parser()

@type parser() :: (String.t() -> {:ok, Feel.Value.Temporal.t()} | :error)

What reads the text of a temporal value as DMN 1.6 writes it: Feel.Value.Time.parse/1, Feel.Value.Temporal.parse/1.

Functions

candidates(text)

@spec candidates(String.t()) :: [String.t()]

The ways that DMN 1.6 writes text, if it is one of the other spellings above: none, or one.

fix(text, parse)

@spec fix(String.t(), parser()) :: {:ok, Feel.Value.Temporal.t(), String.t()} | :error

Reads text with parse as DMN 1.6 writes it, if it is one of the other spellings: the first of the candidates/1 that parse reads, with the value and the text it read.

iex> Feel.Value.Temporal.Spellings.fix("13:30", &Feel.Value.Time.parse/1) |> elem(2)
"13:30:00"
iex> Feel.Value.Temporal.Spellings.fix("13:30", &Feel.Value.Date.parse/1)
:error
iex> Feel.Value.Temporal.Spellings.fix("nonsense", &Feel.Value.Time.parse/1)
:error

hint(text, parse, at?)

@spec hint(String.t(), parser(), boolean()) :: String.t() | nil

The hint of the error of a text that parse does not read: how DMN 1.6 writes it if it is one of the other spellings and parse reads that, and nil otherwise. at? is for the text of a literal, @"...".

iex> Feel.Value.Temporal.Spellings.hint("13:30", &Feel.Value.Time.parse/1, false)
~s(DMN 1.6 writes it "13:30:00")
iex> Feel.Value.Temporal.Spellings.hint("13:30", &Feel.Value.Time.parse/1, true)
~s(DMN 1.6 writes it @"13:30:00")
iex> Feel.Value.Temporal.Spellings.hint("x", &Feel.Value.Time.parse/1, false)
nil