Tutorial: business days end to end
@johnhenry/temporals covers a lot of ground — recurrence rules, cron scheduling, interval algebra, humanized durations. This tutorial picks one task it solves well and does it start to finish: business-day arithmetic on Temporal.PlainDate. It’s the kind of thing you’d otherwise hand-roll with a weekday check and a holiday list, and getting it slightly wrong is easy (off-by-one at month boundaries, forgetting a holiday falls on a weekend and observance shifts).
Takes about 5 minutes.
1. Install
Section titled “1. Install”npm install @johnhenry/temporals temporal-polyfillTemporal isn’t in every JS runtime yet, so temporal-polyfill is a required peer dependency until it is. @johnhenry/temporals builds entirely on the standard Temporal API — nothing proprietary underneath.
2. Create the file
Section titled “2. Create the file”Create business-days.mjs:
import "temporal-polyfill/global";import { BusinessCalendar, usFederalHolidays } from "@johnhenry/temporals/business";
const D = (s) => Temporal.PlainDate.from(s);
// A calendar that knows weekends AND US federal holidays.const cal = new BusinessCalendar({ holidays: usFederalHolidays() });
console.log("Is 2026-01-01 a business day?", cal.isBusinessDay(D("2026-01-01")));console.log("Add 5 business days to 2026-01-02:", cal.addBusinessDays(D("2026-01-02"), 5).toString());console.log("Business days in Jan 2026:", cal.businessDaysBetween(D("2026-01-01"), D("2026-02-01")));3. Run it
Section titled “3. Run it”node business-days.mjsYou should see:
Is 2026-01-01 a business day? falseAdd 5 business days to 2026-01-02: 2026-01-09Business days in Jan 2026: 202026-01-01 is a Thursday, but it’s New Year’s Day, so isBusinessDay correctly says false — that’s the holiday calendar working, not just a weekday check. 2026-01-02 (Friday) plus 5 business days skips the weekend and lands on 2026-01-09 (the following Friday). And January 2026 has 20 business days once weekends and New Year’s Day are excluded.
What just happened
Section titled “What just happened”usFederalHolidays()returns the real US federal holiday rule set (including holidays whose date depends on the calendar, like the third Monday of a given month) —BusinessCalendarcombines that with ordinary weekend rules, soisBusinessDay/addBusinessDays/businessDaysBetweenall account for both in one call.- Every value here is a real
Temporal.PlainDate—D("2026-01-01")isTemporal.PlainDate.from("2026-01-01"), not a proprietary date type.@johnhenry/temporalsadds vocabulary on top of the standardTemporalAPI rather than replacing it. addBusinessDaysandbusinessDaysBetweenare the two operations most hand-rolled business-day code gets subtly wrong at edges (a holiday landing on a weekend, a range boundary) — this is the same logic the library’s own test suite exercises.
Where to go next
Section titled “Where to go next”- Business time — the fuller picture: working hours, business duration across a working-hours boundary, and multi-timezone meeting-slot finding (
meetingSlots) built on the sameBusinessCalendar. - temporals overview —
range,recur(RRULE),cron, andInterval/IntervalSetset algebra, if business days aren’t the piece you need. temporals’s ownexamples/—business.mjsis the fuller version of this tutorial (working hours, overnight shifts, multi-zone availability);recur.mjs,cron.mjs, andintervals.mjscover the rest of the library the same way.