refactor(calendar): use built-in DateFnsAdapter from @taskgenius/calendar

Remove redundant custom date adapter implementations in favor of the DateFnsAdapter exported directly from @taskgenius/calendar library.

- Delete local DateFnsAdapter utility class

- Remove inline NormalizedDateFnsAdapter from calendar component

- Import DateFnsAdapter from @taskgenius/calendar package
This commit is contained in:
Quorafind 2025-11-30 17:18:09 +08:00
parent 82a20200a3
commit 5fb5ff6268
2 changed files with 3 additions and 476 deletions

View file

@ -25,6 +25,7 @@ import {
import {
Calendar,
type DateAdapter,
DateFnsAdapter,
hideWeekends,
workingHours,
onlyDays,
@ -82,171 +83,6 @@ export interface CalendarEvent extends Task {
badge?: boolean;
}
class NormalizedDateFnsAdapter implements DateAdapter<Date> {
constructor(private readonly fns: typeof dateFns) {}
private normalizeFormat(formatStr?: string) {
if (!formatStr) return formatStr;
// Align legacy moment-style tokens with date-fns v4 requirements
return formatStr
.replace(/Y{2,4}/g, (token) => token.toLowerCase())
.replace(/D{1,2}/g, (token) => token.toLowerCase());
}
create(date?: string | Date) {
if (!date) return new Date();
if (date instanceof Date) return new Date(date);
return this.fns.parseISO(date);
}
parse(dateStr: string, formatStr?: string) {
const normalizedFormat = this.normalizeFormat(formatStr);
if (!normalizedFormat) {
return this.fns.parseISO(dateStr);
}
return this.fns.parse(dateStr, normalizedFormat, new Date());
}
format(date: Date, formatStr: string) {
return this.fns.format(
date,
this.normalizeFormat(formatStr) ?? formatStr,
);
}
year(date: Date) {
return this.fns.getYear(date);
}
month(date: Date) {
return this.fns.getMonth(date);
}
date(date: Date) {
return this.fns.getDate(date);
}
day(date: Date) {
return this.fns.getDay(date);
}
hour(date: Date) {
return this.fns.getHours(date);
}
minute(date: Date) {
return this.fns.getMinutes(date);
}
setHour(date: Date, hour: number) {
return this.fns.setHours(date, hour);
}
setMinute(date: Date, minute: number) {
return this.fns.setMinutes(date, minute);
}
add(date: Date, amount: number, unit: string) {
switch (unit) {
case "year":
return this.fns.addYears(date, amount);
case "month":
return this.fns.addMonths(date, amount);
case "week":
return this.fns.addWeeks(date, amount);
case "day":
return this.fns.addDays(date, amount);
case "hour":
return this.fns.addHours(date, amount);
case "minute":
return this.fns.addMinutes(date, amount);
default:
return date;
}
}
diff(date1: Date, date2: Date, unit: string) {
switch (unit) {
case "year":
return this.fns.differenceInYears(date1, date2);
case "month":
return this.fns.differenceInMonths(date1, date2);
case "week":
return this.fns.differenceInWeeks(date1, date2);
case "day":
return this.fns.differenceInDays(date1, date2);
case "hour":
return this.fns.differenceInHours(date1, date2);
case "minute":
return this.fns.differenceInMinutes(date1, date2);
default:
return 0;
}
}
startOf(date: Date, unit: string) {
switch (unit) {
case "year":
return this.fns.startOfYear(date);
case "month":
return this.fns.startOfMonth(date);
case "week":
return this.fns.startOfWeek(date);
case "day":
return this.fns.startOfDay(date);
case "hour":
return this.fns.startOfHour(date);
case "minute":
return this.fns.startOfMinute(date);
default:
return date;
}
}
endOf(date: Date, unit: string) {
switch (unit) {
case "year":
return this.fns.endOfYear(date);
case "month":
return this.fns.endOfMonth(date);
case "week":
return this.fns.endOfWeek(date);
case "day":
return this.fns.endOfDay(date);
case "hour":
return this.fns.endOfHour(date);
case "minute":
return this.fns.endOfMinute(date);
default:
return date;
}
}
isBefore(date1: Date, date2: Date, unit?: string) {
if (!unit) return this.fns.isBefore(date1, date2);
return this.fns.isBefore(
this.startOf(date1, unit),
this.startOf(date2, unit),
);
}
isAfter(date1: Date, date2: Date, unit?: string) {
if (!unit) return this.fns.isAfter(date1, date2);
return this.fns.isAfter(
this.startOf(date1, unit),
this.startOf(date2, unit),
);
}
isSame(date1: Date, date2: Date, unit?: string) {
if (!unit) return this.fns.isEqual(date1, date2);
return this.fns.isEqual(
this.startOf(date1, unit),
this.startOf(date2, unit),
);
}
}
/**
* Main CalendarComponent class
*/
@ -886,7 +722,7 @@ export class CalendarComponent extends Component {
},
// Use custom view registry for agenda/year views
viewRegistry: isAgendaOrYear ? this.viewRegistry : undefined,
dateAdapter: new NormalizedDateFnsAdapter(dateFns),
dateAdapter: new DateFnsAdapter(dateFns),
events: this.convertTasksToTGEvents(),
showEventCounts: cc.showEventCounts ?? true,
dateFormats: {
@ -974,7 +810,7 @@ export class CalendarComponent extends Component {
)
: undefined,
},
dateAdapter: new NormalizedDateFnsAdapter(dateFns),
dateAdapter: new DateFnsAdapter(dateFns),
events: this.convertTasksToTGEvents(),
showEventCounts: true,
dateFormats: {

View file

@ -1,309 +0,0 @@
/**
* DateFnsAdapter - Adapter for @taskgenius/calendar using date-fns
*
* This adapter bridges date-fns with @taskgenius/calendar's DateAdapter interface,
* allowing the calendar to use date-fns for all date operations.
*/
import {
parse,
format,
startOfDay,
startOfWeek,
startOfMonth,
startOfYear,
endOfDay,
endOfWeek,
endOfMonth,
endOfYear,
addDays,
addWeeks,
addMonths,
addYears,
subDays,
subWeeks,
subMonths,
subYears,
differenceInDays,
differenceInWeeks,
differenceInMonths,
differenceInYears,
isSameDay,
isSameWeek,
isSameMonth,
isSameYear,
isBefore,
isAfter,
getDay,
getDaysInMonth,
isValid,
parseISO,
} from "date-fns";
/**
* Time unit types supported by the adapter
*/
type TimeUnit = "day" | "week" | "month" | "year" | "hour" | "minute";
/**
* DateAdapter interface that must be implemented
* This is the contract expected by @taskgenius/calendar
*/
interface DateAdapter<T> {
create(date?: string | Date | T): T;
parse(dateStr: string, format?: string): T;
format(date: T, format: string): string;
startOf(date: T, unit: TimeUnit): T;
endOf(date: T, unit: TimeUnit): T;
add(date: T, amount: number, unit: TimeUnit): T;
subtract(date: T, amount: number, unit: TimeUnit): T;
diff(date1: T, date2: T, unit: TimeUnit): number;
isSame(date1: T, date2: T, unit?: TimeUnit): boolean;
isBefore(date: T, compare: T): boolean;
isAfter(date: T, compare: T): boolean;
getDay(date: T): number;
getDaysInMonth(date: T): number;
}
/**
* DateFnsAdapter implementation using date-fns library
*/
export class DateFnsAdapter implements DateAdapter<Date> {
/**
* Create a Date object from various input types
*/
create(date?: string | Date): Date {
if (!date) {
return new Date();
}
if (date instanceof Date) {
return new Date(date);
}
if (typeof date === "string") {
// Try to parse ISO format first
const parsed = parseISO(date);
if (isValid(parsed)) {
return parsed;
}
// Fallback to native Date constructor
return new Date(date);
}
return new Date();
}
/**
* Parse a date string with optional format
*/
parse(dateStr: string, formatStr?: string): Date {
if (!formatStr) {
// Default to ISO format
const parsed = parseISO(dateStr);
if (isValid(parsed)) {
return parsed;
}
return new Date(dateStr);
}
// Use date-fns parse with format
const parsed = parse(dateStr, formatStr, new Date());
if (!isValid(parsed)) {
throw new Error(`Invalid date string: ${dateStr}`);
}
return parsed;
}
/**
* Format a date to string
*/
format(date: Date, formatStr: string): string {
return format(date, formatStr);
}
/**
* Get the start of a time unit
*/
startOf(date: Date, unit: TimeUnit): Date {
switch (unit) {
case "day":
return startOfDay(date);
case "week":
return startOfWeek(date);
case "month":
return startOfMonth(date);
case "year":
return startOfYear(date);
case "hour":
// date-fns doesn't have startOfHour, so we set minutes and seconds to 0
const hourStart = new Date(date);
hourStart.setMinutes(0, 0, 0);
return hourStart;
case "minute":
// Set seconds and milliseconds to 0
const minuteStart = new Date(date);
minuteStart.setSeconds(0, 0);
return minuteStart;
default:
return startOfDay(date);
}
}
/**
* Get the end of a time unit
*/
endOf(date: Date, unit: TimeUnit): Date {
switch (unit) {
case "day":
return endOfDay(date);
case "week":
return endOfWeek(date);
case "month":
return endOfMonth(date);
case "year":
return endOfYear(date);
case "hour":
// Set to last millisecond of the hour
const hourEnd = new Date(date);
hourEnd.setMinutes(59, 59, 999);
return hourEnd;
case "minute":
// Set to last millisecond of the minute
const minuteEnd = new Date(date);
minuteEnd.setSeconds(59, 999);
return minuteEnd;
default:
return endOfDay(date);
}
}
/**
* Add time to a date
*/
add(date: Date, amount: number, unit: TimeUnit): Date {
switch (unit) {
case "day":
return addDays(date, amount);
case "week":
return addWeeks(date, amount);
case "month":
return addMonths(date, amount);
case "year":
return addYears(date, amount);
case "hour":
return new Date(date.getTime() + amount * 60 * 60 * 1000);
case "minute":
return new Date(date.getTime() + amount * 60 * 1000);
default:
return addDays(date, amount);
}
}
/**
* Subtract time from a date
*/
subtract(date: Date, amount: number, unit: TimeUnit): Date {
switch (unit) {
case "day":
return subDays(date, amount);
case "week":
return subWeeks(date, amount);
case "month":
return subMonths(date, amount);
case "year":
return subYears(date, amount);
case "hour":
return new Date(date.getTime() - amount * 60 * 60 * 1000);
case "minute":
return new Date(date.getTime() - amount * 60 * 1000);
default:
return subDays(date, amount);
}
}
/**
* Calculate difference between two dates
*/
diff(date1: Date, date2: Date, unit: TimeUnit): number {
switch (unit) {
case "day":
return differenceInDays(date1, date2);
case "week":
return differenceInWeeks(date1, date2);
case "month":
return differenceInMonths(date1, date2);
case "year":
return differenceInYears(date1, date2);
case "hour":
return Math.floor((date1.getTime() - date2.getTime()) / (60 * 60 * 1000));
case "minute":
return Math.floor((date1.getTime() - date2.getTime()) / (60 * 1000));
default:
return differenceInDays(date1, date2);
}
}
/**
* Check if two dates are the same
*/
isSame(date1: Date, date2: Date, unit?: TimeUnit): boolean {
if (!unit) {
return date1.getTime() === date2.getTime();
}
switch (unit) {
case "day":
return isSameDay(date1, date2);
case "week":
return isSameWeek(date1, date2);
case "month":
return isSameMonth(date1, date2);
case "year":
return isSameYear(date1, date2);
case "hour":
return (
isSameDay(date1, date2) &&
date1.getHours() === date2.getHours()
);
case "minute":
return (
isSameDay(date1, date2) &&
date1.getHours() === date2.getHours() &&
date1.getMinutes() === date2.getMinutes()
);
default:
return isSameDay(date1, date2);
}
}
/**
* Check if date is before compare date
*/
isBefore(date: Date, compare: Date): boolean {
return isBefore(date, compare);
}
/**
* Check if date is after compare date
*/
isAfter(date: Date, compare: Date): boolean {
return isAfter(date, compare);
}
/**
* Get day of week (0 = Sunday, 6 = Saturday)
*/
getDay(date: Date): number {
return getDay(date);
}
/**
* Get number of days in the month
*/
getDaysInMonth(date: Date): number {
return getDaysInMonth(date);
}
}
/**
* Export a singleton instance for convenience
*/
export const dateFnsAdapter = new DateFnsAdapter();