Refactors date handling with DateService
Replaces DateCalculator with DateService for improved date and time operations, including timezone handling. This change enhances the calendar's accuracy and flexibility in managing dates, especially concerning timezone configurations. It also corrects a typo in the `allDay` dataset attribute.
This commit is contained in:
parent
4859f42450
commit
6bbf2d8adb
17 changed files with 159 additions and 749 deletions
|
|
@ -1,310 +0,0 @@
|
|||
import { describe, it, expect, beforeEach } from 'vitest';
|
||||
import { DateCalculator } from '../../src/utils/DateCalculator';
|
||||
import { CalendarConfig } from '../../src/core/CalendarConfig';
|
||||
|
||||
describe('DateCalculator', () => {
|
||||
let testConfig: CalendarConfig;
|
||||
|
||||
beforeEach(() => {
|
||||
testConfig = new CalendarConfig();
|
||||
DateCalculator.initialize(testConfig);
|
||||
});
|
||||
|
||||
describe('Week Operations', () => {
|
||||
it('should get ISO week start (Monday)', () => {
|
||||
// Wednesday, January 17, 2024
|
||||
const date = new Date(2024, 0, 17);
|
||||
const weekStart = DateCalculator.getISOWeekStart(date);
|
||||
|
||||
// Should be Monday, January 15
|
||||
expect(weekStart.getDate()).toBe(15);
|
||||
expect(weekStart.getDay()).toBe(1); // Monday
|
||||
expect(weekStart.getHours()).toBe(0);
|
||||
expect(weekStart.getMinutes()).toBe(0);
|
||||
});
|
||||
|
||||
it('should get ISO week start for Sunday', () => {
|
||||
// Sunday, January 21, 2024
|
||||
const date = new Date(2024, 0, 21);
|
||||
const weekStart = DateCalculator.getISOWeekStart(date);
|
||||
|
||||
// Should be Monday, January 15
|
||||
expect(weekStart.getDate()).toBe(15);
|
||||
expect(weekStart.getDay()).toBe(1);
|
||||
});
|
||||
|
||||
it('should get week end (Sunday)', () => {
|
||||
// Wednesday, January 17, 2024
|
||||
const date = new Date(2024, 0, 17);
|
||||
const weekEnd = DateCalculator.getWeekEnd(date);
|
||||
|
||||
// Should be Sunday, January 21
|
||||
expect(weekEnd.getDate()).toBe(21);
|
||||
expect(weekEnd.getDay()).toBe(0); // Sunday
|
||||
expect(weekEnd.getHours()).toBe(23);
|
||||
expect(weekEnd.getMinutes()).toBe(59);
|
||||
});
|
||||
|
||||
it('should get work week dates (Mon-Fri)', () => {
|
||||
const date = new Date(2024, 0, 17); // Wednesday
|
||||
const workDays = DateCalculator.getWorkWeekDates(date);
|
||||
|
||||
expect(workDays).toHaveLength(5);
|
||||
expect(workDays[0].getDay()).toBe(1); // Monday
|
||||
expect(workDays[4].getDay()).toBe(5); // Friday
|
||||
});
|
||||
|
||||
it('should get full week dates (7 days)', () => {
|
||||
const weekStart = new Date(2024, 0, 15); // Monday
|
||||
const fullWeek = DateCalculator.getFullWeekDates(weekStart);
|
||||
|
||||
expect(fullWeek).toHaveLength(7);
|
||||
expect(fullWeek[0].getDay()).toBe(1); // Monday
|
||||
expect(fullWeek[6].getDay()).toBe(0); // Sunday
|
||||
});
|
||||
|
||||
it('should calculate ISO week number', () => {
|
||||
const date1 = new Date(2024, 0, 1); // January 1, 2024
|
||||
const weekNum1 = DateCalculator.getWeekNumber(date1);
|
||||
expect(weekNum1).toBe(1);
|
||||
|
||||
const date2 = new Date(2024, 0, 15); // January 15, 2024
|
||||
const weekNum2 = DateCalculator.getWeekNumber(date2);
|
||||
expect(weekNum2).toBe(3);
|
||||
});
|
||||
|
||||
it('should handle year boundary for week numbers', () => {
|
||||
const date = new Date(2023, 11, 31); // December 31, 2023
|
||||
const weekNum = DateCalculator.getWeekNumber(date);
|
||||
// Week 52 or 53 depending on year
|
||||
expect(weekNum).toBeGreaterThanOrEqual(52);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Date Manipulation', () => {
|
||||
it('should add days', () => {
|
||||
const date = new Date(2024, 0, 15);
|
||||
const newDate = DateCalculator.addDays(date, 5);
|
||||
|
||||
expect(newDate.getDate()).toBe(20);
|
||||
expect(newDate.getMonth()).toBe(0);
|
||||
});
|
||||
|
||||
it('should subtract days', () => {
|
||||
const date = new Date(2024, 0, 15);
|
||||
const newDate = DateCalculator.addDays(date, -5);
|
||||
|
||||
expect(newDate.getDate()).toBe(10);
|
||||
});
|
||||
|
||||
it('should add weeks', () => {
|
||||
const date = new Date(2024, 0, 15);
|
||||
const newDate = DateCalculator.addWeeks(date, 2);
|
||||
|
||||
expect(newDate.getDate()).toBe(29);
|
||||
});
|
||||
|
||||
it('should subtract weeks', () => {
|
||||
const date = new Date(2024, 0, 15);
|
||||
const newDate = DateCalculator.addWeeks(date, -1);
|
||||
|
||||
expect(newDate.getDate()).toBe(8);
|
||||
});
|
||||
|
||||
it('should handle month boundaries when adding days', () => {
|
||||
const date = new Date(2024, 0, 30); // January 30
|
||||
const newDate = DateCalculator.addDays(date, 5);
|
||||
|
||||
expect(newDate.getDate()).toBe(4); // February 4
|
||||
expect(newDate.getMonth()).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Time Formatting', () => {
|
||||
it('should format time (24-hour)', () => {
|
||||
const date = new Date(2024, 0, 15, 14, 30, 45);
|
||||
const formatted = DateCalculator.formatTime(date);
|
||||
|
||||
expect(formatted).toBe('14:30');
|
||||
});
|
||||
|
||||
it('should format time (12-hour)', () => {
|
||||
const date1 = new Date(2024, 0, 15, 14, 30, 0);
|
||||
const formatted1 = DateCalculator.formatTime12(date1);
|
||||
expect(formatted1).toBe('2:30 PM');
|
||||
|
||||
const date2 = new Date(2024, 0, 15, 9, 15, 0);
|
||||
const formatted2 = DateCalculator.formatTime12(date2);
|
||||
expect(formatted2).toBe('9:15 AM');
|
||||
|
||||
const date3 = new Date(2024, 0, 15, 0, 0, 0);
|
||||
const formatted3 = DateCalculator.formatTime12(date3);
|
||||
expect(formatted3).toBe('12:00 AM');
|
||||
});
|
||||
|
||||
it('should format ISO date', () => {
|
||||
const date = new Date(2024, 0, 15, 14, 30, 0);
|
||||
const formatted = DateCalculator.formatISODate(date);
|
||||
|
||||
expect(formatted).toBe('2024-01-15');
|
||||
});
|
||||
|
||||
it('should format date range', () => {
|
||||
const start = new Date(2024, 0, 15);
|
||||
const end = new Date(2024, 0, 21);
|
||||
const formatted = DateCalculator.formatDateRange(start, end);
|
||||
|
||||
expect(formatted).toContain('Jan');
|
||||
expect(formatted).toContain('15');
|
||||
expect(formatted).toContain('21');
|
||||
});
|
||||
|
||||
it('should get day name (short)', () => {
|
||||
const monday = new Date(2024, 0, 15); // Monday
|
||||
const dayName = DateCalculator.getDayName(monday, 'short');
|
||||
|
||||
expect(dayName).toBe('Mon');
|
||||
});
|
||||
|
||||
it('should get day name (long)', () => {
|
||||
const monday = new Date(2024, 0, 15); // Monday
|
||||
const dayName = DateCalculator.getDayName(monday, 'long');
|
||||
|
||||
expect(dayName).toBe('Monday');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Time Calculations', () => {
|
||||
it('should convert time string to minutes', () => {
|
||||
expect(DateCalculator.timeToMinutes('09:00')).toBe(540);
|
||||
expect(DateCalculator.timeToMinutes('14:30')).toBe(870);
|
||||
expect(DateCalculator.timeToMinutes('00:00')).toBe(0);
|
||||
expect(DateCalculator.timeToMinutes('23:59')).toBe(1439);
|
||||
});
|
||||
|
||||
it('should convert minutes to time string', () => {
|
||||
expect(DateCalculator.minutesToTime(540)).toBe('09:00');
|
||||
expect(DateCalculator.minutesToTime(870)).toBe('14:30');
|
||||
expect(DateCalculator.minutesToTime(0)).toBe('00:00');
|
||||
expect(DateCalculator.minutesToTime(1439)).toBe('23:59');
|
||||
});
|
||||
|
||||
it('should get minutes since midnight from Date', () => {
|
||||
const date = new Date(2024, 0, 15, 14, 30, 0);
|
||||
const minutes = DateCalculator.getMinutesSinceMidnight(date);
|
||||
|
||||
expect(minutes).toBe(870); // 14*60 + 30
|
||||
});
|
||||
|
||||
it('should get minutes since midnight from ISO string', () => {
|
||||
const isoString = '2024-01-15T14:30:00.000Z';
|
||||
const minutes = DateCalculator.getMinutesSinceMidnight(isoString);
|
||||
|
||||
// Note: This will be in local time after parsing
|
||||
expect(minutes).toBeGreaterThanOrEqual(0);
|
||||
expect(minutes).toBeLessThan(1440);
|
||||
});
|
||||
|
||||
it('should calculate duration in minutes', () => {
|
||||
const start = new Date(2024, 0, 15, 9, 0, 0);
|
||||
const end = new Date(2024, 0, 15, 10, 30, 0);
|
||||
const duration = DateCalculator.getDurationMinutes(start, end);
|
||||
|
||||
expect(duration).toBe(90);
|
||||
});
|
||||
|
||||
it('should calculate duration from ISO strings', () => {
|
||||
const start = '2024-01-15T09:00:00.000Z';
|
||||
const end = '2024-01-15T10:30:00.000Z';
|
||||
const duration = DateCalculator.getDurationMinutes(start, end);
|
||||
|
||||
expect(duration).toBe(90);
|
||||
});
|
||||
|
||||
it('should handle cross-midnight duration', () => {
|
||||
const start = new Date(2024, 0, 15, 23, 0, 0);
|
||||
const end = new Date(2024, 0, 16, 1, 0, 0);
|
||||
const duration = DateCalculator.getDurationMinutes(start, end);
|
||||
|
||||
expect(duration).toBe(120); // 2 hours
|
||||
});
|
||||
});
|
||||
|
||||
describe('Date Comparisons', () => {
|
||||
it('should check if date is today', () => {
|
||||
const today = new Date();
|
||||
const yesterday = DateCalculator.addDays(new Date(), -1);
|
||||
|
||||
expect(DateCalculator.isToday(today)).toBe(true);
|
||||
expect(DateCalculator.isToday(yesterday)).toBe(false);
|
||||
});
|
||||
|
||||
it('should check if same day', () => {
|
||||
const date1 = new Date(2024, 0, 15, 10, 0, 0);
|
||||
const date2 = new Date(2024, 0, 15, 14, 30, 0);
|
||||
const date3 = new Date(2024, 0, 16, 10, 0, 0);
|
||||
|
||||
expect(DateCalculator.isSameDay(date1, date2)).toBe(true);
|
||||
expect(DateCalculator.isSameDay(date1, date3)).toBe(false);
|
||||
});
|
||||
|
||||
it('should check if multi-day event (Date objects)', () => {
|
||||
const start = new Date(2024, 0, 15, 10, 0, 0);
|
||||
const end1 = new Date(2024, 0, 15, 14, 0, 0);
|
||||
const end2 = new Date(2024, 0, 16, 10, 0, 0);
|
||||
|
||||
expect(DateCalculator.isMultiDay(start, end1)).toBe(false);
|
||||
expect(DateCalculator.isMultiDay(start, end2)).toBe(true);
|
||||
});
|
||||
|
||||
it('should check if multi-day event (ISO strings)', () => {
|
||||
const start = '2024-01-15T10:00:00.000Z';
|
||||
const end1 = '2024-01-15T14:00:00.000Z';
|
||||
const end2 = '2024-01-16T10:00:00.000Z';
|
||||
|
||||
expect(DateCalculator.isMultiDay(start, end1)).toBe(false);
|
||||
expect(DateCalculator.isMultiDay(start, end2)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Edge Cases', () => {
|
||||
it('should handle midnight', () => {
|
||||
const date = new Date(2024, 0, 15, 0, 0, 0);
|
||||
const minutes = DateCalculator.getMinutesSinceMidnight(date);
|
||||
|
||||
expect(minutes).toBe(0);
|
||||
});
|
||||
|
||||
it('should handle end of day', () => {
|
||||
const date = new Date(2024, 0, 15, 23, 59, 0);
|
||||
const minutes = DateCalculator.getMinutesSinceMidnight(date);
|
||||
|
||||
expect(minutes).toBe(1439);
|
||||
});
|
||||
|
||||
it('should handle leap year', () => {
|
||||
const date = new Date(2024, 1, 29); // February 29, 2024 (leap year)
|
||||
const nextDay = DateCalculator.addDays(date, 1);
|
||||
|
||||
expect(nextDay.getDate()).toBe(1); // March 1
|
||||
expect(nextDay.getMonth()).toBe(2);
|
||||
});
|
||||
|
||||
it('should handle DST transitions', () => {
|
||||
// This test depends on timezone, but we test the basic functionality
|
||||
const beforeDST = new Date(2024, 2, 30); // March 30, 2024
|
||||
const afterDST = DateCalculator.addDays(beforeDST, 1);
|
||||
|
||||
expect(afterDST.getDate()).toBe(31);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Error Handling', () => {
|
||||
it('should handle invalid dates gracefully', () => {
|
||||
const invalidDate = new Date('invalid');
|
||||
|
||||
const result = DateCalculator.formatISODate(invalidDate);
|
||||
expect(result).toBe('');
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue