UNPKG

@eristack/business-calendar

Version:

Business days and holidays on YYYY-MM-DD wall dates — no timestamp import in core

139 lines (135 loc) • 4.53 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { BusinessCalendarParseError: () => BusinessCalendarParseError, addWallDays: () => addWallDays, createBusinessCalendar: () => createBusinessCalendar, normalizeWallDate: () => normalizeWallDate, wallDateDayOfWeek: () => wallDateDayOfWeek }); module.exports = __toCommonJS(index_exports); // src/core/errors.ts var BusinessCalendarParseError = class extends Error { code = "BUSINESS_CALENDAR_PARSE_ERROR"; constructor(message) { super(message); this.name = "BusinessCalendarParseError"; } }; // src/core/wall-date.ts var WALL_DATE_RE = /^(\d{4})-(\d{2})-(\d{2})$/; function normalizeWallDate(value) { const trimmed = value.trim(); const match = WALL_DATE_RE.exec(trimmed); if (!match) { throw new BusinessCalendarParseError( `Invalid wall date "${value}" \u2014 expected YYYY-MM-DD` ); } const year = Number(match[1]); const month = Number(match[2]); const day = Number(match[3]); const utc = Date.UTC(year, month - 1, day); const check = new Date(utc); if (check.getUTCFullYear() !== year || check.getUTCMonth() !== month - 1 || check.getUTCDate() !== day) { throw new BusinessCalendarParseError(`Invalid calendar date "${value}"`); } const mm = String(month).padStart(2, "0"); const dd = String(day).padStart(2, "0"); return `${year}-${mm}-${dd}`; } function wallDateDayOfWeek(date) { const normalized = normalizeWallDate(date); const [y, m, d] = normalized.split("-").map(Number); return new Date(Date.UTC(y, m - 1, d)).getUTCDay(); } function addWallDays(date, days) { const normalized = normalizeWallDate(date); const [y, m, d] = normalized.split("-").map(Number); const next = new Date(Date.UTC(y, m - 1, d)); next.setUTCDate(next.getUTCDate() + days); const ny = next.getUTCFullYear(); const nm = String(next.getUTCMonth() + 1).padStart(2, "0"); const nd = String(next.getUTCDate()).padStart(2, "0"); return `${ny}-${nm}-${nd}`; } // src/core/calendar.ts function normalizeWeekendDays(days) { const set = /* @__PURE__ */ new Set(); for (const day of days) { if (!Number.isInteger(day) || day < 0 || day > 6) { throw new BusinessCalendarParseError( `weekendDays entry ${day} must be an integer 0\u20136 (Sun\u2013Sat)` ); } set.add(day); } return set; } function createBusinessCalendar(options) { const weekendDays = normalizeWeekendDays(options.weekendDays); const holidays = new Set( options.holidays.map((h) => normalizeWallDate(h)) ); function isBusinessDay(date) { const wall = normalizeWallDate(date); if (holidays.has(wall)) { return false; } const dow = wallDateDayOfWeek(wall); return !weekendDays.has(dow); } function nextBusinessDay(date) { let cursor = normalizeWallDate(date); do { cursor = addWallDays(cursor, 1); } while (!isBusinessDay(cursor)); return cursor; } function addBusinessDays(date, days) { if (!Number.isInteger(days)) { throw new BusinessCalendarParseError("days must be an integer"); } let cursor = normalizeWallDate(date); if (days === 0) { return cursor; } const step = days > 0 ? 1 : -1; let remaining = Math.abs(days); while (remaining > 0) { cursor = addWallDays(cursor, step); if (isBusinessDay(cursor)) { remaining -= 1; } } return cursor; } return { isBusinessDay, nextBusinessDay, addBusinessDays }; } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { BusinessCalendarParseError, addWallDays, createBusinessCalendar, normalizeWallDate, wallDateDayOfWeek }); //# sourceMappingURL=index.cjs.map