UNPKG

@publidata/utils-opening-hours

Version:

Collection of methods to handle opening hours

90 lines (82 loc) 2.41 kB
const OpeningHours = require("opening_hours"); const dayjs = require("dayjs"); const nominatimModule = require("./nominatim"); const cache = new Map(); function nominatimCacheKey(n) { if (!n) return "default"; try { return JSON.stringify(n); } catch { return "default"; } } /** * Cached opening_hours.js instances keyed by (OH string + nominatim). * * @param {string} ohString * @param {object} [nominatim] defaults to nominatim.get() * @returns {object|null} */ function getCachedOpeningHours(ohString, nominatim) { if (!ohString) return null; const nom = nominatim != null ? nominatim : nominatimModule.get(); const key = `${ohString}\0${nominatimCacheKey(nom)}`; if (cache.has(key)) return cache.get(key); try { const instance = new OpeningHours(ohString, nom); cache.set(key, instance); return instance; } catch { return null; } } /** * @param {string} ohString * @param {Date} date * @param {object} [nominatim] * @returns {boolean|null} null if OH string is invalid */ function getOpeningStateAt(ohString, date, nominatim) { const oh = getCachedOpeningHours(ohString, nominatim); if (!oh) return null; const d = date instanceof Date ? date : new Date(date); return oh.getState(d); } /** * @param {string} ohString * @param {Date} fromDate * @param {object} [nominatim] * @returns {Date|null} */ function getNextOpeningChange(ohString, fromDate, nominatim) { const oh = getCachedOpeningHours(ohString, nominatim); if (!oh) return null; const d = fromDate instanceof Date ? fromDate : new Date(fromDate); return oh.getNextChange(d); } /** * Whether the OH string defines an open interval on that calendar day * (opening exception / regular collection day without 24/7 prefix). * * @param {string} ohString * @param {import("dayjs").Dayjs} day * @param {object} [nominatim] */ function hasOpenIntervalOnDay(ohString, day, nominatim) { const oh = getCachedOpeningHours(ohString, nominatim); if (!oh) return false; const dayStart = day.startOf("day").toDate(); if (oh.getState(dayStart)) return true; const nextChange = oh.getNextChange(new Date(dayStart.valueOf() - 1)); return ( nextChange !== null && dayjs(nextChange).isSame(day, "day") && oh.getState(nextChange) ); } module.exports = { getCachedOpeningHours, getOpeningStateAt, getNextOpeningChange, hasOpenIntervalOnDay };