npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

bizdays-toolkit

v0.30.0

Published

Holidays, business-day calendar and day-by-day schedules (e.g. store hours) with time zone support. Japanese holidays verified against the Cabinet Office data; UK bank holidays (England, Wales, Scotland, Northern Ireland) verified against GOV.UK and The G

Readme

A business-day calendar that combines public holidays with company or store closures.

  • Holidays verified day by day against official data: Japan (Cabinet Office, 1955 to the latest year in the Official Gazette), the UK (GOV.UK; for 1974–2011 the Royal Proclamations in The Gazette, and from 2000 the government lists of the time; England, Wales, Scotland and Northern Ireland), France (data.gouv.fr; metropolitan France and Alsace-Moselle, verified for 2006–2031) and Singapore (Ministry of Manpower on data.gov.sg, 2020 onwards). Every date is checked in the tests, differences are watched daily and shipped as patch versions
  • Business-day arithmetic: closed weekdays, annual closures (across the new year too), specific closed and open dates and holidays combine into "N business days later", "next business day after the cutoff" and month-based due dates with the four adjustment conventions used in finance
  • Recurring rules: "closed on the 3rd Wednesday", "every other Wednesday", "stocktaking on the last day of the month", "closed on Mondays, moved to the next non-holiday when Monday is a holiday", "the day after (or before) a holiday", "the last weekday before a bank holiday", shift cycles such as four days on and two days off, each with its own behaviour on holidays and an optional effective period
  • Day-by-day values and combined calendars: store hours that change by weekday, holiday and date; a business-day calendar made from such a schedule; and the days on which all (or any) of several calendars are open
  • Option diagnostics: bizdays-toolkit/diagnose lists rules that never apply, rules that are shadowed or redundant, rules that have ended, typos in option names and options with no business day at all, without throwing. One line in a test keeps options honest
  • Lightweight, zero dependencies, time-zone safe: about 12.7 KB min+gzip (about 14.4 KB with Japanese holidays, about 14.8 KB with UK bank holidays, about 13.6 KB with French holidays, about 13.6 KB with Singapore holidays; measured for 0.30.0). Standard JavaScript and Intl only, ESM with bundled types; tested on Node.js, Chrome, Firefox, Edge, Safari, Cloudflare Workers, Bun and Deno. Instants such as Date are converted to a civil date in the calendar's time zone before evaluation
  • Extensible to other countries and regions: holiday providers are pluggable through the HolidayProvider interface, and bizdays-toolkit/provider exposes the calendar arithmetic (nth weekday of a month, Easter, substitute days for holidays on a weekend) that most countries' holidays are built from

Installation

pnpm add bizdays-toolkit

Node.js 22.12 or later. CI tests the package on Node.js 22.12, 22, 24 and 26, on Chrome, Firefox and Edge (Linux) and Safari (macOS), on Cloudflare Workers (workerd, the open-source Workers runtime), and on Bun (1.4) and Deno (2.9). The browsers are the latest stable versions on GitHub's runners, so their versions change as the runners are updated. The package is ESM only, but it can also be loaded from CommonJS with require() (tested in CI as well; on Node.js 22.12, require() prints an experimental-feature warning, which does not affect the result, and Node.js 26 prints none). Vercel's Edge Runtime is not tested.

Types are bundled. CI type-checks a consumer project against the published type definitions with TypeScript 5.0, 5.5, 5.8, 6.0 and 7.0 (the native compiler), each with moduleResolution set to node16, nodenext and bundler, and confirms that an intentional type error is reported by each.

Quick start

import { createCalendar } from "bizdays-toolkit";
import { isHoliday, jp } from "bizdays-toolkit/jp";

isHoliday("2026-11-23"); // true (Labor Thanksgiving Day)

const calendar = createCalendar({
  holidayProvider: jp,
  closedWeekdays: [0, 6],
  closedAnnualDates: [{ from: "12-29", to: "01-03", name: "New Year closure" }],
});
calendar.isBusinessDay("2026-12-30"); // false
calendar.addBusinessDays("2026-12-28", 1); // "2027-01-04"
calendar.businessDayOnOrAfter("2026-12-28T15:30", { cutoff: "14:00" }); // "2027-01-04" (after the cutoff, so the next business day)
calendar.dueDate("2026-11", { dayOfMonth: 23, convention: "following" }); // "2026-11-24" (the 23rd is a holiday)

