UNPKG

@burglekitt/gmt

Version:

Temporal-based date and time utilities with timezone support and polyfill integration

45 lines (44 loc) 2.32 kB
import { getStartOfZonedUnit, getUnitSpan } from "../../internal/index.js"; import { resolveUnixIntervalPair } from "./resolveUnixIntervalPair.js"; /** * Count how many `unit` boundaries a Unix epoch interval crosses. * * - Counts local calendar boundaries touched by the half-open interval `[start, end)` — * distinct from `diffUnix`, which measures exact elapsed duration. * - The end boundary is excluded: midnight to midnight two days later counts 2 days. * - A zero-length interval counts 1 when it sits mid-unit and 0 when it sits exactly on a * unit boundary. * - Uses the system timeZone for calendar-unit boundaries (consistent with `addUnix` and * `splitIntervalByUnitUnix`), so day/week/month/year counts are host-dependent. * - Weeks start on Monday (ISO 8601). * - Accepts singular or plural units (`"day"` and `"days"` behave identically). * - Returns `null` on invalid input (non-finite/non-integer start/end, `start > end`, * unsupported unit, or invalid timeZone). * * @param start Unix epoch value (seconds or milliseconds) — interval start * @param end Unix epoch value (seconds or milliseconds) — interval end * @param unit unit string — any `DateTimeUnit` * @returns number of unit boundaries touched, or null on invalid input * * @example intervalCountUnix(0, 86400000, "hour") // 24 * @example intervalCountUnix(1704153540000, 1704153660000, "day") // 2 (23:59 to 00:01 UTC) * @example intervalCountUnix(0, 0, "hour") // 0 (zero-length, on the boundary) * @example intervalCountUnix(1800000, 1800000, "hour") // 1 (zero-length, mid-hour) * @example intervalCountUnix(86400000, 0, "hour") // null * @example intervalCountUnix(NaN, 86400000, "hour") // null */ export function intervalCountUnix(start, end, unit) { const resolved = resolveUnixIntervalPair(start, end, unit); if (!resolved) return null; try { const { startVal, endVal, resolvedUnit } = resolved; const startOfStart = getStartOfZonedUnit(startVal, resolvedUnit); const startOfEnd = getStartOfZonedUnit(endVal, resolvedUnit); const spanned = getUnitSpan(startOfStart.until(startOfEnd, { largestUnit: resolvedUnit }), resolvedUnit); return spanned + (startOfEnd.equals(endVal) ? 0 : 1); } catch { return null; } }