Time
Timezone-aware datetime helpers built on top of native Intl.DateTimeFormat. No TZ-database vendor; operators get the IANA names Node's ICU build supports (full set on every mainstream platform).
The module covers four concerns: parsing ISO 8601 strings into Date, decomposing an instant into calendar parts in a named timezone, formatting an instant for human display, and DST-safe calendar arithmetic (addDays / addMonths / startOfDay / endOfDay / diffDays).
Every operation accepts a Date, a millisecond-epoch number, or an ISO 8601 string interchangeably. The timezone opt defaults to "UTC" and the locale opt defaults to "en-US".
Calendar arithmetic anchors on parts in the requested timezone, not on UTC milliseconds — so addDays(d, 1, { timezone: "America/New_York" }) always lands on the same wall-clock time the next civil day, even across the spring-forward / fall-back transitions.
b.time.toParts(input, opts) #
{
timezone: string, // IANA name; defaults to "UTC"
}
Decompose an instant into calendar parts as observed in a named timezone. Returns { year, month, day, hour, minute, second, millisecond, weekday: 1..7, weekdayName: "Mon".."Sun", dayOfYear }. Weekday numbering follows ISO 8601 (Monday = 1, Sunday = 7).
Accepts a Date, ms-epoch number, or ISO 8601 string. timezone defaults to "UTC".
var parts = b.time.toParts("2026-05-09T14:30:00Z", {
timezone: "America/New_York",
});
parts.year; // → 2026
parts.month; // → 5
parts.day; // → 9
parts.hour; // → 10
parts.weekdayName; // → "Sat"
parts.weekday; // → 6
parts.dayOfYear; // → 129
b.time.format(input, opts) #
{
timezone: string, // IANA name; defaults to "UTC"
locale: string, // BCP 47; defaults to "en-US"
dateStyle: string, // "full" | "long" | "medium" | "short"
timeStyle: string, // "full" | "long" | "medium" | "short"
year: string, // "numeric" | "2-digit"
month: string, // "numeric" | "2-digit" | "long" | "short" | "narrow"
day: string,
hour: string,
minute: string,
second: string,
weekday: string,
era: string,
hour12: boolean,
fractionalSecondDigits: number,
timeZoneName: string, // "long" | "short" | "shortOffset" | etc.
}
Render an instant as an operator-readable string in a named timezone and locale. Accepts the same Date | number | string input as the rest of the module. When neither dateStyle / timeStyle nor any per-field opt is supplied, defaults to dateStyle: "medium" + timeStyle: "short".
Per-field opts (year / month / day / hour / minute / second / weekday / era / hour12 / fractionalSecondDigits / timeZoneName) pass through to Intl.DateTimeFormat unchanged.
var when = "2026-05-09T14:30:00Z";
b.time.format(when, { timezone: "America/New_York" });
// → "May 9, 2026, 10:30 AM"
b.time.format(when, {
timezone: "Asia/Tokyo",
dateStyle: "full",
timeStyle: "long",
});
// → operator-readable Japanese-locale-style string
b.time.tzOffsetMs(input, timezone) #
Compute the offset in milliseconds between the named timezone's local wall-clock and UTC at the given instant. Positive east of UTC, negative west. The value depends on the instant — DST transitions are honoured automatically.
Throws TimeError when timezone is missing, non-string, or not an IANA name supported by Node's ICU build.
var offset = b.time.tzOffsetMs("2026-05-09T12:00:00Z", "America/New_York");
// → -14400000 (UTC-4 during DST; 4h * 60m * 60s * 1000ms)
var winter = b.time.tzOffsetMs("2026-01-15T12:00:00Z", "America/New_York");
// → -18000000 (UTC-5 in standard time)
b.time.startOfDay(input, opts) #
{
timezone: string, // IANA name; defaults to "UTC"
}
Return a Date pointing at midnight (00:00:00.000) of the input's civil day in the named timezone. DST-safe — the spring-forward day still resolves to the first valid wall-clock instant. Useful for day-bucketed audit queries and "is this still today?" comparisons.
var dayStart = b.time.startOfDay("2026-05-09T14:30:00Z", {
timezone: "America/New_York",
});
dayStart.toISOString();
// → "2026-05-09T04:00:00.000Z" (midnight NY = 04:00 UTC during DST)
b.time.endOfDay(input, opts) #
{
timezone: string, // IANA name; defaults to "UTC"
}
Return a Date pointing at the last representable millisecond (23:59:59.999) of the input's civil day in the named timezone. DST-safe. Pair with startOfDay to bracket "all events on day X in timezone Y" range queries.
var dayEnd = b.time.endOfDay("2026-05-09T14:30:00Z", {
timezone: "America/New_York",
});
dayEnd.toISOString();
// → "2026-05-10T03:59:59.999Z" (23:59:59.999 NY = 03:59 next-day UTC)
b.time.addDays(input, n, opts) #
{
timezone: string, // IANA name; defaults to "UTC"
}
Add n calendar days to the input, anchored on the named timezone's wall clock. Negative n subtracts. Calendar-day arithmetic — the wall-clock hour / minute / second / millisecond stay the same across DST transitions, even though the resulting UTC offset between the two instants will differ by an hour around the transition.
Throws TimeError when n is not a finite number.
var due = b.time.addDays("2026-05-09T14:30:00Z", 7, {
timezone: "America/New_York",
});
due.toISOString();
// → "2026-05-16T14:30:00.000Z"
// Subtract: "yesterday at this time"
var yesterday = b.time.addDays(Date.now(), -1, { timezone: "UTC" });
b.time.addMonths(input, n, opts) #
{
timezone: string, // IANA name; defaults to "UTC"
}
Add n calendar months to the input, anchored on the named timezone's wall clock. Negative n subtracts. End-of-month days clamp to the target month's last day — Jan 31 + 1 month is Feb 28/29, not "March 3". Wall-clock hour / minute / second / millisecond are preserved.
Throws TimeError when n is not a finite number.
var renewal = b.time.addMonths("2026-01-31T09:00:00Z", 1, {
timezone: "UTC",
});
renewal.toISOString();
// → "2026-02-28T09:00:00.000Z" (clamped: Feb has no day 31)
var nextQuarter = b.time.addMonths(Date.now(), 3, { timezone: "UTC" });
b.time.diffDays(a, b, opts) #
{
timezone: string, // IANA name; defaults to "UTC"
}
Calendar days between two instants in the named timezone, computed as startOfDay(b) - startOfDay(a) rounded to whole days. Positive when b is after a; negative otherwise. Foundation for "X days ago" / "Y days until" relative formatting.
var posted = "2026-05-02T08:00:00Z";
var now = "2026-05-09T14:30:00Z";
var ago = b.time.diffDays(posted, now, { timezone: "UTC" });
// → 7
// "X days ago" relative formatting:
var label = ago === 0 ? "today"
: ago === 1 ? "yesterday"
: ago + " days ago";
// → "7 days ago"
b.time.parseISO(s) #
Parse an ISO 8601 / RFC 3339 datetime string into a Date. Accepts YYYY-MM-DD, YYYY-MM-DDTHH:MM, YYYY-MM-DDTHH:MM:SS, optional .sss fractional seconds, and an optional trailing Z / +HH:MM / -HH:MM zone designator. A space separator between date and time is also accepted. Strings without a zone designator are interpreted as UTC.
Throws TimeError for non-strings, malformed input, or out-of-range component values (month > 12, day > 31, hour > 23, etc.).
var d = b.time.parseISO("2026-05-09T14:30:00Z");
d.toISOString(); // → "2026-05-09T14:30:00.000Z"
// Offset zone:
var withOffset = b.time.parseISO("2026-05-09T10:30:00-04:00");
withOffset.toISOString(); // → "2026-05-09T14:30:00.000Z"
// Date-only (interpreted as UTC midnight):
var date = b.time.parseISO("2026-05-09");
date.toISOString(); // → "2026-05-09T00:00:00.000Z"
b.time.toIso8601NoMs(input) #
Emit an ISO 8601 string with the trailing .sssZ milliseconds dropped — produces 2026-05-09T14:30:00Z instead of 2026-05-09T14:30:00.000Z. Used by SAS / SigV4 / log-filename builders that need a one-second-resolution timestamp string. The strip pattern lives in one place so every caller agrees on the shape.
b.time.toIso8601NoMs("2026-05-09T14:30:00.789Z");
// → "2026-05-09T14:30:00Z"
b.time.toIso8601NoMs(new Date(Date.UTC(2026, 4, 9, 14, 30, 0)));
// → "2026-05-09T14:30:00Z"
Last updated 2026-08-08T16:39:49.652Z by seeder.