Enhances date handling and formatting
Improves date validation and adds flexible date/time formatting capabilities. The date validation is updated to return a boolean and is incorporated directly into calling functions to throw errors, improving code readability and maintainability. DateService is extended with functions for formatting time in 12-hour format, getting day names, and formatting date ranges with customizable options.
This commit is contained in:
parent
4fea01c76b
commit
4859f42450
3 changed files with 465 additions and 25 deletions
|
|
@ -25,13 +25,10 @@ export class DateCalculator {
|
|||
/**
|
||||
* Validate that a date is valid
|
||||
* @param date - Date to validate
|
||||
* @param methodName - Name of calling method for error messages
|
||||
* @throws Error if date is invalid
|
||||
* @returns True if date is valid, false otherwise
|
||||
*/
|
||||
private static validateDate(date: Date, methodName: string): void {
|
||||
if (!date || !(date instanceof Date) || !DateCalculator.dateService.isValid(date)) {
|
||||
throw new Error(`${methodName}: Invalid date provided - ${date}`);
|
||||
}
|
||||
private static validateDate(date: Date): boolean {
|
||||
return date && date instanceof Date && DateCalculator.dateService.isValid(date);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -40,7 +37,9 @@ export class DateCalculator {
|
|||
* @returns Array of dates for the configured work days
|
||||
*/
|
||||
static getWorkWeekDates(weekStart: Date): Date[] {
|
||||
DateCalculator.validateDate(weekStart, 'getWorkWeekDates');
|
||||
if (!DateCalculator.validateDate(weekStart)) {
|
||||
throw new Error('getWorkWeekDates: Invalid date provided');
|
||||
}
|
||||
|
||||
const dates: Date[] = [];
|
||||
const workWeekSettings = DateCalculator.config.getWorkWeekSettings();
|
||||
|
|
@ -66,7 +65,9 @@ export class DateCalculator {
|
|||
* @returns The Monday of the ISO week
|
||||
*/
|
||||
static getISOWeekStart(date: Date): Date {
|
||||
DateCalculator.validateDate(date, 'getISOWeekStart');
|
||||
if (!DateCalculator.validateDate(date)) {
|
||||
throw new Error('getISOWeekStart: Invalid date provided');
|
||||
}
|
||||
|
||||
const weekBounds = DateCalculator.dateService.getWeekBounds(date);
|
||||
return DateCalculator.dateService.startOfDay(weekBounds.start);
|
||||
|
|
@ -78,7 +79,9 @@ export class DateCalculator {
|
|||
* @returns The end date of the ISO week (Sunday)
|
||||
*/
|
||||
static getWeekEnd(date: Date): Date {
|
||||
DateCalculator.validateDate(date, 'getWeekEnd');
|
||||
if (!DateCalculator.validateDate(date)) {
|
||||
throw new Error('getWeekEnd: Invalid date provided');
|
||||
}
|
||||
|
||||
const weekBounds = DateCalculator.dateService.getWeekBounds(date);
|
||||
return DateCalculator.dateService.endOfDay(weekBounds.end);
|
||||
|
|
@ -137,9 +140,12 @@ export class DateCalculator {
|
|||
/**
|
||||
* Format a date to ISO date string (YYYY-MM-DD) using DateService
|
||||
* @param date - Date to format
|
||||
* @returns ISO date string
|
||||
* @returns ISO date string or empty string if invalid
|
||||
*/
|
||||
static formatISODate(date: Date): string {
|
||||
if (!DateCalculator.validateDate(date)) {
|
||||
return '';
|
||||
}
|
||||
return DateCalculator.dateService.formatDate(date);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,24 +3,25 @@
|
|||
* Handles all date operations, timezone conversions, and formatting
|
||||
*/
|
||||
|
||||
import {
|
||||
format,
|
||||
parse,
|
||||
addMinutes,
|
||||
differenceInMinutes,
|
||||
startOfDay,
|
||||
import {
|
||||
format,
|
||||
parse,
|
||||
addMinutes,
|
||||
differenceInMinutes,
|
||||
startOfDay,
|
||||
endOfDay,
|
||||
setHours,
|
||||
setMinutes as setMins,
|
||||
getHours,
|
||||
getMinutes,
|
||||
setHours,
|
||||
setMinutes as setMins,
|
||||
getHours,
|
||||
getMinutes,
|
||||
parseISO,
|
||||
isValid,
|
||||
addDays,
|
||||
startOfWeek,
|
||||
endOfWeek,
|
||||
isValid,
|
||||
addDays,
|
||||
startOfWeek,
|
||||
endOfWeek,
|
||||
addWeeks,
|
||||
isSameDay
|
||||
isSameDay,
|
||||
getISOWeek
|
||||
} from 'date-fns';
|
||||
import {
|
||||
toZonedTime,
|
||||
|
|
@ -109,6 +110,70 @@ export class DateService {
|
|||
return this.formatDate(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format time in 12-hour format with AM/PM
|
||||
* @param date - Date to format
|
||||
* @returns Time string in 12-hour format (e.g., "2:30 PM")
|
||||
*/
|
||||
public formatTime12(date: Date): string {
|
||||
const hours = getHours(date);
|
||||
const minutes = getMinutes(date);
|
||||
const period = hours >= 12 ? 'PM' : 'AM';
|
||||
const displayHours = hours % 12 || 12;
|
||||
|
||||
return `${displayHours}:${String(minutes).padStart(2, '0')} ${period}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get day name for a date
|
||||
* @param date - Date to get day name for
|
||||
* @param format - 'short' (e.g., 'Mon') or 'long' (e.g., 'Monday')
|
||||
* @returns Day name
|
||||
*/
|
||||
public getDayName(date: Date, format: 'short' | 'long' = 'short'): string {
|
||||
const formatter = new Intl.DateTimeFormat('en-US', {
|
||||
weekday: format
|
||||
});
|
||||
return formatter.format(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a date range with customizable options
|
||||
* @param start - Start date
|
||||
* @param end - End date
|
||||
* @param options - Formatting options
|
||||
* @returns Formatted date range string
|
||||
*/
|
||||
public formatDateRange(
|
||||
start: Date,
|
||||
end: Date,
|
||||
options: {
|
||||
locale?: string;
|
||||
month?: 'numeric' | '2-digit' | 'long' | 'short' | 'narrow';
|
||||
day?: 'numeric' | '2-digit';
|
||||
year?: 'numeric' | '2-digit';
|
||||
} = {}
|
||||
): string {
|
||||
const { locale = 'en-US', month = 'short', day = 'numeric' } = options;
|
||||
|
||||
const startYear = start.getFullYear();
|
||||
const endYear = end.getFullYear();
|
||||
|
||||
const formatter = new Intl.DateTimeFormat(locale, {
|
||||
month,
|
||||
day,
|
||||
year: startYear !== endYear ? 'numeric' : undefined
|
||||
});
|
||||
|
||||
// @ts-ignore - formatRange is available in modern browsers
|
||||
if (typeof formatter.formatRange === 'function') {
|
||||
// @ts-ignore
|
||||
return formatter.formatRange(start, end);
|
||||
}
|
||||
|
||||
return `${formatter.format(start)} - ${formatter.format(end)}`;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// TIME CALCULATIONS
|
||||
// ============================================
|
||||
|
|
@ -193,6 +258,53 @@ export class DateService {
|
|||
return addWeeks(date, weeks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ISO week number (1-53)
|
||||
* @param date - Date to get week number for
|
||||
* @returns ISO week number
|
||||
*/
|
||||
public getWeekNumber(date: Date): number {
|
||||
return getISOWeek(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all dates in a full week (7 days starting from given date)
|
||||
* @param weekStart - Start date of the week
|
||||
* @returns Array of 7 dates
|
||||
*/
|
||||
public getFullWeekDates(weekStart: Date): Date[] {
|
||||
const dates: Date[] = [];
|
||||
for (let i = 0; i < 7; i++) {
|
||||
dates.push(this.addDays(weekStart, i));
|
||||
}
|
||||
return dates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get dates for work week using ISO 8601 day numbering (Monday=1, Sunday=7)
|
||||
* @param weekStart - Any date in the week
|
||||
* @param workDays - Array of ISO day numbers (1=Monday, 7=Sunday)
|
||||
* @returns Array of dates for the specified work days
|
||||
*/
|
||||
public getWorkWeekDates(weekStart: Date, workDays: number[]): Date[] {
|
||||
const dates: Date[] = [];
|
||||
|
||||
// Get Monday of the week
|
||||
const weekBounds = this.getWeekBounds(weekStart);
|
||||
const mondayOfWeek = this.startOfDay(weekBounds.start);
|
||||
|
||||
// Calculate dates for each work day using ISO numbering
|
||||
workDays.forEach(isoDay => {
|
||||
const date = new Date(mondayOfWeek);
|
||||
// ISO day 1=Monday is +0 days, ISO day 7=Sunday is +6 days
|
||||
const daysFromMonday = isoDay === 7 ? 6 : isoDay - 1;
|
||||
date.setDate(mondayOfWeek.getDate() + daysFromMonday);
|
||||
dates.push(date);
|
||||
});
|
||||
|
||||
return dates;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// GRID HELPERS
|
||||
// ============================================
|
||||
|
|
@ -290,4 +402,16 @@ export class DateService {
|
|||
public isValid(date: Date): boolean {
|
||||
return isValid(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if event spans multiple days
|
||||
* @param start - Start date or ISO string
|
||||
* @param end - End date or ISO string
|
||||
* @returns True if spans multiple days
|
||||
*/
|
||||
public isMultiDay(start: Date | string, end: Date | string): boolean {
|
||||
const startDate = typeof start === 'string' ? this.parseISO(start) : start;
|
||||
const endDate = typeof end === 'string' ? this.parseISO(end) : end;
|
||||
return !this.isSameDay(startDate, endDate);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue