import { timeMonday, timeSunday, timeDay, timeMonth } from 'd3-time'; import { timeFormat } from 'd3-time-format'; import type { DayEntry } from '../types'; export const DAY_LABELS_MONDAY = ['Mon', '', 'Wed', '', 'Fri', '', '']; export const DAY_LABELS_SUNDAY = ['Sun', '', 'Tue', '', 'Thu', '', 'Sat']; export function getDayLabels(weekStart: string): string[] { return weekStart === 'sunday' ? DAY_LABELS_SUNDAY : DAY_LABELS_MONDAY; } export const MONTH_FORMAT = timeFormat('%b'); export const DATE_FORMAT = timeFormat('%Y-%m-%d'); export const DISPLAY_FORMAT = timeFormat('%a, %b %-d, %Y'); export interface DayCell { date: Date; dateStr: string; entry: DayEntry | null; week: number; day: number; isWeekend: boolean; } export function buildDateMap(days: DayEntry[]): Map { const map = new Map(); for (const d of days) { map.set(d.date, d); } return map; } export function getWeekInterval(weekStart: string) { return weekStart === 'sunday' ? timeSunday : timeMonday; } export function generateCells( begin: Date, end: Date, dateMap: Map, weekStart: string = 'monday', ): DayCell[] { const weekInterval = getWeekInterval(weekStart); const firstWeekDay = weekInterval.floor(begin); const cells: DayCell[] = []; let current = new Date(begin); while (current <= end) { const dateStr = DATE_FORMAT(current); const weeksSinceStart = weekInterval.count(firstWeekDay, current); const jsDay = current.getDay(); // 0=Sunday, 6=Saturday const dayOfWeek = weekStart === 'sunday' ? jsDay // Sunday=0 already first : (jsDay + 6) % 7; // Monday=0, Sunday=6 const isWeekend = jsDay === 0 || jsDay === 6; cells.push({ date: new Date(current), dateStr, entry: dateMap.get(dateStr) || null, week: weeksSinceStart, day: dayOfWeek, isWeekend, }); current = timeDay.offset(current, 1); } return cells; }