@publidata/utils-opening-hours
Version:
Collection of methods to handle opening hours
90 lines (82 loc) • 2.41 kB
JavaScript
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
};