bugfix: appointment hours now use the client timezone on UTC servers.
Logical API errors throw stable codes so users see translated messages instead of a generic bad request. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
55
backend/src/common/zoned-civil-time.ts
Normal file
55
backend/src/common/zoned-civil-time.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
/** Convert an absolute instant into weekday + minute-of-day in an IANA time zone. */
|
||||
|
||||
const JS_WEEKDAY: Record<string, number> = {
|
||||
Sun: 0,
|
||||
Mon: 1,
|
||||
Tue: 2,
|
||||
Wed: 3,
|
||||
Thu: 4,
|
||||
Fri: 5,
|
||||
Sat: 6,
|
||||
};
|
||||
|
||||
export function isValidIanaTimeZone(timeZone: string): boolean {
|
||||
if (!timeZone || timeZone.length > 64) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
Intl.DateTimeFormat('en-US', { timeZone }).format(new Date(0));
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function zonedWeekdayAndMinutes(
|
||||
date: Date,
|
||||
timeZone: string,
|
||||
): { jsWeekday: number; minuteOfDay: number } {
|
||||
const parts = new Intl.DateTimeFormat('en-US', {
|
||||
timeZone,
|
||||
weekday: 'short',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
hourCycle: 'h23',
|
||||
}).formatToParts(date);
|
||||
|
||||
const weekdayToken = parts.find((p) => p.type === 'weekday')?.value ?? 'Sun';
|
||||
let hour = Number(parts.find((p) => p.type === 'hour')?.value ?? '0');
|
||||
const minute = Number(parts.find((p) => p.type === 'minute')?.value ?? '0');
|
||||
if (hour === 24) {
|
||||
hour = 0;
|
||||
}
|
||||
|
||||
return {
|
||||
jsWeekday: JS_WEEKDAY[weekdayToken] ?? 0,
|
||||
minuteOfDay: hour * 60 + minute,
|
||||
};
|
||||
}
|
||||
|
||||
/** Weekday of a YYYY-MM-DD civil date (Gregorian; same worldwide). */
|
||||
export function civilDateJsWeekday(isoDate: string): number {
|
||||
const [y, m, d] = isoDate.split('-').map(Number);
|
||||
const utcNoon = new Date(Date.UTC(y, m - 1, d, 12, 0, 0, 0));
|
||||
return utcNoon.getUTCDay();
|
||||
}
|
||||
Reference in New Issue
Block a user