Ask how it repeats, not how often
Three answers — never, forever, or after a delay — because "how often" is rarely the question a reader has. They know it comes back the moment it ends, or that it comes back after a wait. The cadence follows from that and from dates they have already typed, so the form reports what it measured instead of asking for a number, and says it out loud rather than filling a field silently. A delay is expressed by where it lands: the next opening is the wait added to the close, so a delay cannot produce a rule that comes round before it ends. Only a hand-stated cadence can, and stating one by hand stays available — measuring is the convenience, not a cage. Both readings are shown for a delay, since a week's wait after a week's window is a fortnightly rule and seeing that spelled out is how a wrong number gets caught. contiguousOpening is the load-bearing detail. An end given as a date is stored as 23:59:59, so a successor opening "the moment it closes" opens at the following midnight, a second later. Comparing against the stored end instead read every day-precision rule as having a gap it does not have — and the form has to measure the instants it will save, not the ones the record happens to hold, or it opens describing a rule it would not write. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
2c301d466d
commit
1f1d608e95
@@ -161,18 +161,27 @@ export type RepeatMode = "never" | "forever" | "delay";
|
||||
* state describes it, rather than in whichever state happens to be the
|
||||
* default.
|
||||
*
|
||||
* **`contiguousMs` is the instant a successor would open if it opened the
|
||||
* moment this one closed — which is not always the stored end.** A boundary
|
||||
* the reader gave a time to is an instant, and a successor opens on it. One
|
||||
* they gave only a date to is stored as the last second of that day, so its
|
||||
* successor opens a second later, at the following midnight. Passing the
|
||||
* stored end for both would read every day-precision rule as having a gap it
|
||||
* does not have. The caller owns that convention because the caller is what
|
||||
* wrote the boundary.
|
||||
*
|
||||
* An unstated end is `forever`: the reader gave a cadence and no end, so each
|
||||
* occurrence runs until the next opens. There is no gap to describe, and a
|
||||
* delay would have nothing to be measured from.
|
||||
*/
|
||||
export function repeatModeOf(
|
||||
startsMs: number,
|
||||
endsMs: number | null,
|
||||
contiguousMs: number | null,
|
||||
repeat: Repeat | null,
|
||||
): RepeatMode {
|
||||
if (repeat === null) return "never";
|
||||
if (endsMs === null) return "forever";
|
||||
return addUnits(startsMs, repeat.unit, repeat.interval) === endsMs
|
||||
if (contiguousMs === null) return "forever";
|
||||
return addUnits(startsMs, repeat.unit, repeat.interval) === contiguousMs
|
||||
? "forever"
|
||||
: "delay";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user