spanWallClock
Signature
Section titled “Signature”spanWallClock(start: string, end: string, unit: WallClockSpanUnit): number | nullReturn the wall-clock distance between two zoned datetime strings — calendar time, not elapsed time.
- The counterpart to
spanMs. Both are correct answers to different questions, and conflating them is the most common span bug there is: across a DST transition “one day later” and “24 hours later” are not the same moment. - Reads each endpoint’s own local wall clock and measures between them, so a calendar day is 1 day and 24 hours in every zone, including one whose offset shifted in between.
spanMsover the same pair reports the 23, 24.5 or 25 hours that actually elapsed. - Truncates toward zero, so the result is a whole count and
spanWallClock(b, a, unit)is-spanWallClock(a, b, unit). Noon Friday to 18:00 Saturday is 1 day, or 30 hours — ask forhourswhen the remainder matters. - Not a count of boundaries crossed. 23:00 to 01:00 the next calendar day is
0days, not1; that question is about local midnights, and isstartOfZoned’s to answer. - No disambiguation policy applies, because no local time is converted to an instant. The wall clock is read straight off the string with
Temporal.PlainDateTime.from. Going viaZonedDateTimewould be a local → instant → local round trip, and that round trip is lossy at exactly the DST edges this function exists to get right: an offset-less"2024-03-10T02:30:00[America/New_York]"names a wall time that never occurred, and Temporal’s defaultcompatibledisambiguation would silently advance it to03:30, turning a 24-hour answer into 23. A nonexistent or ambiguous local time is measured as written instead — for a clock-face question, the digits in the string are the answer. - Requires a bracketed IANA time zone on both endpoints, as
isValidZonedDateTimedoes — an instant string (Z) or a bare offset carries no zone whose wall clock could shift. The offset is optional, but a present one must match the zone. Leap seconds and[u-ca=...]calendar annotations are rejected;daysandhoursmean the same thing in every calendar system, so the annotation would change nothing. - The endpoints need not share a zone. When they differ, this is the distance between two local wall clocks — a flight leaving New York at 23:00 and landing in Berlin at 11:00 the next local day is 12 wall-clock hours, and 7 elapsed hours by
spanMs. - Returns
nullon invalid input, not0—0is the span between a wall time and itself.
Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
start | string | zoned ISO 8601 datetime string the span is measured from |
end | string | zoned ISO 8601 datetime string the span is measured to |
unit | WallClockSpanUnit | “days” or “hours” (or the singular “day” or “hour”) of wall-clock distance |
Returns
Section titled “Returns”whole wall-clock units, negative when start is after end, or null on invalid input
WallClockSpanUnit
Section titled “WallClockSpanUnit”Units spanWallClock measures a calendar distance in.
import type { WallClockSpanUnit } from "@northguild/gmt";"hour" | "day" | "hours" | "days"Examples
Section titled “Examples”import { spanWallClock } from "@northguild/gmt/span/calculate";
spanWallClock("2024-03-09T12:00:00-05:00[America/New_York]", "2024-03-10T12:00:00-04:00[America/New_York]", "hours") // 24 — spanMs reports 82800000 (23 hours)