Feel.Analysis.DatePreimage (feel v0.1.0)

Copy Markdown View Source

The dates and the durations that give a date in a set when one is added to the other (D-122).

Feel.Analysis.DateArithmetic goes from a date and a duration to the dates they give. This goes the other way, for d + p > @"2020-06-01": given the days that the sum is in, the operator and the amounts or the dates that the other operand is, dates/4 gives the days that the date can be, and amounts/4 the seconds or the months that the duration can be.

The run adds a duration to a date in two ways (Feel.Runtime.Temporal), and both are whole days and do not decrease when the date does or the duration does:

  • A days and time duration adds the whole days of its seconds, rounded down: floor(seconds / 86400), so 36 hours are a day and minus one second is minus a day. The days a date can be are the days of the set less the days of the amounts, and the seconds a duration can be are the seconds of whole days from the days of the set less the dates (the last of them is a second short of the next day, so that end is open). Both are exact.
  • A years and months duration adds its months to the month of the date and cuts the day to the length of the month: 2021-01-31 plus P1M is 2021-02-28. The function does not decrease, so the least date that gives a day or more, and the greatest that gives a day or less, are found by a search, and the dates in between are the dates that give a day in the set. For each month of the duration that is a piece, up to 64 of them, and the hull of the pieces past that, which holds more and so is sound. The months a duration can be are the least that gives a day or more at the last date and the greatest that gives a day or less at the first (a later date needs fewer months), which is exact for dates one after the other.

A subtraction adds the negative: a date less a duration is the date plus the amounts reflected.

iex> alias Feel.Type.NumberSet
iex> day = fn date -> Decimal.new(Date.to_gregorian_days(date)) end
iex> result = NumberSet.interval(day.(~D[2021-03-01]), day.(~D[2021-03-31]))
iex> month = NumberSet.point(Decimal.new(1))
iex> dates = Feel.Analysis.DatePreimage.dates(:add, :years_and_months_duration, result, month)
iex> Feel.Type.Union.format([{:date, dates}])
"date in [2021-02-01..2021-02-28]"

Summary

Functions

The amounts that a duration of a kind can be, when its sum with (:add) or its difference from (:subtract) a date of the days is a day of the results.

The days that a date can be, when its sum with (:add) or its difference from (:subtract) a duration of the amounts of a kind is a day of the results.

Functions

amounts(operator, atom, results, dates)

@spec amounts(
  :add | :subtract,
  :years_and_months_duration | :days_and_time_duration,
  Feel.Type.NumberSet.t(),
  Feel.Type.NumberSet.t()
) :: Feel.Type.NumberSet.t()

The amounts that a duration of a kind can be, when its sum with (:add) or its difference from (:subtract) a date of the days is a day of the results.

dates(operator, kind, results, amounts)

@spec dates(
  :add | :subtract,
  :years_and_months_duration | :days_and_time_duration,
  Feel.Type.NumberSet.t(),
  Feel.Type.NumberSet.t()
) :: Feel.Type.NumberSet.t()

The days that a date can be, when its sum with (:add) or its difference from (:subtract) a duration of the amounts of a kind is a day of the results.