The numbers that stand for a time and for a date and time in a set (D-109).
A date and a duration are ordered as a number is, and the number of a value is its image (Feel.Type.Image). A
time and a date and time are not: the order of two of them depends on their zones
(Feel.Runtime.Temporal.compare/3). When either has no zone their local clocks are compared, and when both have
a zone (an offset or a zone id) their instants are, at the second (D-54: 10:30:00.0001 and 10:30:00.0002 are
equal). A value with no zone has one number to compare, its clock; one with a zone has two, its instant and its clock,
and which one a comparison needs depends on the other side.
So the image of a value is the whole second it falls in, and a set has three lines of them, far apart on the number line (each within 3.2E+16 of its centre, the centres 1E+17 apart):
| Line | Of | Its numbers | Written |
|---|---|---|---|
| the clock | the values with no zone | the seconds of the local clock since 0000-01-01T00:00:00; for a time the seconds of the day, 0 to 86,399 | 2021-01-31T10:30:00 |
| the instants | the values with a zone | the seconds of the instant since 0000-01-01T00:00:00Z; for a time the seconds of the day less the offset, as the run orders times (not wrapped: 00:30:00+01:00 is -1,800) | 2021-01-31T09:30:00Z |
| the zoned clock | the values with a zone | the seconds of the local clock, as the first | zoned clock 2021-01-31T10:30:00 |
A fourth line holds the fraction of the second (D-118): the images are whole seconds, and a value has a fraction of
one past it, .5 for 10:00:00.5. It is the same for the values of every zone, so the set has the one line of them:
the seconds [0..1) that a value can have, which are all of them when nothing is known (a range of allowed values has
any), {0} for a value of whole seconds, and so on. A comparison does not look at it (the run compares at the
second); the sum with a fraction, the difference, the second and the value do (Feel.Analysis.MomentArithmetic,
Feel.Analysis.MomentZones, Feel.Analysis.MomentProperties). It is on the number line at 3E+17, and a set that has
none has every fraction.
A set holds the values of the first line, and those of a zone that have their instant in the second and their
clock in the third: a set of three lines is a box, and a value of a zone is in it when both its numbers are. The
clock of an instant is the instant and an offset, and an offset is within 18 hours (a fixed offset is within 14,
and the zones of the time zone database had a local mean time of up to 15 hours 56 minutes, Asia/Manila before
1844), so each of the two lines is within that of the other, and normalize/2 cuts each to that. A set with a line
of the instants and none of the zoned clock has no value with a zone, and neither is kept.
iex> {:ok, date_time} = Feel.Value.DateTime.parse("2021-01-01T00:00:00")
iex> {:ok, [image]} = Feel.Type.Moment.images(date_time)
iex> Feel.Type.Moment.format_value(:date_and_time, image)
"2021-01-01T00:00:00"
iex> {:ok, date_time} = Feel.Value.DateTime.parse("2021-01-01T00:00:00+01:00")
iex> {:ok, [instant, clock]} = Feel.Type.Moment.images(date_time)
iex> {Feel.Type.Moment.format_value(:date_and_time, instant), Feel.Type.Moment.format_value(:date_and_time, clock)}
{"2020-12-31T23:00:00Z", "2021-01-01T00:00:00"}
Summary
Types
A kind whose sets are sets of moments.
Functions
The first and the last second of the clock of a kind: of the calendar for a date and time, of a day for a time.
The values of a kind that a set leaves out (D-152), as a set: every one of them, and no other where a set of lines can say it.
Whether a value is one of a set: its seconds are on the lines, and its fraction is one of the fractions.
A set with every number within some seconds of one of its own, ends included: what the clock of a value can be when its instant is in the set and its offset is within that many seconds, and the other way round.
The images of the values of a kind with no zone: the first line.
Writes the set of a kind of moments after the name of the kind: = 2021-01-31T10:30:00+01:00 for the one value of
a zone, which is written with its offset, and in and the lines of it otherwise: those with no zone as they are, the
instants of the values with a zone with a Z, and their clocks as zoned clock (left out when the instants say as
much, and when the clocks are those of the values with no zone, any zone takes their place).
Writes the value that an image stands for: a clock as 2021-01-31T10:30:00, an instant in UTC as
2021-01-31T09:30:00Z; a time as 10:30:00 and 09:30:00Z. The clock of a zoned value is written as a clock.
A time on the line of the instants is not wrapped, so one before midnight UTC is written with a minus
(-00:30:00Z) and one after it past 24 hours (24:30:00Z). A number that is none of these is written as it is.
The fraction of a second of a value, exactly: 0.5 for 10:00:00.5.
The fractions of a second that any value can have: [0..1).
The fractions of a second that the values of a set can have, as numbers in [0..1). A set that has no line of them
has every fraction.
The images of a time or a date and time: {:ok, [clock]} for one with no zone, and {:ok, [instant, zoned_clock]}
for one with a zone. It is :error for a value that is not one of FEEL (a zone that is not in the database, a year
out of range).
The kinds whose sets are sets of moments: :time and :date_and_time.
The largest offset of a zone from UTC, in seconds (18 hours).
The set cut to the values of the kind there are, with its lines of a zone made to agree: the instants within the largest offset of the zoned clocks and the zoned clocks within it of the instants, and neither if the other is none.
The most that the instant of a date and time, as the run reads it, can be below the instant it was moved to, for instants from the one given: 2 hours from 2023-03-09, and 25 hours before it.
The set of the one value of a time or a date and time: its lines and its fraction. It is :error for a value that is
not one of FEEL.
A set moved by a number of seconds: every end of every interval.
A set moved by whole seconds with no rounding: a fraction of a second is as long as a second can be, and the
arithmetic of Decimal rounds to 28 digits.
The three lines of a set, each as the seconds it holds, with the numbers of the second and third taken back to the
seconds they are: {clock, instants, zoned_clock}.
The union of two sets of one kind, line by line: a line of more than 16 intervals is made its own hull, and not the
hull of the lines together, which a Feel.Type.NumberSet of that many would be.
The images of every value of a kind, on the three lines.
The three lines of the universe of a kind, as the seconds they hold.
The set with the fractions of a second given (a set of numbers in [0..1)), in place of the ones it had. An empty set
of fractions leaves the set with every fraction.
Types
@type kind() :: :time | :date_and_time
A kind whose sets are sets of moments.
@type lines() :: {Feel.Type.NumberSet.t(), Feel.Type.NumberSet.t(), Feel.Type.NumberSet.t()}
The three lines of a set, each as the seconds it holds (split/1).
Functions
The first and the last second of the clock of a kind: of the calendar for a date and time, of a day for a time.
iex> Feel.Type.Moment.clock_range(:time)
{0, 86399}
@spec complement(Feel.Type.NumberSet.t(), kind()) :: Feel.Type.NumberSet.t()
The values of a kind that a set leaves out (D-152), as a set: every one of them, and no other where a set of lines can say it.
A value with no zone is left out when the set has not its clock. A value with a zone is in the set when its instant is on
the second line and its clock on the third, so it is left out when its instant is not, or its clock: two boxes, and a
set is one. The set that holds both has the instants that the set leaves out and those within the largest offset of the
clocks that it leaves out, and the clocks likewise. It holds a value that the set holds as well only if an instant and a
clock that it leaves out are both there and near each other, so the answer is exact when the set holds a line whole,
when it holds no value with a zone, and when its instants are what its clocks give within the largest offset (which is how a
bound on a time of any zone is made: time >= 10:00:00). Otherwise it holds more.
The fractions of a second are one line for the values of every zone, and a set of some of them leaves values out on every other line, which is no box. For that, and for a set that holds no value, the answer is every value of the kind.
iex> alias Feel.Type.{Moment, NumberSet, Union}
iex> morning = Moment.join({NumberSet.interval(Decimal.new(0), Decimal.new(36_000)), [], []})
iex> Union.format([{:time, Moment.complement(morning, :time)}])
"time in (10:00:00..23:59:59], instants [-18:00:00Z..41:59:59Z]"
iex> Moment.complement(Moment.universe(:time), :time)
[]
iex> {:ok, time} = Feel.Value.Time.parse("10:00:00.5")
iex> {:ok, point} = Moment.point(time)
iex> Moment.complement(point, :time) == Moment.universe(:time)
true
@spec contains?( Feel.Type.NumberSet.t(), Feel.Value.Time.t() | Feel.Value.DateTime.t() ) :: boolean()
Whether a value is one of a set: its seconds are on the lines, and its fraction is one of the fractions.
@spec dilate(Feel.Type.NumberSet.t(), non_neg_integer()) :: Feel.Type.NumberSet.t()
A set with every number within some seconds of one of its own, ends included: what the clock of a value can be when its instant is in the set and its offset is within that many seconds, and the other way round.
iex> set = Feel.Type.NumberSet.point(Decimal.new(100))
iex> Feel.Type.NumberSet.format(Feel.Type.Moment.dilate(set, 10))
"[90..110]"
@spec floating(kind()) :: Feel.Type.NumberSet.t()
The images of the values of a kind with no zone: the first line.
@spec format_member(kind(), Feel.Type.NumberSet.t()) :: String.t()
Writes the set of a kind of moments after the name of the kind: = 2021-01-31T10:30:00+01:00 for the one value of
a zone, which is written with its offset, and in and the lines of it otherwise: those with no zone as they are, the
instants of the values with a zone with a Z, and their clocks as zoned clock (left out when the instants say as
much, and when the clocks are those of the values with no zone, any zone takes their place).
iex> {:ok, date_time} = Feel.Value.DateTime.parse("2021-01-31T10:30:00+01:00")
iex> Feel.Type.Union.format(Feel.Type.Union.of_value(date_time))
"date and time = 2021-01-31T10:30:00+01:00"
Writes the value that an image stands for: a clock as 2021-01-31T10:30:00, an instant in UTC as
2021-01-31T09:30:00Z; a time as 10:30:00 and 09:30:00Z. The clock of a zoned value is written as a clock.
A time on the line of the instants is not wrapped, so one before midnight UTC is written with a minus
(-00:30:00Z) and one after it past 24 hours (24:30:00Z). A number that is none of these is written as it is.
iex> Feel.Type.Moment.format_value(:time, Decimal.new(37_800))
"10:30:00"
iex> Feel.Type.Moment.format_value(:time, Decimal.new(100_000_000_000_000_000 - 1800))
"-00:30:00Z"
@spec fraction(Feel.Value.Time.t() | Feel.Value.DateTime.t()) :: Decimal.t()
The fraction of a second of a value, exactly: 0.5 for 10:00:00.5.
iex> {:ok, time} = Feel.Value.Time.parse("10:00:00.5")
iex> Feel.Type.Moment.fraction(time)
Decimal.new("0.5")
@spec fraction_universe() :: Feel.Type.NumberSet.t()
The fractions of a second that any value can have: [0..1).
@spec fractions(Feel.Type.NumberSet.t()) :: Feel.Type.NumberSet.t()
The fractions of a second that the values of a set can have, as numbers in [0..1). A set that has no line of them
has every fraction.
iex> alias Feel.Type.{Moment, NumberSet}
iex> {:ok, time} = Feel.Value.Time.parse("10:00:00.5")
iex> {:ok, set} = Moment.point(time)
iex> NumberSet.format(Moment.fractions(set))
"0.5"
iex> NumberSet.format(Moment.fractions(NumberSet.point(Decimal.new(36_000))))
"[0..1)"
@spec images(Feel.Value.Time.t() | Feel.Value.DateTime.t()) :: {:ok, [Decimal.t(), ...]} | :error
The images of a time or a date and time: {:ok, [clock]} for one with no zone, and {:ok, [instant, zoned_clock]}
for one with a zone. It is :error for a value that is not one of FEEL (a zone that is not in the database, a year
out of range).
iex> {:ok, time} = Feel.Value.Time.parse("10:30:00.5")
iex> Feel.Type.Moment.images(time)
{:ok, [Decimal.new(37_800)]}
iex> {:ok, time} = Feel.Value.Time.parse("00:30:00+01:00")
iex> {:ok, [instant, clock]} = Feel.Type.Moment.images(time)
iex> {Decimal.sub(instant, Decimal.new(100_000_000_000_000_000)), Decimal.sub(clock, Decimal.new(200_000_000_000_000_000))}
{Decimal.new(-1800), Decimal.new(1800)}
@spec join(lines()) :: Feel.Type.NumberSet.t()
The set of three lines, as split/1 gives them: the inverse.
@spec kinds() :: [kind(), ...]
The kinds whose sets are sets of moments: :time and :date_and_time.
@spec max_offset() :: pos_integer()
The largest offset of a zone from UTC, in seconds (18 hours).
@spec normalize(Feel.Type.NumberSet.t(), kind()) :: Feel.Type.NumberSet.t()
The set cut to the values of the kind there are, with its lines of a zone made to agree: the instants within the largest offset of the zoned clocks and the zoned clocks within it of the instants, and neither if the other is none.
iex> alias Feel.Type.{Moment, NumberSet}
iex> {clock, instants, _} = Moment.universe_lines(:time)
iex> set = Moment.join({[], instants, NumberSet.interval(Decimal.new(0), Decimal.new(3600))})
iex> {_, instants, zoned_clock} = set |> Moment.normalize(:time) |> Moment.split()
iex> {NumberSet.format(instants), NumberSet.format(zoned_clock)}
{"[-64800..68400]", "[0..3600]"}
iex> set |> Moment.join_without_clocks() |> Moment.normalize(:time) |> Moment.split()
{[], [], []}
iex> NumberSet.format(clock)
"[0..86399]"
@spec overlap(integer()) :: pos_integer()
The most that the instant of a date and time, as the run reads it, can be below the instant it was moved to, for instants from the one given: 2 hours from 2023-03-09, and 25 hours before it.
iex> Feel.Type.Moment.overlap(63_845_596_800)
7200
iex> Feel.Type.Moment.overlap(0)
90000
@spec point(Feel.Value.Time.t() | Feel.Value.DateTime.t()) :: {:ok, Feel.Type.NumberSet.t()} | :error
The set of the one value of a time or a date and time: its lines and its fraction. It is :error for a value that is
not one of FEEL.
iex> {:ok, time} = Feel.Value.Time.parse("10:00:00.5")
iex> {:ok, set} = Feel.Type.Moment.point(time)
iex> Feel.Type.Union.format([{:time, set}])
"time = 10:00:00.5"
@spec shift(Feel.Type.NumberSet.t(), integer()) :: Feel.Type.NumberSet.t()
A set moved by a number of seconds: every end of every interval.
@spec shift_exact(Feel.Type.NumberSet.t(), integer()) :: Feel.Type.NumberSet.t()
A set moved by whole seconds with no rounding: a fraction of a second is as long as a second can be, and the
arithmetic of Decimal rounds to 28 digits.
iex> alias Feel.Type.{Moment, NumberSet}
iex> set = NumberSet.point(Decimal.new("0.123456789012345678901234567890"))
iex> NumberSet.format(Moment.shift_exact(set, 5))
"5.12345678901234567890123456789"
@spec split(Feel.Type.NumberSet.t()) :: lines()
The three lines of a set, each as the seconds it holds, with the numbers of the second and third taken back to the
seconds they are: {clock, instants, zoned_clock}.
iex> alias Feel.Type.{Moment, NumberSet}
iex> set = NumberSet.new([{{Decimal.new(5), :closed}, {Decimal.new(5), :closed}}, {{Decimal.new(100_000_000_000_003_600), :closed}, {Decimal.new(100_000_000_000_003_600), :closed}}])
iex> {clock, instants, zoned_clock} = Moment.split(set)
iex> {NumberSet.format(clock), NumberSet.format(instants), zoned_clock}
{"5", "3600", []}
@spec union(Feel.Type.NumberSet.t(), Feel.Type.NumberSet.t()) :: Feel.Type.NumberSet.t()
The union of two sets of one kind, line by line: a line of more than 16 intervals is made its own hull, and not the
hull of the lines together, which a Feel.Type.NumberSet of that many would be.
@spec universe(kind()) :: Feel.Type.NumberSet.t()
The images of every value of a kind, on the three lines.
iex> Feel.Type.NumberSet.format(Feel.Type.Moment.floating(:time))
"[0..86399]"
The three lines of the universe of a kind, as the seconds they hold.
@spec with_fractions(Feel.Type.NumberSet.t(), Feel.Type.NumberSet.t()) :: Feel.Type.NumberSet.t()
The set with the fractions of a second given (a set of numbers in [0..1)), in place of the ones it had. An empty set
of fractions leaves the set with every fraction.