kimai-plugin-heatmap/assets/src/shared/date-utils.ts

70 lines
1.9 KiB
TypeScript

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<string, DayEntry> {
const map = new Map<string, DayEntry>();
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<string, DayEntry>,
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;
}