Availability
app/features/availability/core/Availability.tsNo overview comment at the top of the file.
- Imports
- no other modules
- Used by
- 2 loaders1 action7 modules4 components1 routine1 script3 other
Functions & values
Database timestamp of the Monday 00:00 starting the week date falls in, as seen in timezone.
export function weekStartsAt(date: Date, timezone: string)
Unit tests (2)
The week date falls in, endsAt being the next Monday 00:00. Not always 7×24h: a week with a DST transition is an hour shorter or longer.
export function weekRange(date: Date, timezone: string): TimeRange
Unit tests (2)
Whether date falls on the first day of its week (Monday), as the week is seen in timezone.
export function isFirstDayOfWeek(date: Date, timezone: string)
Unit tests (1)
Whether date falls on the last day of its week (Sunday), as the week is seen in timezone.
export function isLastDayOfWeek(date: Date, timezone: string)
Unit tests (2)
ISO week number of the week the timestamp falls in, as seen in timezone.
export function isoWeekNumber(timestamp: number, timezone: string)
Unit tests (2)
Whether the two week starts name the same week: closer than timezones can set them apart (hours, never days).
export function isSameWeek(weekStart: number, rangeStartsAt: number)
Database timestamp of date (YYYY-MM-DD) at time (HH:mm) in timezone.
export function localToTimestamp({ date, time, timezone, }: { date: string; time: string; timezone: string; })
Database timestamp of minutes from midnight of date in timezone. Minutes past 1440 roll into the next day; on a DST day the clock rolls through the change like a hand-entered time would.
export function dayMinutesToTimestamp({ date, minutes, timezone, }: { date: string; minutes: number; timezone: string; })
Unit tests (3)
Minutes from midnight of date in timezone, the inverse of {@link dayMinutesToTimestamp}. A timestamp on a later day counts on past 1440, read off the wall clock so a DST change inside the range does not stretch or shrink it.
export function timestampToDayMinutes({ date, timestamp, timezone, }: { date: string; timestamp: number; timezone: string; })
YYYY-MM-DD of the timestamp in timezone. A slot's day depends on who is looking, so it is always resolved from the timestamp, never from the day its author entered it on.
export function dateInTimezone(timestamp: number, timezone: string)
YYYY-MM-DD in to of a day saved as a date in from, mapped through that day's noon in case the viewer has since moved. How day notes find their viewer-local day.
export function dateAcrossTimezones({ date, from, to, }: { date: string; from: string; to: string; })
Whether the two ranges share any time at all. Ranges that merely touch do not overlap.
export function overlaps(one: TimeRange, other: TimeRange)
Unit tests (1)
The ranges sorted and merged so that no two overlap or touch. Empty ranges are dropped.
export function normalize(ranges: Array<TimeRange>): Array<TimeRange>
Unit tests (3)
What is left of ranges once every busy block is cut out: a commitment always wins over what was reported.
export function subtract( ranges: Array<TimeRange>, busy: Array<TimeRange>, ): Array<TimeRange>
Unit tests (4)
The parts of the ranges inside window, sorted and merged. Keeps one week's view from picking up the next week's windows.
export function clip( ranges: Array<TimeRange>, window: TimeRange, ): Array<TimeRange>
Unit tests (3)
The ranges cut up into the day tracks they render on, what runs past a track's end continuing on the next day's.
export function splitByDayTracks( ranges: Array<TimeRange>, timezone: string, ): Array<TimeRange>
How one person's schedule relates to an event's window. A busy block overlapping it wins over anything reported (committed elsewhere, schedule known or not). Otherwise the slots cover the window (available, ranges as reported), part of it (partial, overlap clipped to the window), miss it (unavailable) or do not exist (unknown).
export function availabilityInWindow({ reported, slots, busy, window, }: { reported: boolean; slots: Array<TimeRange>; busy: Array<BusyBlock>; window: TimeRange; }): WindowAvailability
Unit tests (10)
- a
- slot covering the whole window is available, ranges as reported
- slot covering part of the window is partial, ranges clipped to it
- reported week without overlap is unavailable
- slot only touching the window start is unavailable
- busy block overlapping the window wins over reported availability
- busy block wins even when nothing was reported
- busy block outside the window changes nothing
- cross-midnight slot covers a window reaching past midnight
- split slots leaving a gap inside the window are partial even when they span it
- no reported week is unknown
Spans where minPlayers members (FULL) or one fewer (ONE_SHORT) are free throughout. Windows shorter than minDurationMinutes are dropped, as is a ONE_SHORT window containing a FULL one.
export function playableWindows({ members, minPlayers = AVAILABILITY.DEFAULT_MIN_PLAYERS, minDurationMinutes = AVAILABILITY.MIN_WINDOW_MINUTES, }: { members: Array<MemberAvailability>; minPlayers?: number; minDurationMinutes?: number; }): Array<PlayableWindow>
Unit tests (8)
Splits the members' availability at every start/end into spans, each with the members free throughout. Spans nobody is free in come out with an empty userIds.
export function availabilitySegments(members: Array<MemberAvailability>)
Unit tests (4)
HH:mm at the given minutes from midnight; minutes past 24h wrap, so a range crossing midnight ends at e.g. 02:00.
export function minutesToTime(minutes: number)
Unit tests (1)
Editor day range of the given times. An end before the start crosses midnight; an end equal to the start is an empty range (dropped by {@link mergedDayRanges}).
export function dayRangeFromTimes(start: string, end: string): DayTimeRange
Unit tests (3)
One day track's ranges sorted and merged so that no two overlap or touch. Empty ranges are dropped.
export function mergedDayRanges( ranges: Array<DayTimeRange>, ): Array<DayTimeRange>
Unit tests (2)
Range painted by dragging an empty part of a day track from anchor to cursor (minutes from midnight): snapped to the entry step, at least one step long, inside the track, start kept before midnight (a paint anchored past it grows leftwards from the day's last step). Null when the anchor is inside a wall (a commitment); a paint may still extend across one.
export function paintedRange({ anchor, cursor, walls, trackStart, trackEnd, }: TrackWindowArgs & { anchor: number; cursor: number; /** Blocks a paint cannot start on, i.e. the day's commitments. */ walls: Array<DayTimeRange>; }): DayTimeRange | null
Unit tests (6)
range moved by delta minutes, snapped to the entry step, stopped at the track edges, start kept before midnight.
export function movedRange({ range, delta, trackStart, trackEnd, }: TrackWindowArgs & { range: DayTimeRange; delta: number; }): DayTimeRange
Unit tests (3)
range with one edge dragged to cursor: snapped, at least one step long, inside the track, start kept before midnight.
export function resizedRange({ range, edge, cursor, trackStart, trackEnd, }: TrackWindowArgs & { range: DayTimeRange; edge: "start" | "end"; cursor: number; }): DayTimeRange
Unit tests (4)
Unit tests not about one export (3)
Not shown, only used by tests: timeInTimezone, snapMinutes, timeToMinutes