datetime
Date/time math capability pack using JS Date + Intl only (zero dependencies): duration breakdown between two dates, add a duration, business-day counting/adding (Mon-Fri minus holidays), ISO week...
datetime (adapter system)
Date/time math pack built purely on the JS Date + Intl built-ins (both always present in Node) — zero dependencies. Every tool takes ONE args object. Dates are accepted loosely (ISO string, epoch-ms number, or anything Date.parse handles); calendar arithmetic runs in UTC so it's deterministic and DST-agnostic.
Tools (adapters)
| tool | args | result |
|---|---|---|
durationBetween | { from, to, unit? } | { breakdown:{years,months,days,hours,minutes,seconds}, totals, negative } |
addDuration | { date, years?,months?,days?,hours?,minutes?,seconds? } | { iso, epoch } |
businessDays | { from, to, holidays? } | { businessDays, holidaysExcluded } — Mon-Fri, inclusive of both ends |
addBusinessDays | { date, days, holidays? } | { iso, epoch, date } |
weekNumber | { date } | { week, isoYear, label } — ISO-8601 week |
dayOfYear | { date } | { dayOfYear, daysInYear } |
timeAgo | { date, now? } | { phrase, unit, value, future } — e.g. "3 days ago" / "in 2 hours" |
toTimezone | { date, timeZone } | { wallClock, parts, formatted } via Intl in that IANA zone |
format | { date, locale?, options? } | { formatted } via Intl.DateTimeFormat |
isWeekend | { date } | { isWeekend, weekday } |
isLeapYear | { year } | { isLeapYear } |
daysInMonth | { year, month } | { days } (month is 1-12) |
parse | { input } | { iso, epoch, valid, year, month, day, weekday } — tolerant |
Usage
import datetime from './index.js';
datetime.adapters.businessDays({ from: '2024-01-01', to: '2024-01-05' }); // → { businessDays: 5, ... }
datetime.adapters.timeAgo({ date: '2024-01-01', now: '2024-01-04' }); // → { phrase: '3 days ago', ... }
datetime.adapters.weekNumber({ date: '2024-01-01' }); // → { week: 1, isoYear: 2024, ... }
datetime.adapters.toTimezone({ date: '2024-06-01T12:00:00Z', timeZone: 'America/New_York' });
DRY boundary notes
- Does NOT parse interval strings like
"5m"/"2h"into milliseconds — that belongs to the
cron pack.
- Does NOT do generic ISO coercion of arbitrary/loose types — that's **a-transformation
timestamps.*. (This pack coerces inputs only as a convenience for its own math.)
- Does NOT render calendars (month grids, week layouts) — that's the
calendarpack. toTimezonereturns the wall-clock parts in the requested zone viaIntl(which carries the
real IANA tz db in Node). True raw numeric tz-offset arithmetic without a bundled tz db is out of scope here.
This pack = duration / business-day / timezone / relative-time math.