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

What a comparison of a time or a date and time says of the values, as sets of their images (D-109).

The run compares two of them (`Feel.Runtime.Temporal.compare/3`) by their **clocks** when either has no zone, and by
their **instants** when both have one, at the second. A set has the three lines of `Feel.Type.Moment` (the clock of
the values with no zone, and the instant and the clock of those with a zone), and `? < y` is, for the pairs of
classes that `?` and `y` can be of:

| `?` is | `y` is | `? < y` is true for |
| ------ | ------ | ------------------- |
| no zone | no zone | a clock before that of `y` |
| no zone | a zone | a clock before the clock of `y` |
| a zone | no zone | a zoned clock before the clock of `y` (its instant follows, within the largest offset) |
| a zone | a zone | an instant before that of `y` (its zoned clock follows, within the largest offset) |

So the sets are exact for the class that `y` is, whichever `?` is. The set of the values for which a comparison can be
true and the set for which it can be false are not each other's complement: a value 10 hours either side of `y` can be
either, when `y` may or may not have a zone. `Feel.Analysis.TestSets` reads both, as it does for a number, for the
narrowing of a name (`Feel.Analysis.Narrowing`) and for the allowed values of a variable.

Two sets are compared in the same way by `decide/3`, which says whether a comparison is `true` for every pair, `false`
for every pair, or for some.

    iex> alias Feel.Type.{Moment, NumberSet}
    iex> {:ok, date_time} = Feel.Value.DateTime.parse("2021-01-01T00:00:00")
    iex> {:ok, images} = Moment.images(date_time)
    iex> other = Enum.reduce(Enum.map(images, &NumberSet.point/1), &NumberSet.union/2)
    iex> {before, _} = Feel.Analysis.MomentTests.compared(:date_and_time, :lt, other, false, true)
    iex> Moment.format_member(:date_and_time, before)
    "in [-999999999-01-01T00:00:00..2021-01-01T00:00:00) any zone"

# `compared`

```elixir
@spec compared(
  Feel.Type.Moment.kind(),
  atom(),
  Feel.Type.NumberSet.t(),
  boolean(),
  boolean()
) ::
  {Feel.Type.NumberSet.t(), Feel.Type.NumberSet.t()}
```

Returns `{where `? operator other` can be true, where it can be false}` for a kind of moments, given the images that
`other` can be (`numbers`), whether it can be `null`, and whether it is one member of its type (a single value, if
the set says one).

Both are supersets of the images for which the comparison is `true` and `false`, in the form of the kind
(`Feel.Type.Moment.normalize/2`).

# `decide`

```elixir
@spec decide(atom(), Feel.Type.NumberSet.t(), Feel.Type.NumberSet.t()) ::
  :always | :never | :unknown
```

Whether `left operator right` is `true` for every pair of images of the two sets (`:always`), `false` for every pair
(`:never`), or for some (`:unknown`). The images are compared as the run compares the values: the clocks of two with no
zone, the clock of one with no zone and the clock of one with a zone, and the instants of two with one.

    iex> alias Feel.Type.NumberSet
    iex> a = NumberSet.interval(Decimal.new(0), Decimal.new(10))
    iex> b = NumberSet.interval(Decimal.new(100), Decimal.new(110))
    iex> Feel.Analysis.MomentTests.decide(:lt, a, b)
    :always
    iex> Feel.Analysis.MomentTests.decide(:gt, a, b)
    :never

---

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