The guide explains everything below in full, with examples that are run in CI. This README is the short version.

What you can do

Holidays of Japan, the UK, France and Singapore

| Provider | Subpath | Time zone | Supported years | Verified against | | ------------------------------------------------- | -------------------- | ---------------- | --------------- | --------------------------------------------------------------------------------------------- | | jp | bizdays-toolkit/jp | Asia/Tokyo | 1955–2099 | Cabinet Office "National Holidays" CSV | | england, wales, scotland, northernIreland | bizdays-toolkit/uk | Europe/London | 1974–2099 | GOV.UK bank holidays (1974–2011: The Gazette, and the government lists of the time from 2000) | | metropole, alsaceMoselle | bizdays-toolkit/fr | Europe/Paris | 2000–2099 | data.gouv.fr "Jours fériés en France" | | sg | bizdays-toolkit/sg | Asia/Singapore | 2020–2027 | data.gov.sg (Ministry of Manpower) |

Each holiday carries its date, name (and English name), kind (national, substitute, citizens' holiday, bank holiday and so on, by country) and confirmed (whether the date is officially fixed; the Japanese equinox days and UK bank holidays after the last published year are predictions). Years after the supported range are an error unless outOfRangePolicy: "ignore" is set, and unconfirmedHolidayPolicy: "throw" stops any result that would depend on a predicted holiday. Details: Bundled holiday providers, Unconfirmed holidays.

Business-day calendars and recurring rules

A calendar is built from the holiday provider and your closures: closedWeekdays, closedAnnualDates (month-day ranges, across the new year too), closedDates and openDates, and recurring rules in closedRecurringRules / openRecurringRules:

| Rule | Meaning | | --------------------------------------------------------- | -------------------------------------------------------------------------------- | | { weekday: 3, nth: 3 } | The 3rd Wednesday (nth is 1–5 or -1 for the last; an array for several) | | { weekday: 3, interval: 2, anchor: "2026-01-07" } | Every other Wednesday, counted from the anchor | | { cycle: 6, anchor: "2026-01-05", positions: [5, 6] } | Days 5 and 6 of every 6 days from the anchor (four days on, two days off) | | { dayOfMonth: 20 }, { dayOfMonth: -1 } | The 20th, the last day of the month | | { businessDayOfMonth: -1 }, { businessDayOfMonth: 5 } | The last business day of the month, the 5th business day | | { businessDayOfWeek: -1, weekStart: 1 } | The last business day of the week starting on Monday | | { holiday: true, kinds: ["substitute"] } | Holidays, optionally narrowed by kind or by key (keys: ["vernal-equinox"]) | | { dayAfterHoliday: true }, { dayBeforeHoliday: true } | The day after (or before) a holiday or a run of holidays | | holidayOverlapPolicy: "after-holiday" | "Closed on Mondays, or the next non-holiday if a holiday" (can be a Saturday) | | skipWeekdays: [0, 6] | With "after-holiday": also skip weekends ("June 15, or the next business day") | | effectiveFrom, effectiveTo | The period the rule is in effect |

dayInfoOn tells you why a day is open or closed (reason, name, optionPath). Every bundled holiday that recurs each year has a stable key (vernal-equinox, good-friday, hari-raya-puasa, …), so a rule can select individual holidays that no date pattern can express. Details: Business-day calendars, Recurring rules, Holiday keys, Common recipes.

Due dates, schedules and combined calendars

  • dueDate("2026-11", { dayOfMonth: 23, convention: "following" }), adjust, closingMonth and closingPeriod compute month-based due dates and closing periods with the following, preceding, modified-following and modified-preceding conventions (Month-based due dates)
  • createSchedule gives a value per day (store hours, a shipping cutoff, a price band) from the same kinds of rules, and createCalendarFromSchedule turns such a schedule into a calendar so the hours are the only configuration (Day-by-day values, A calendar from a schedule)
  • combineCalendars builds the days on which all (or any) of several calendars are open, such as your company and the bank for a remittance date (Combining calendars)
  • Dates can be given as "YYYY-MM-DD", "YYYY-MM-DDTHH:mm", Date or Temporal objects; instants are converted in the calendar's time zone (Date and date-time inputs)

Option diagnostics

import { diagnoseCalendar } from "bizdays-toolkit/diagnose";
import { jp } from "bizdays-toolkit/jp";

diagnoseCalendar({
  holidayProvider: jp,
  closedWeekdays: [0],
  closedRecurringRules: [{ weekday: 0 }],
  closeAnnual: ["12-31"],
}).map((d) => [d.severity, d.code, d.path]);
// [["warning", "unknown-option", "closeAnnual"], ["info", "redundant", "closedRecurringRules[0]"]]

diagnoseCalendar and diagnoseSchedule return every problem in the options without throwing: typos (with a suggestion), rules that never match, rules shadowed by earlier ones, rules whose removal changes nothing, options with no business day, and, with { asOf }, rules that have ended. assert.deepEqual(diagnoseCalendar(options), []) in a test keeps options honest. Details: Option diagnostics, Errors.

Other countries and regions

A holiday provider is an object with id, timeZone, supportedYears and holidaysInYear(year). bizdays-toolkit/provider exposes nthWeekdayOfMonth and easterSunday, which most countries' holidays are built from. See providers.md.

Documentation

Versioning and data updates

Versioning follows Semantic Versioning. See RELEASING.md (Japanese) for details.

  • Official data updates (new, moved and one-off holidays by law, Official Gazette or proclamation, fixed equinox days in Japan, newly published years on GOV.UK, changes to the French Labour Code, newly gazetted years and revised dates in Singapore) are released as patch versions, so they reach you with either ^ or ~
  • To freeze the holiday results, pin an exact version (for example "bizdays-toolkit": "0.21.3")
  • The reflected data is shown by the provider's dataVersion (for Japan, the year and month of the Official Gazette reflected; for the UK, France and Singapore, the year and month of the GOV.UK, data.gouv.fr or data.gov.sg data reflected) and confirmedThrough (jp.dataVersion, england.confirmedThrough and so on). The module-level constants dataVersion and confirmedThrough in bizdays-toolkit/jp and bizdays-toolkit/uk are deprecated since 0.12.0 and will be removed in 1.0.0
  • Before 1.0.0, minor versions may contain breaking changes. What you need to change when moving between minor versions is listed in the migration guide (Japanese) and in the "移行" (migration) part of each version in the CHANGELOG
  • Decision reasons (reason), holiday kinds (kind), error codes and diagnostic codes may gain values in future versions. When you branch on their values, handle "anything else" too (see "互換性の約束", the compatibility promise, in RELEASING.md)

Data sources

Japanese holidays are verified with the "National Holidays" CSV published on the Cabinet Office website (https://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv) (as a test fixture only; not included in the package).

UK bank holidays are verified with the GOV.UK bank holidays data (https://www.gov.uk/bank-holidays.json, and for earlier years the history of the official GOV.UK repositories alphagov/calendars and alphagov/frontend), and the Welsh names of the Wales holidays with the Welsh version of GOV.UK (the verification data is a test fixture only; not included in the package).

For 2000–2011, which predate GOV.UK's data, the authority is the bank holiday lists the government published at the time (DTI and BERR, directgov, the Scottish Executive and Government, nidirect; captured by the Wayback Machine), checked against the Royal Proclamations and Northern Ireland Orders in The Gazette (https://www.thegazette.co.uk/); for 1974–1999 the proclamations are the authority. Thirteen days in 1975–1990 are returned by rule but could not be checked (listed as unverified in the test fixture, with the reasons): the Northern Ireland Orders of 1986–1990 are in issues of The Gazette that are not online, and the 1987 annual proclamation and the Northern Ireland Order of 1975 were not found. The sources are listed in docs/sources/uk-bank-holidays-1974-1999.md and docs/sources/uk-bank-holidays-2000-2011.md (not included in the package).

French public holidays are verified with the "Jours fériés en France" dataset published by DINUM on data.gouv.fr (https://www.data.gouv.fr/datasets/jours-feries-en-france, JSON exports for the Métropole and Alsace-Moselle zones; the verification data is a test fixture only; not included in the package).

Singapore public holidays are verified with the "Singapore Public Holidays" collection published by the Ministry of Manpower on data.gov.sg (https://data.gov.sg/collections/691/view), with the Ministry's press releases as the authority where the two differ (the verification data is a test fixture only; not included in the package).

Contains public sector information licensed under the Open Government Licence v3.0, data from data.gouv.fr made available under the Licence Ouverte / Open Licence 2.0, and data from data.gov.sg made available under the Singapore Open Data Licence.

License

This software is released under the MIT License, see LICENSE.