// Feiertage-Service: Lädt Feiertage aus DB oder von feiertage-api.de (BW), speichert in public_holidays const https = require('https'); const { db } = require('../database'); const API_BASE = 'https://feiertage-api.de/api/'; const LAND = 'BW'; /** * Holt Feiertage für ein Jahr von der API und speichert sie in der DB. * @param {number} year * @returns {Promise>} Set von Datums-Strings YYYY-MM-DD */ function fetchHolidaysFromAPI(year) { return new Promise((resolve, reject) => { const url = `${API_BASE}?jahr=${year}&nur_land=${LAND}`; https.get(url, (res) => { let data = ''; res.on('data', (chunk) => { data += chunk; }); res.on('end', () => { try { const json = JSON.parse(data); const dates = new Set(); const toInsert = []; for (const [name, obj] of Object.entries(json)) { if (obj && obj.datum) { dates.add(obj.datum); toInsert.push({ date: obj.datum, name: name || null }); } } if (toInsert.length === 0) { resolve(dates); return; } let pending = toInsert.length; toInsert.forEach(({ date, name }) => { db.run('INSERT OR REPLACE INTO public_holidays (date, name) VALUES (?, ?)', [date, name], (err) => { if (err) console.warn('Feiertage: Fehler beim Speichern:', err.message); pending--; if (pending === 0) resolve(dates); }); }); } catch (e) { reject(e); } }); }).on('error', reject); }); } /** * Liest Feiertage für ein Jahr aus der DB. * @param {number} year * @returns {Promise>} */ function getHolidaysFromDB(year) { return new Promise((resolve, reject) => { const pattern = `${year}-%`; db.all('SELECT date FROM public_holidays WHERE date LIKE ?', [pattern], (err, rows) => { if (err) return reject(err); const set = new Set((rows || []).map((r) => r.date)); resolve(set); }); }); } /** * Liefert alle Feiertage für ein Jahr. Zuerst DB; wenn Jahr fehlt, API aufrufen und in DB schreiben. * @param {number} year * @returns {Promise>} Set von YYYY-MM-DD */ function getHolidaysForYear(year) { return getHolidaysFromDB(year).then((set) => { if (set.size > 0) return set; return fetchHolidaysFromAPI(year).catch((err) => { console.warn('Feiertage API fehlgeschlagen für Jahr', year, err.message); return new Set(); }); }); } /** * Liefert alle Feiertage im Datumsbereich [weekStart, weekEnd] (inklusive). * Lädt ggf. fehlende Jahre aus der API und speichert sie in der DB. * @param {string} weekStart YYYY-MM-DD * @param {string} weekEnd YYYY-MM-DD * @returns {Promise>} Set von YYYY-MM-DD */ function getHolidaysForDateRange(weekStart, weekEnd) { const startYear = parseInt(weekStart.slice(0, 4), 10); const endYear = parseInt(weekEnd.slice(0, 4), 10); const years = []; for (let y = startYear; y <= endYear; y++) years.push(y); return Promise.all(years.map((y) => getHolidaysForYear(y))).then((sets) => { const combined = new Set(); sets.forEach((s) => s.forEach((d) => combined.add(d))); const inRange = new Set(); combined.forEach((d) => { if (d >= weekStart && d <= weekEnd) inRange.add(d); }); return inRange; }); } module.exports = { getHolidaysForYear, getHolidaysForDateRange, };