import { describe, it, expect, beforeEach } from 'vitest'; import { DateService } from '../../src/utils/DateService'; describe('DateService', () => { let dateService: DateService; beforeEach(() => { dateService = new DateService('Europe/Copenhagen'); }); describe('Core Conversions', () => { it('should convert local date to UTC', () => { // 2024-01-15 10:00:00 Copenhagen (UTC+1 in winter) const localDate = new Date(2024, 0, 15, 10, 0, 0); const utcString = dateService.toUTC(localDate); // Should be 09:00:00 UTC expect(utcString).toContain('2024-01-15T09:00:00'); expect(utcString).toContain('Z'); }); it('should convert UTC to local date', () => { const utcString = '2024-01-15T09:00:00.000Z'; const localDate = dateService.fromUTC(utcString); // Should be 10:00 in Copenhagen (UTC+1) expect(localDate.getHours()).toBe(10); expect(localDate.getMinutes()).toBe(0); }); it('should handle summer time (DST)', () => { // 2024-07-15 10:00:00 Copenhagen (UTC+2 in summer) const localDate = new Date(2024, 6, 15, 10, 0, 0); const utcString = dateService.toUTC(localDate); // Should be 08:00:00 UTC expect(utcString).toContain('2024-07-15T08:00:00'); }); }); describe('Time Formatting', () => { it('should format time without seconds', () => { const date = new Date(2024, 0, 15, 14, 30, 45); const formatted = dateService.formatTime(date); expect(formatted).toBe('14:30'); }); it('should format time with seconds', () => { const date = new Date(2024, 0, 15, 14, 30, 45); const formatted = dateService.formatTime(date, true); expect(formatted).toBe('14:30:45'); }); it('should format time range', () => { const start = new Date(2024, 0, 15, 9, 0, 0); const end = new Date(2024, 0, 15, 10, 30, 0); const formatted = dateService.formatTimeRange(start, end); expect(formatted).toBe('09:00 - 10:30'); }); it('should format technical datetime', () => { const date = new Date(2024, 0, 15, 14, 30, 45); const formatted = dateService.formatTechnicalDateTime(date); expect(formatted).toBe('2024-01-15 14:30:45'); }); it('should format date as ISO', () => { const date = new Date(2024, 0, 15, 14, 30, 0); const formatted = dateService.formatDate(date); expect(formatted).toBe('2024-01-15'); }); }); describe('Time Calculations', () => { it('should convert time string to minutes', () => { expect(dateService.timeToMinutes('09:00')).toBe(540); expect(dateService.timeToMinutes('14:30')).toBe(870); expect(dateService.timeToMinutes('00:00')).toBe(0); expect(dateService.timeToMinutes('23:59')).toBe(1439); }); it('should convert minutes to time string', () => { expect(dateService.minutesToTime(540)).toBe('09:00'); expect(dateService.minutesToTime(870)).toBe('14:30'); expect(dateService.minutesToTime(0)).toBe('00:00'); expect(dateService.minutesToTime(1439)).toBe('23:59'); }); it('should get minutes since midnight', () => { const date = new Date(2024, 0, 15, 14, 30, 0); const minutes = dateService.getMinutesSinceMidnight(date); expect(minutes).toBe(870); // 14*60 + 30 }); 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 = dateService.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 = dateService.getDurationMinutes(start, end); expect(duration).toBe(90); }); }); describe('Week Operations', () => { it('should get week bounds (Monday to Sunday)', () => { // Wednesday, January 17, 2024 const date = new Date(2024, 0, 17); const bounds = dateService.getWeekBounds(date); // Should start on Monday, January 15 expect(bounds.start.getDate()).toBe(15); expect(bounds.start.getDay()).toBe(1); // Monday // Should end on Sunday, January 21 expect(bounds.end.getDate()).toBe(21); expect(bounds.end.getDay()).toBe(0); // Sunday }); it('should add weeks', () => { const date = new Date(2024, 0, 15); const newDate = dateService.addWeeks(date, 2); expect(newDate.getDate()).toBe(29); }); it('should subtract weeks', () => { const date = new Date(2024, 0, 15); const newDate = dateService.addWeeks(date, -1); expect(newDate.getDate()).toBe(8); }); }); describe('Grid Helpers', () => { it('should create date at specific time', () => { const baseDate = new Date(2024, 0, 15); const date = dateService.createDateAtTime(baseDate, 870); // 14:30 expect(date.getHours()).toBe(14); expect(date.getMinutes()).toBe(30); expect(date.getDate()).toBe(15); }); it('should snap to 15-minute interval', () => { const date = new Date(2024, 0, 15, 14, 37, 0); // 14:37 const snapped = dateService.snapToInterval(date, 15); // 14:37 is closer to 14:30 than 14:45, so should snap to 14:30 expect(snapped.getHours()).toBe(14); expect(snapped.getMinutes()).toBe(30); }); it('should snap to 30-minute interval', () => { const date = new Date(2024, 0, 15, 14, 20, 0); // 14:20 const snapped = dateService.snapToInterval(date, 30); // Should snap to 14:30 expect(snapped.getHours()).toBe(14); expect(snapped.getMinutes()).toBe(30); }); }); describe('Utility Methods', () => { 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(dateService.isSameDay(date1, date2)).toBe(true); expect(dateService.isSameDay(date1, date3)).toBe(false); }); it('should get start of day', () => { const date = new Date(2024, 0, 15, 14, 30, 45); const start = dateService.startOfDay(date); expect(start.getHours()).toBe(0); expect(start.getMinutes()).toBe(0); expect(start.getSeconds()).toBe(0); }); it('should get end of day', () => { const date = new Date(2024, 0, 15, 14, 30, 45); const end = dateService.endOfDay(date); expect(end.getHours()).toBe(23); expect(end.getMinutes()).toBe(59); expect(end.getSeconds()).toBe(59); }); it('should add days', () => { const date = new Date(2024, 0, 15); const newDate = dateService.addDays(date, 5); expect(newDate.getDate()).toBe(20); }); it('should add minutes', () => { const date = new Date(2024, 0, 15, 10, 0, 0); const newDate = dateService.addMinutes(date, 90); expect(newDate.getHours()).toBe(11); expect(newDate.getMinutes()).toBe(30); }); it('should parse ISO string', () => { const isoString = '2024-01-15T10:30:00.000Z'; const date = dateService.parseISO(isoString); expect(date.toISOString()).toBe(isoString); }); it('should validate dates', () => { const validDate = new Date(2024, 0, 15); const invalidDate = new Date('invalid'); expect(dateService.isValid(validDate)).toBe(true); expect(dateService.isValid(invalidDate)).toBe(false); }); }); describe('Edge Cases', () => { it('should handle midnight', () => { const date = new Date(2024, 0, 15, 0, 0, 0); const minutes = dateService.getMinutesSinceMidnight(date); expect(minutes).toBe(0); }); it('should handle end of day', () => { const date = new Date(2024, 0, 15, 23, 59, 0); const minutes = dateService.getMinutesSinceMidnight(date); expect(minutes).toBe(1439); }); 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 = dateService.getDurationMinutes(start, end); expect(duration).toBe(120); // 2 hours }); }); });