# `Feel.Analysis.MomentZones`
[🔗](https://github.com/FeeJai/BDM/blob/feel-v0.1.0/apps/feel/lib/feel/analysis/moment_zones.ex#L1)

The `value`, `time offset` and `timezone` of a time or a date and time that is one of the seconds of a set (D-109).

Of the properties of Table 67, these three depend on the zone of the value, and a set has the lines of the zone
(`Feel.Type.Moment`): the clock of the values with no zone, and the instant and the clock of those with one. What the
run gives (`Feel.Runtime.Path`, `Feel.Runtime.Temporal.value/1`):

| Property | A value with no zone | A value with an offset or a zone id |
| -------- | -------------------- | ----------------------------------- |
| `value` of a date and time | an error, and `null` | the seconds from `1970-01-01T00:00:00Z` to the instant, with the fraction of the second (D-118), to 34 digits |
| `value` of a time | the seconds of the day, with the fraction | the seconds of the day less the offset, with the fraction, to 34 digits |
| `time offset` | `null` | the offset, which is the clock less the instant (a zone id has the one it has at the date, or in standard time for a time) |
| `timezone` | `null` | the id of a zone id, and `null` for an offset |

So `value` is the seconds of the line of the instants, from the second to the end of it; the offset is the difference of
the zoned clocks and the instants; and the zone is a string for a value with a zone, since the set does not say if it
has an offset or a zone id. Each is `null`, or an error, exactly for the values with no zone.

`restrict/4` is the other way round: a condition on one of them leaves the values that have it: those with no zone
stay for `null` only, and those with a zone are cut to the instants that have the value, or to the pairs of an instant
and a clock that have the offset.

    iex> alias Feel.Type.{Moment, NumberSet}
    iex> {:ok, date_time} = Feel.Value.DateTime.parse("1970-01-01T01:00:00+01:00")
    iex> {:ok, images} = Moment.images(date_time)
    iex> set = images |> Enum.map(&NumberSet.point/1) |> Enum.reduce(&NumberSet.union/2)
    iex> {:ok, value, :never} = Feel.Analysis.MomentZones.select(:date_and_time, set, "value")
    iex> Feel.Type.Union.format(value)
    "number in [0..1]"
    iex> {:ok, offset, :never} = Feel.Analysis.MomentZones.select(:date_and_time, set, "time offset")
    iex> Feel.Type.Union.format(offset)
    "days and time duration = PT1H"

# `errors`

```elixir
@type errors() :: :never | :maybe | :always
```

Whether selecting the property can be an error.

# `keys`

```elixir
@spec keys() :: [String.t(), ...]
```

The properties that depend on the zone.

# `restrict`

```elixir
@spec restrict(Feel.Type.Moment.kind(), Feel.Type.NumberSet.t(), String.t(), [
  Feel.Type.Union.member()
]) ::
  {:ok, Feel.Type.NumberSet.t()} | :error
```

The set of a time or a date and time cut to the values whose `key` is one of what `members` has, or `:error` if that is not
worked out. `members` is the type that a condition leaves of the property.

# `select`

```elixir
@spec select(Feel.Type.Moment.kind(), Feel.Type.NumberSet.t(), String.t()) ::
  {:ok, Feel.Type.Union.t(), errors()} | :error
```

The type of the property `key` of a time or a date and time in the set, and whether selecting it can be an error; or
`:error` if the set has no second.

---

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