dralkh_spaceforge/utils/dates.ts
2025-07-31 07:03:20 +03:00

177 lines
7.3 KiB
TypeScript

/**
* Utility functions for date operations
*/
export class DateUtils {
/**
* Get start of day timestamp for a given date
*
* @param date Date to get start of day for
* @returns Timestamp for start of day
*/
static startOfDay(date: Date = new Date()): number {
const newDate = new Date(date);
newDate.setHours(0, 0, 0, 0);
return newDate.getTime();
}
/**
* Add days to a timestamp
*
* @param timestamp Base timestamp
* @param days Number of days to add
* @returns New timestamp
*/
static addDays(timestamp: number, days: number): number {
return timestamp + (days * 24 * 60 * 60 * 1000);
}
/**
* Format a timestamp as a readable date string
*
* @param timestamp Timestamp to format
* @param format Format type ('short', 'medium', 'long', 'relative')
* @param baseDateParam Optional base date for relative formatting
* @returns Formatted date string
*/
static formatDate(timestamp: number, format: 'short' | 'medium' | 'long' | 'relative' = 'medium', baseDateParam?: Date | null): string {
const noteEventDate = new Date(timestamp); // The date of the note/event
if (format === 'relative') {
// Determine the reference date for relative calculations
const referenceDateForCalc = baseDateParam ? new Date(baseDateParam) : new Date();
// Normalize dates to their start of day for accurate day-based comparison
const normalizedNoteEventDate = this.startOfDay(noteEventDate);
const normalizedReferenceDate = this.startOfDay(referenceDateForCalc);
const normalizedActualCurrentDate = this.startOfDay(new Date()); // Actual current day, for "Due notes"
// "Due notes" are always relative to the *actual* current day, regardless of baseDateParam
if (normalizedNoteEventDate < normalizedActualCurrentDate) {
return 'Due notes';
}
// If baseDateParam is set, we are in a calendar view for a specific day.
// The label for the group of notes (which are all for baseDateParam's day)
// should reflect how baseDateParam's day relates to the actual current day.
if (baseDateParam) {
const normalizedBaseDate = this.startOfDay(new Date(baseDateParam)); // The day being viewed in the calendar
if (normalizedBaseDate === normalizedActualCurrentDate) {
return 'Today'; // e.g., Calendar view is set to actual today
} else if (normalizedBaseDate === this.startOfDay(new Date(this.addDays(normalizedActualCurrentDate, 1)))) {
return 'Tomorrow'; // e.g., Calendar view is set to actual tomorrow
} else {
// Calendar view is set to a specific day that is not actual today or actual tomorrow.
// This includes future days beyond tomorrow, or past days (which aren't "Due notes" but >= actualCurrentDate).
// Display the specific date of the calendar view.
return new Date(normalizedBaseDate).toLocaleDateString(undefined, { month: 'short', day: 'numeric' });
}
} else {
// No baseDateParam, so this is the default dashboard view.
// Comparisons are relative to the actual current date.
// We already know normalizedNoteEventDate >= normalizedActualCurrentDate from the "Due notes" check.
const diffInDays = Math.floor((normalizedNoteEventDate - normalizedActualCurrentDate) / (24 * 60 * 60 * 1000));
if (diffInDays === 0) {
return 'Today'; // Note is scheduled for actual today
} else if (diffInDays === 1) {
return 'Tomorrow'; // Note is scheduled for actual tomorrow
} else { // diffInDays > 1
return `In ${diffInDays} days`; // Note is scheduled further in the future
}
}
} else if (format === 'short') {
return noteEventDate.toLocaleDateString();
} else if (format === 'long') {
return noteEventDate.toLocaleDateString(undefined, {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
});
} else {
// Medium format (default)
return noteEventDate.toLocaleDateString(undefined, {
weekday: 'short',
month: 'short',
day: 'numeric'
});
}
}
/**
* Get the day difference between two timestamps
*
* @param timestamp1 First timestamp
* @param timestamp2 Second timestamp
* @returns Difference in days
*/
static dayDifference(timestamp1: number, timestamp2: number): number {
const date1 = new Date(timestamp1);
const date2 = new Date(timestamp2);
// Reset to midnight
date1.setHours(0, 0, 0, 0);
date2.setHours(0, 0, 0, 0);
// Calculate difference in days
const diffTime = Math.abs(date2.getTime() - date1.getTime());
const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
return diffDays;
}
/**
* Get start of UTC day timestamp for a given date
*
* @param date Date to get start of UTC day for
* @returns Timestamp for start of UTC day (00:00:00.000Z)
*/
static startOfUTCDay(date: Date = new Date()): number {
const newDate = new Date(date.getTime()); // Create a new Date object from the timestamp
newDate.setUTCHours(0, 0, 0, 0);
return newDate.getTime();
}
/**
* Get end of UTC day timestamp for a given date
*
* @param date Date to get end of UTC day for
* @returns Timestamp for end of UTC day (23:59:59.999Z)
*/
static endOfUTCDay(date: Date = new Date()): number {
const newDate = new Date(date.getTime()); // Create a new Date object from the timestamp
newDate.setUTCHours(23, 59, 59, 999);
return newDate.getTime();
}
/**
* Get the day difference between two timestamps based on UTC days
*
* @param timestamp1 First timestamp
* @param timestamp2 Second timestamp
* @returns Difference in UTC days
*/
static dayDifferenceUTC(timestamp1: number, timestamp2: number): number {
const date1UTCMidnight = this.startOfUTCDay(new Date(timestamp1));
const date2UTCMidnight = this.startOfUTCDay(new Date(timestamp2));
// Calculate difference in days
const diffTime = Math.abs(date2UTCMidnight - date1UTCMidnight);
const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
return diffDays;
}
/**
* Check if two dates are the same day, ignoring time.
* @param date1 The first date.
* @param date2 The second date.
* @returns True if both dates fall on the same day, false otherwise.
*/
static isSameDay(date1: Date, date2: Date): boolean {
return date1.getFullYear() === date2.getFullYear() &&
date1.getMonth() === date2.getMonth() &&
date1.getDate() === date2.getDate();
}
}