Integrate LiveKit SFU and harden booking workflow
This commit is contained in:
@@ -1,5 +1,59 @@
|
||||
const BERLIN_TZ = "Europe/Berlin";
|
||||
|
||||
export type CalendarDate = { year: number; month: number; day: number };
|
||||
|
||||
export function berlinDateKey(date: Date): string {
|
||||
const { year, month, day } = berlinParts(date);
|
||||
return `${year}-${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
|
||||
}
|
||||
|
||||
export function formatBerlinDate(date: Date, options: Intl.DateTimeFormatOptions = {}): string {
|
||||
return new Intl.DateTimeFormat("de-DE", { ...options, timeZone: BERLIN_TZ }).format(date);
|
||||
}
|
||||
|
||||
export function formatBerlinTime(date: Date, options: Intl.DateTimeFormatOptions = {}): string {
|
||||
return new Intl.DateTimeFormat("de-DE", { ...options, timeZone: BERLIN_TZ }).format(date);
|
||||
}
|
||||
|
||||
export function berlinParts(date: Date): CalendarDate & { hour: number; minute: number } {
|
||||
const parts = new Intl.DateTimeFormat("en-US", {
|
||||
timeZone: BERLIN_TZ,
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
hourCycle: "h23",
|
||||
}).formatToParts(date);
|
||||
const get = (type: string) => Number(parts.find((part) => part.type === type)?.value ?? "0");
|
||||
return { year: get("year"), month: get("month"), day: get("day"), hour: get("hour"), minute: get("minute") };
|
||||
}
|
||||
|
||||
export function berlinOffsetMinutes(date: Date): number {
|
||||
const tzName = new Intl.DateTimeFormat("en-US", { timeZone: BERLIN_TZ, timeZoneName: "shortOffset" })
|
||||
.formatToParts(date)
|
||||
.find((part) => part.type === "timeZoneName")?.value ?? "GMT+1";
|
||||
const match = tzName.match(/GMT([+-]\d+)(?::(\d+))?/);
|
||||
const hours = match ? Number(match[1]) : 1;
|
||||
const minutes = match?.[2] ? Number(match[2]) : 0;
|
||||
return hours * 60 + (hours < 0 ? -minutes : minutes);
|
||||
}
|
||||
|
||||
/** Converts a Berlin wall-clock date/time into the UTC instant it represents. */
|
||||
export function berlinWallTimeToUTC(date: CalendarDate, hour: number, minute: number): Date {
|
||||
const guess = Date.UTC(date.year, date.month - 1, date.day, hour, minute);
|
||||
return new Date(guess - berlinOffsetMinutes(new Date(guess)) * 60_000);
|
||||
}
|
||||
|
||||
export function berlinDayBounds(date: Date): { key: string; start: Date; end: Date } {
|
||||
const current = berlinParts(date);
|
||||
const nextCalendarDay = new Date(Date.UTC(current.year, current.month - 1, current.day + 1));
|
||||
const next = berlinParts(nextCalendarDay);
|
||||
const start = berlinWallTimeToUTC(current, 0, 0);
|
||||
const nextStart = berlinWallTimeToUTC(next, 0, 0);
|
||||
return { key: berlinDateKey(date), start, end: new Date(nextStart.getTime() - 1) };
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a JS Date (a UTC instant) into its Europe/Berlin wall-clock
|
||||
* representation for iCalendar's local `TZID` date-time form
|
||||
|
||||
Reference in New Issue
Block a user