# `Feel.Value.Temporal.Spellings`
[🔗](https://github.com/FeeJai/BDM/blob/feel-v0.1.0/apps/feel/lib/feel/value/temporal/spellings.ex#L1)

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 `c: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:

| Text | DMN 1.6 writes it |
| ---- | ----------------- |
| `13:30`, `13:30Z`, `13:30+02:00`, `13:30@Europe/Paris` | `13:30:00` with the same zone: no seconds |
| `T23:59:00`, `T13:30` | `23:59:00`, `13:30:00`: a `T` before a time |
| `2020-01-01T10:30`, `2020-01-01T00:00Z` | the 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")
    []

# `parser`

```elixir
@type parser() :: (String.t() -&gt; {: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`.

# `candidates`

```elixir
@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`

```elixir
@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`

```elixir
@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

---

*Consult [api-reference.md](api-reference.md) for complete listing*
