Display national holidays on the calendar.
This commit is contained in:
179
src/utils/holidays.js
Normal file
179
src/utils/holidays.js
Normal file
@@ -0,0 +1,179 @@
|
||||
// holidays.js — Holiday utilities using date-holidays package
|
||||
import Holidays from 'date-holidays'
|
||||
|
||||
let holidaysInstance = null
|
||||
let currentCountry = null
|
||||
let currentState = null
|
||||
let currentRegion = null
|
||||
let holidayCache = new Map()
|
||||
let yearCache = new Map()
|
||||
|
||||
/**
|
||||
* Initialize holidays for a specific country/region
|
||||
* @param {string} country - Country code (e.g., 'US', 'GB', 'DE')
|
||||
* @param {string} [state] - State/province code (e.g., 'CA' for California)
|
||||
* @param {string} [region] - Region code
|
||||
*/
|
||||
export function initializeHolidays(country, state = null, region = null) {
|
||||
if (!country) {
|
||||
console.warn('No country provided for holiday initialization')
|
||||
holidaysInstance = null
|
||||
return false
|
||||
}
|
||||
|
||||
try {
|
||||
holidaysInstance = new Holidays(country, state, region)
|
||||
currentCountry = country
|
||||
currentState = state
|
||||
currentRegion = region
|
||||
|
||||
holidayCache.clear()
|
||||
yearCache.clear()
|
||||
|
||||
return true
|
||||
} catch (error) {
|
||||
console.warn('Failed to initialize holidays for', country, state, region, error)
|
||||
holidaysInstance = null
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get holidays for a specific year
|
||||
* @param {number} year - The year to get holidays for
|
||||
* @returns {Array} Array of holiday objects
|
||||
*/
|
||||
export function getHolidaysForYear(year) {
|
||||
if (!holidaysInstance) {
|
||||
return []
|
||||
}
|
||||
|
||||
if (yearCache.has(year)) {
|
||||
return yearCache.get(year)
|
||||
}
|
||||
|
||||
try {
|
||||
const holidays = holidaysInstance.getHolidays(year)
|
||||
yearCache.set(year, holidays)
|
||||
return holidays
|
||||
} catch (error) {
|
||||
console.warn('Failed to get holidays for year', year, error)
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get holiday for a specific date
|
||||
* @param {string|Date} date - Date in YYYY-MM-DD format or Date object
|
||||
* @returns {Object|null} Holiday object or null if no holiday
|
||||
*/
|
||||
export function getHolidayForDate(date) {
|
||||
if (!holidaysInstance) {
|
||||
return null
|
||||
}
|
||||
|
||||
const cacheKey = typeof date === 'string' ? date : date.toISOString().split('T')[0]
|
||||
if (holidayCache.has(cacheKey)) {
|
||||
return holidayCache.get(cacheKey)
|
||||
}
|
||||
|
||||
try {
|
||||
let dateObj
|
||||
if (typeof date === 'string') {
|
||||
const [year, month, day] = date.split('-').map(Number)
|
||||
dateObj = new Date(year, month - 1, day)
|
||||
} else {
|
||||
dateObj = date
|
||||
}
|
||||
|
||||
const year = dateObj.getFullYear()
|
||||
const holidays = getHolidaysForYear(year)
|
||||
|
||||
const holiday = holidays.find((h) => {
|
||||
const holidayDate = new Date(h.date)
|
||||
return (
|
||||
holidayDate.getFullYear() === dateObj.getFullYear() &&
|
||||
holidayDate.getMonth() === dateObj.getMonth() &&
|
||||
holidayDate.getDate() === dateObj.getDate()
|
||||
)
|
||||
})
|
||||
|
||||
const result = holiday || null
|
||||
holidayCache.set(cacheKey, result)
|
||||
|
||||
return result
|
||||
} catch (error) {
|
||||
console.warn('Failed to get holiday for date', date, error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a date is a holiday
|
||||
* @param {string|Date} date - Date in YYYY-MM-DD format or Date object
|
||||
* @returns {boolean} True if the date is a holiday
|
||||
*/
|
||||
export function isHoliday(date) {
|
||||
return getHolidayForDate(date) !== null
|
||||
}
|
||||
|
||||
/**
|
||||
* Get available countries for holidays
|
||||
* @returns {Array} Array of country codes
|
||||
*/
|
||||
export function getAvailableCountries() {
|
||||
try {
|
||||
const holidays = new Holidays()
|
||||
const countries = holidays.getCountries()
|
||||
|
||||
// The getCountries method might return an object, convert to array of keys
|
||||
if (countries && typeof countries === 'object') {
|
||||
return Array.isArray(countries) ? countries : Object.keys(countries)
|
||||
}
|
||||
|
||||
return ['US', 'GB', 'DE', 'FR', 'CA', 'AU'] // Fallback
|
||||
} catch (error) {
|
||||
console.warn('Failed to get available countries', error)
|
||||
return ['US', 'GB', 'DE', 'FR', 'CA', 'AU'] // Fallback to common countries
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get available states/regions for a country
|
||||
* @param {string} country - Country code
|
||||
* @returns {Array} Array of state/region codes
|
||||
*/
|
||||
export function getAvailableStates(country) {
|
||||
try {
|
||||
if (!country) return []
|
||||
|
||||
const holidays = new Holidays()
|
||||
const states = holidays.getStates(country)
|
||||
|
||||
// The getStates method might return an object, convert to array of keys
|
||||
if (states && typeof states === 'object') {
|
||||
return Array.isArray(states) ? states : Object.keys(states)
|
||||
}
|
||||
|
||||
return []
|
||||
} catch (error) {
|
||||
console.warn('Failed to get available states for', country, error)
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get holiday configuration info
|
||||
* @returns {Object} Current holiday configuration
|
||||
*/
|
||||
export function getHolidayConfig() {
|
||||
return {
|
||||
country: currentCountry,
|
||||
state: currentState,
|
||||
region: currentRegion,
|
||||
initialized: !!holidaysInstance,
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize with US holidays by default
|
||||
initializeHolidays('US')
|
||||
Reference in New Issue
Block a user