Introduces DateService for time zone handling
Adds DateService using date-fns-tz for robust time zone conversions and date manipulations. Refactors DateCalculator and TimeFormatter to utilize the DateService, centralizing date logic and ensuring consistent time zone handling throughout the application. Improves event dragging by updating time displays and data attributes, handling cross-midnight events correctly.
This commit is contained in:
parent
1821d805d1
commit
53cf097a47
8 changed files with 764 additions and 136 deletions
|
|
@ -1,5 +1,6 @@
|
|||
/**
|
||||
* TimeFormatter - Centralized time formatting with timezone support
|
||||
* Now uses DateService internally for all date/time operations
|
||||
*
|
||||
* Handles conversion from UTC/Zulu time to configured timezone (default: Europe/Copenhagen)
|
||||
* Supports both 12-hour and 24-hour format configuration
|
||||
|
|
@ -7,6 +8,8 @@
|
|||
* All events in the system are stored in UTC and must be converted to local timezone
|
||||
*/
|
||||
|
||||
import { DateService } from './DateService';
|
||||
|
||||
export interface TimeFormatSettings {
|
||||
timezone: string;
|
||||
use24HourFormat: boolean;
|
||||
|
|
@ -24,11 +27,15 @@ export class TimeFormatter {
|
|||
showSeconds: false // Don't show seconds by default
|
||||
};
|
||||
|
||||
private static dateService: DateService = new DateService('Europe/Copenhagen');
|
||||
|
||||
/**
|
||||
* Configure time formatting settings
|
||||
*/
|
||||
static configure(settings: Partial<TimeFormatSettings>): void {
|
||||
TimeFormatter.settings = { ...TimeFormatter.settings, ...settings };
|
||||
// Update DateService with new timezone
|
||||
TimeFormatter.dateService = new DateService(TimeFormatter.settings.timezone);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -40,21 +47,17 @@ export class TimeFormatter {
|
|||
|
||||
/**
|
||||
* Convert UTC date to configured timezone
|
||||
* @param utcDate - Date in UTC (or assumed to be UTC)
|
||||
* @param utcDate - Date in UTC (or ISO string)
|
||||
* @returns Date object adjusted to configured timezone
|
||||
*/
|
||||
static convertToLocalTime(utcDate: Date): Date {
|
||||
// Create a new date to avoid mutating the original
|
||||
const localDate = new Date(utcDate);
|
||||
|
||||
// If the date doesn't have timezone info, treat it as UTC
|
||||
// This handles cases where mock data doesn't have 'Z' suffix
|
||||
if (!utcDate.toISOString().endsWith('Z') && utcDate.getTimezoneOffset() === new Date().getTimezoneOffset()) {
|
||||
// Adjust for the fact that we're treating local time as UTC
|
||||
localDate.setMinutes(localDate.getMinutes() + localDate.getTimezoneOffset());
|
||||
static convertToLocalTime(utcDate: Date | string): Date {
|
||||
if (typeof utcDate === 'string') {
|
||||
return TimeFormatter.dateService.fromUTC(utcDate);
|
||||
}
|
||||
|
||||
return localDate;
|
||||
// If it's already a Date object, convert to UTC string first, then back to local
|
||||
const utcString = utcDate.toISOString();
|
||||
return TimeFormatter.dateService.fromUTC(utcString);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -85,17 +88,13 @@ export class TimeFormatter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Format time in 24-hour format
|
||||
* Format time in 24-hour format using DateService
|
||||
* @param date - Date to format
|
||||
* @returns Formatted time string (e.g., "09:00")
|
||||
*/
|
||||
static format24Hour(date: Date): string {
|
||||
const localDate = TimeFormatter.convertToLocalTime(date);
|
||||
|
||||
// Always use colon separator, not locale-specific formatting
|
||||
let hours = String(localDate.getHours()).padStart(2, '0');
|
||||
let minutes = String(localDate.getMinutes()).padStart(2, '0');
|
||||
return `${hours}:${minutes}`;
|
||||
return TimeFormatter.dateService.formatTime(localDate, TimeFormatter.settings.showSeconds);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -110,19 +109,12 @@ export class TimeFormatter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Format time from total minutes since midnight
|
||||
* Format time from total minutes since midnight using DateService
|
||||
* @param totalMinutes - Minutes since midnight (e.g., 540 for 9:00 AM)
|
||||
* @returns Formatted time string
|
||||
*/
|
||||
static formatTimeFromMinutes(totalMinutes: number): string {
|
||||
const hours = Math.floor(totalMinutes / 60) % 24;
|
||||
const minutes = totalMinutes % 60;
|
||||
|
||||
// Create a date object for today with the specified time
|
||||
const date = new Date();
|
||||
date.setHours(hours, minutes, 0, 0);
|
||||
|
||||
return TimeFormatter.formatTime(date);
|
||||
return TimeFormatter.dateService.formatTimeFromMinutes(totalMinutes);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -146,15 +138,15 @@ export class TimeFormatter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Format time range (start - end)
|
||||
* Format time range (start - end) using DateService
|
||||
* @param startDate - Start date
|
||||
* @param endDate - End date
|
||||
* @returns Formatted time range string (e.g., "09:00 - 10:30")
|
||||
*/
|
||||
static formatTimeRange(startDate: Date, endDate: Date): string {
|
||||
const startTime = TimeFormatter.formatTime(startDate);
|
||||
const endTime = TimeFormatter.formatTime(endDate);
|
||||
return `${startTime} - ${endTime}`;
|
||||
const localStart = TimeFormatter.convertToLocalTime(startDate);
|
||||
const localEnd = TimeFormatter.convertToLocalTime(endDate);
|
||||
return TimeFormatter.dateService.formatTimeRange(localStart, localEnd);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -187,37 +179,44 @@ export class TimeFormatter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Format date in technical format: yyyy-mm-dd
|
||||
* Format date in technical format: yyyy-mm-dd using DateService
|
||||
*/
|
||||
static formatDateTechnical(date: Date): string {
|
||||
let year = date.getFullYear();
|
||||
let month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
let day = String(date.getDate()).padStart(2, '0');
|
||||
return `${year}-${month}-${day}`;
|
||||
const localDate = TimeFormatter.convertToLocalTime(date);
|
||||
return TimeFormatter.dateService.formatDate(localDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format time in technical format: hh:mm or hh:mm:ss
|
||||
* Format time in technical format: hh:mm or hh:mm:ss using DateService
|
||||
*/
|
||||
static formatTimeTechnical(date: Date, includeSeconds: boolean = false): string {
|
||||
let hours = String(date.getHours()).padStart(2, '0');
|
||||
let minutes = String(date.getMinutes()).padStart(2, '0');
|
||||
|
||||
if (includeSeconds) {
|
||||
let seconds = String(date.getSeconds()).padStart(2, '0');
|
||||
return `${hours}:${minutes}:${seconds}`;
|
||||
}
|
||||
return `${hours}:${minutes}`;
|
||||
const localDate = TimeFormatter.convertToLocalTime(date);
|
||||
return TimeFormatter.dateService.formatTime(localDate, includeSeconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format date and time in technical format: yyyy-mm-dd hh:mm:ss
|
||||
* Format date and time in technical format: yyyy-mm-dd hh:mm:ss using DateService
|
||||
*/
|
||||
static formatDateTimeTechnical(date: Date): string {
|
||||
let localDate = TimeFormatter.convertToLocalTime(date);
|
||||
let dateStr = TimeFormatter.formatDateTechnical(localDate);
|
||||
let timeStr = TimeFormatter.formatTimeTechnical(localDate, TimeFormatter.settings.showSeconds);
|
||||
return `${dateStr} ${timeStr}`;
|
||||
const localDate = TimeFormatter.convertToLocalTime(date);
|
||||
return TimeFormatter.dateService.formatTechnicalDateTime(localDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert local date to UTC ISO string using DateService
|
||||
* @param localDate - Date in local timezone
|
||||
* @returns ISO string in UTC (with 'Z' suffix)
|
||||
*/
|
||||
static toUTC(localDate: Date): string {
|
||||
return TimeFormatter.dateService.toUTC(localDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert UTC ISO string to local date using DateService
|
||||
* @param utcString - ISO string in UTC
|
||||
* @returns Date in local timezone
|
||||
*/
|
||||
static fromUTC(utcString: string): Date {
|
||||
return TimeFormatter.dateService.fromUTC(utcString);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue