Skip to Content
ReferenceAvailability primitives

Availability primitives

Two functions over half-open [start, end) intervals. Both work on resolved Interval objects ({ start: Date; end: Date }), and they are what generateAvailableTimeslots uses internally.

subtract

subtract(source: Interval[], busy: Interval[]): Interval[]

Removes the busy intervals from the source (available) intervals and returns the free time that is left. The busy list can be unsorted, overlapping, or touching boundaries. A busy window in the middle of a source splits it in two. Touching boundaries do not count as overlap. It runs in O((n + m) log m) with a sort and a sweep, not a nested scan.

import { subtract } from 'timeslottr' const free = subtract( [{ start: new Date('2024-01-01T09:00:00Z'), end: new Date('2024-01-01T17:00:00Z') }], [{ start: new Date('2024-01-01T12:00:00Z'), end: new Date('2024-01-01T13:00:00Z') }], ) // result: [09:00 to 12:00, 13:00 to 17:00]

intersect

intersect(intervalSets: Interval[][]): Interval[]

Given one set of free intervals per person, it returns the windows where all of them overlap. With no sets it returns []. With one set it returns a merged copy. If any set is empty the result is [], since a person with no availability blocks everyone. It runs in O(total intervals · log) with a sweep, not pairwise nested loops.

import { intersect } from 'timeslottr' const team = intersect([ [{ start: new Date('2024-01-01T09:00:00Z'), end: new Date('2024-01-01T15:00:00Z') }], [{ start: new Date('2024-01-01T11:00:00Z'), end: new Date('2024-01-01T17:00:00Z') }], ]) // result: [11:00 to 15:00]

Both return new Interval objects with fresh Date instances, so your inputs are not mutated. See the Interval type.

Last updated on