/**
 * Gets the day number from a date.
 *
 * @remark
 * Used in SchedulerElement
 *
 * @internal
 * @param date - The date.
 * @returns The day number.
 */
export function getDayNumber(date) {
    return date.getDate();
}
/**
 * Gets the weekday name for a date.
 *
 * @remark
 * Used in SchedulerElement
 *
 * @internal
 * @param date - The date.
 * @param locale - The locale for formatting.
 * @param format - The format ('long', 'short', 'narrow').
 * @returns The weekday name.
 *
 */
export function getWeekdayName(date, locale, format = 'short') {
    try {
        return date.toLocaleDateString(locale === 'default' ? undefined : locale, { weekday: format });
    }
    catch {
        return date.toLocaleDateString(undefined, { weekday: format });
    }
}
/**
 * Generates an array of Date objects representing each day within a specified month and year.
 *
 * @remark
 * Used in CalendarElement, DateBoxElement, DateTimeBoxElement
 *
 * @internal
 *
 * @param year - The year of the month for which to generate the days.
 * @param month - The zero-based index of the month (0 = January, 11 = December).
 * @returns An array of Date objects, each representing a day in the specified month and year.
 */
export function getDaysOfMonth(year, month) {
    const date = new Date(year, month, 1);
    const days = [];
    while (date.getMonth() === month) {
        days.push(new Date(date));
        date.setDate(date.getDate() + 1);
    }
    return days;
}
/**
 * Calculates the ISO 8601 week number for a given date.
 * ISO week 1 is the first week of the year that contains at least 4 days in the new year.
 * Weeks start on Monday.
 *
 * @param date - The date for which to calculate the week number.
 * @returns The ISO week number of the year for the given date (1-53).
 * @remark Used in CalendarElement
 * @internal
 */
export function getWeekNumber(date) {
    // Create a copy to avoid mutating the original
    const target = new Date(date.valueOf());
    // ISO week date weeks start on Monday, so correct the day number
    const dayNr = (target.getDay() + 6) % 7;
    // ISO 8601 states that week 1 is the first week with a Thursday in it
    // Set target to Thursday of the current week
    target.setDate(target.getDate() - dayNr + 3);
    // Store the target year (might differ from date's year for dates at year boundaries)
    const yearStart = new Date(target.getFullYear(), 0, 4);
    // Set yearStart to Thursday of week 1
    const yearStartDayNr = (yearStart.getDay() + 6) % 7;
    yearStart.setDate(yearStart.getDate() - yearStartDayNr + 3);
    // Calculate the week number
    const weekNumber = 1 + Math.floor((target.getTime() - yearStart.getTime()) / 604800000);
    return weekNumber;
}
/**
 * Generates a mapping of weekday indices to their names according to a specified locale and format.
 *
 * @param locale - A string representing the locale to use for formatting the day names.
 * @param format - The format of the weekday names ("long", "short", or "narrow").
 * @returns A Record<number, string> mapping day indices (0-6) to localized day names.
 * @remark Used in CalendarElement, SchedulerElement
 * @internal
 */
export function getDayNames(locale, format = 'long') {
    const dayNames = {};
    for (let day = 0; day < 7; day++) {
        const date = new Date(Date.UTC(2021, 5, 6 + day));
        const dayName = new Intl.DateTimeFormat(locale, { weekday: format }).format(date);
        dayNames[day] = dayName;
    }
    return dayNames;
}
/**
 * Rotates an array of day names based on the specified first day of the week.
 *
 * @param names - An array of day names ordered from Sunday (0) to Saturday (6).
 * @param firstDayOfWeek - The index of the first day of the week (0 = Sunday, 1 = Monday, ..., 6 = Saturday).
 * @returns A new array of day names rotated so that the first element corresponds to the specified first day of the week.
 * @remark Used in CalendarElement
 * @internal
 */
export function dayNames(names, firstDayOfWeek) {
    const rotatedDayNames = [
        ...names.slice(firstDayOfWeek),
        ...names.slice(0, firstDayOfWeek)
    ];
    return rotatedDayNames;
}
/**
 * Checks if two Date objects represent the same calendar day (ignoring time).
 *
 * @param date1 - The first date to compare.
 * @param date2 - The second date to compare.
 * @returns True if both dates are on the same day, false otherwise.
 * @remark Used in CalendarElement, DateBoxElement, DateTimeBoxElement
 * @internal
 */
export function isDateEqual(date1, date2) {
    return date1.getDate() === date2.getDate() && date1.getMonth() === date2.getMonth() && date1.getFullYear() === date2.getFullYear();
}
/**
 * Checks if a given date is today (local time, ignoring time of day).
 *
 * @param date - The date to check.
 * @returns True if the date is today, false otherwise.
 * @remark Used in CalendarElement, DateBoxElement, DateTimeBoxElement, SchedulerElement
 * @internal
 */
export function isToday(date) {
    const today = new Date();
    return isDateEqual(date, today);
}
/**
 * Checks if a date is present in an array of dates (by calendar day).
 *
 * @param date - The date to check.
 * @param dates - The array of dates to search.
 * @returns True if the date is found in the array, false otherwise.
 * @remark Used in CalendarElement
 * @internal
 */
export function isDateInDates(date, dates) {
    return dates.some((d) => isDateEqual(d, date));
}
/**
 * Checks if a date falls on a weekend (Saturday or Sunday).
 *
 * @param date - The date to check.
 * @returns True if the date is a weekend day, false otherwise.
 * @remark Used in CalendarElement, DateBoxElement, DateTimeBoxElement
 * @internal
 */
export function isWeekendDay(date) {
    return date.getDay() === 0 || date.getDay() === 6;
}
/**
 * Checks if a date falls on a weekday (Monday to Friday).
 *
 * @param date - The date to check.
 * @returns True if the date is a weekday, false otherwise.
 * @remark Used in CalendarElement, DateBoxElement, DateTimeBoxElement
 * @internal
 */
export function isWeekDay(date) {
    return !isWeekendDay(date);
}
/**
 * Returns a new Date object with the time set to midnight (00:00:00) for the given date.
 *
 * @param date - The date to normalize. If invalid, returns today at midnight.
 * @returns A new Date object at midnight of the same day.
 * @remark Used in CalendarElement, DateBoxElement, DateTimeBoxElement
 * @internal
 */
export function getDateOnly(date) {
    // Performance: Simplified validation
    const validDate = (date instanceof Date && !isNaN(date.getTime())) ? date : new Date();
    return new Date(validDate.getFullYear(), validDate.getMonth(), validDate.getDate());
}
/**
 * Parses an ISO date string to a Date object.
 * Handles both date-only (YYYY-MM-DD) and datetime (YYYY-MM-DDTHH:MM) formats.
 * Date-only strings are treated as local midnight, not UTC.
 *
 * @param isoString - The ISO date string.
 * @returns The Date object or null if invalid.
 * @remark Used in SchedulerElement, CalendarElement
 * @internal
 */
export function parseIsoDate(isoString) {
    if (!isoString) {
        return null;
    }
    if (/^\d{4}-\d{2}-\d{2}$/.test(isoString)) {
        const [year, month, day] = isoString.split('-').map(Number);
        return new Date(year, month - 1, day);
    }
    const date = new Date(isoString);
    return isNaN(date.getTime()) ? null : date;
}
/**
 * @internal
 * @remark Used in SchedulerElement, CalendarElement
 */
export function formatDateToIso(date) {
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    return `${year}-${month}-${day}`;
}
/**
 * @internal
 * @remark Used in SchedulerElement
 */
export function formatDateTimeToIso(date) {
    const dateStr = formatDateToIso(date);
    const hours = String(date.getHours()).padStart(2, '0');
    const minutes = String(date.getMinutes()).padStart(2, '0');
    return `${dateStr}T${hours}:${minutes}`;
}
/**
 * Formats a time for display using the specified locale.
 *
 * @internal
 * @remark Used in SchedulerMonthViewElement, SchedulerAgendaViewElement
 * @param time - The date/time to format.
 * @param locale - The locale for formatting.
 * @returns The formatted time string (e.g., "9:30 AM" or "09:30").
 */
export function formatTime(time, locale) {
    try {
        return time.toLocaleTimeString(locale === 'default' ? undefined : locale, {
            hour: 'numeric',
            minute: '2-digit'
        });
    }
    catch {
        return time.toLocaleTimeString(undefined, {
            hour: 'numeric',
            minute: '2-digit'
        });
    }
}
/**
 * @internal
 * @remark Used in SchedulerElement
 */
export function getDayKey(date) {
    return formatDateToIso(date);
}
/**
 * @deprecated Use {@link isDateEqual} instead. This function is a duplicate and will be removed in a future version.
 * @internal
 * @remark Used in SchedulerElement
 */
export function isSameDay(date1, date2) {
    return isDateEqual(date1, date2);
}
/**
 * @internal
 * @remark Used in SchedulerElement
 */
export function calculateTimePosition(time, hourStart, hourEnd) {
    const totalMinutes = (hourEnd - hourStart) * 60;
    const timeMinutes = (time.getHours() - hourStart) * 60 + time.getMinutes();
    const percentage = (timeMinutes / totalMinutes) * 100;
    return Math.max(0, Math.min(100, percentage));
}
/**
 * Calculates the height percentage for a time range between a start and end time, relative to a defined range of hours.
 *
 * @remark Used in SchedulerElement
 *
 * @internal
 * @param startTime - The starting time of the event.
 * @param endTime - The ending time of the event.
 * @param hourStart - The starting hour of the schedule (e.g., 8 for 8:00 AM).
 * @param hourEnd - The ending hour of the schedule (e.g., 18 for 6:00 PM).
 * @returns The height percentage (0-100) that represents the duration of the event within the defined hours.
 */
export function calculateTimeHeight(startTime, endTime, hourStart, hourEnd) {
    const totalMinutes = (hourEnd - hourStart) * 60;
    const durationMinutes = (endTime.getTime() - startTime.getTime()) / (1000 * 60);
    const percentage = (durationMinutes / totalMinutes) * 100;
    return Math.max(0, Math.min(100, percentage));
}
/**
 * Generates an array of hour numbers between the specified start and end hours.
 *
 * @remark Used in SchedulerElement
 *
 * @internal
 * @param hourStart - The starting hour (inclusive).
 * @param hourEnd - The ending hour (exclusive).
 * @returns An array of hour numbers (e.g., [9, 10, 11] for hourStart=9 and hourEnd=12).
 */
export function generateHours(hourStart, hourEnd) {
    const hours = [];
    for (let h = hourStart; h < hourEnd; h++) {
        hours.push(h);
    }
    return hours;
}
/**
 * Generates time slots between specified hours with a given step in minutes, formatted according to the provided locale and optional custom format function.
 *
 * @remark Used in SchedulerElement
 *
 * @internal
 * @param hourStart - The starting hour (inclusive).
 * @param hourEnd - The ending hour (exclusive).
 * @param stepMinutes - The interval in minutes between time slots.
 * @param locale - The locale for formatting the time labels.
 * @param formatFn - Optional custom function to format the time labels. If not provided, defaults to locale-based formatting.
 * @returns An array of objects representing the time slots, each containing the time key, formatted label, and flags for hour start and end.
 */
export function generateTimeSlots(hourStart, hourEnd, stepMinutes, locale, formatFn) {
    const slots = [];
    const effectiveLocale = locale ?? 'default';
    for (let h = hourStart; h < hourEnd; h++) {
        for (let m = 0; m < 60; m += stepMinutes) {
            const hours = String(h).padStart(2, '0');
            const minutes = String(m).padStart(2, '0');
            const timeKey = `${hours}:${minutes}`;
            const date = new Date(2000, 0, 1, h, m);
            let label;
            if (formatFn) {
                label = formatFn(date, effectiveLocale);
            }
            else {
                const formatter = new Intl.DateTimeFormat(effectiveLocale, {
                    hour: 'numeric',
                    minute: '2-digit',
                    hour12: undefined
                });
                label = formatter.format(date);
            }
            const nextMinutes = m + stepMinutes;
            const isLastOfHour = nextMinutes >= 60;
            slots.push({
                time: timeKey,
                label,
                isHour: m === 0,
                isLastOfHour
            });
        }
    }
    return slots;
}
/**
 * Gets the start of the week for a given date.
 *
 * @remark Used in SchedulerElement
 *
 * @internal
 * @param date - The date to find the start of week for.
 * @param firstDayOfWeek - The first day of the week (0 = Sunday, 1 = Monday, etc.).
 * @returns A new Date object at midnight on the first day of the week.
 */
export function getStartOfWeek(date, firstDayOfWeek) {
    const result = new Date(date);
    const currentDay = result.getDay();
    const diff = (currentDay - firstDayOfWeek + 7) % 7;
    result.setDate(result.getDate() - diff);
    // Normalize to midnight for consistency
    result.setHours(0, 0, 0, 0);
    return result;
}
/**
 * Generates an array of Date objects representing consecutive days starting from a given date.
 *
 * @remark Used in SchedulerElement
 *
 * @internal
 * @param startDate - The starting date for generating the visible dates.
 * @param days - The number of consecutive days to generate.
 * @returns An array of Date objects, each representing a day starting from the given date.
 */
export function generateVisibleDates(startDate, days) {
    const dates = [];
    for (let i = 0; i < days; i++) {
        const date = new Date(startDate);
        date.setDate(date.getDate() + i);
        dates.push(date);
    }
    return dates;
}
/**
 * Type guard to check if a value is a valid Date object.
 *
 * @internal
 * @param value The value to check.
 * @returns `true` if the value is a valid Date object, otherwise `false`.
 */
export function isDate(value) {
    return value instanceof Date && !isNaN(value.getTime());
}
/**
 * Safely retrieves a value from a record by key, returning undefined if the key does not exist.
 *
 * @internal
 * @param record - The record to retrieve the value from.
 * @param key - The key of the value to retrieve.
 * @returns The value associated with the key, or undefined if the key doesn't exist.
 */
export function tryGet(record, key) {
    if (key in record) {
        return record[key];
    }
    return undefined;
}
//# sourceMappingURL=DateExtensions.js.map