UNPKG

date-picker-svelte

Version:
140 lines (139 loc) 4.73 kB
export function isLeapYear(year) { return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; } export function getMonthLength(year, month) { const feb = isLeapYear(year) ? 29 : 28; const monthLengths = [31, feb, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; return monthLengths[month]; } export function toText(date, formatTokens) { let text = ''; if (date) { for (const token of formatTokens) { if (typeof token === 'string') { text += token; } else { text += token.toString(date); } } } return text; } export function isSameDate(date1, date2) { return (date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth() && date1.getDate() === date2.getDate()); } export function getMonthDays(year, month) { const monthLength = getMonthLength(year, month); const days = []; for (let i = 0; i < monthLength; i++) { days.push({ year: year, month: month, number: i + 1, }); } return days; } export function getCalendarDays(value, weekStartsOn) { const year = value.getFullYear(); const month = value.getMonth(); const firstWeekday = new Date(year, month, 1).getDay(); let days = []; // add last month const daysBefore = (firstWeekday - weekStartsOn + 7) % 7; if (daysBefore > 0) { let lastMonth = month - 1; let lastMonthYear = year; if (lastMonth === -1) { lastMonth = 11; lastMonthYear = year - 1; } days = getMonthDays(lastMonthYear, lastMonth).slice(-daysBefore); } // add current month days = days.concat(getMonthDays(year, month)); // add next month let nextMonth = month + 1; let nextMonthYear = year; if (nextMonth === 12) { nextMonth = 0; nextMonthYear = year + 1; } const daysAfter = 42 - days.length; days = days.concat(getMonthDays(nextMonthYear, nextMonth).slice(0, daysAfter)); return days; } export function applyTimePrecision(date, timePrecision) { // Set unused time components to 0 if (timePrecision === null) { date.setHours(0, 0, 0, 0); } else if (timePrecision === 'minute') { date.setSeconds(0, 0); } else if (timePrecision === 'second') { date.setMilliseconds(0); } } export function cloneDate(d) { return new Date(d); } export function toValidDate(oldDate, newDate, minDate, maxDate, isDisabledDate) { // Don't mutate the original newDate to avoid unintended side effects let adjustedDate = cloneDate(newDate); if (oldDate > newDate) { adjustDate(adjustedDate, -1, minDate, maxDate, isDisabledDate); if (adjustedDate < minDate) { adjustedDate = clampDate(adjustedDate, minDate, maxDate); // Adjusts the date one more time if the min date is disabled, to ensure a valid, enabled date is selected adjustDate(adjustedDate, 1, minDate, maxDate, isDisabledDate); } } else if (adjustedDate >= oldDate) { adjustDate(adjustedDate, 1, minDate, maxDate, isDisabledDate); if (adjustedDate > maxDate) { adjustedDate = clampDate(adjustedDate, minDate, maxDate); // Adjusts the date one more time if the max date is disabled, to ensure a valid, enabled date is selected adjustDate(adjustedDate, -1, minDate, maxDate, isDisabledDate); } } // Finally, clamp the time if (adjustedDate < minDate || adjustedDate > maxDate) { adjustedDate = clamp(adjustedDate, minDate, maxDate); } return adjustedDate; } function adjustDate(date, increment, minDate, maxDate, isDisabledDate) { // Prevents accidental infinite loops const MAXLOOPS = 36525; // ~100 years, should be large enough let loopCount = 0; while (isDisabledDate?.(date) && date >= minDate && date <= maxDate && loopCount <= MAXLOOPS) { date.setDate(date.getDate() + increment); loopCount++; } } export function clamp(value, min, max) { if (value > max) { return cloneDate(max); } else if (value < min) { return cloneDate(min); } else { return cloneDate(value); } } export function clampDate(value, min, max) { const limit = clamp(value, min, max); value = new Date(limit.getFullYear(), limit.getMonth(), limit.getDate(), value.getHours(), value.getMinutes(), value.getSeconds(), value.getMilliseconds()); if (value > max) { value.setDate(max.getDate()); } if (value < min) { value.setDate(min.getDate()); } return value; }