intervalOverlappingDaysZoned
Signature
Section titled “Signature”intervalOverlappingDaysZoned(aStart: string, aEnd: string, bStart: string, bEnd: string): numberimport { intervalOverlappingDaysZoned } from "@northguild/gmt/zoned/interval";Return how many distinct calendar dates two zoned intervals share, counted in the
- first interval’s zone.
- Counts the number of local dates touched by the closed intersection
[max(aStart, bStart), min(aEnd, bEnd)]— inclusive of both endpoints. aEnd,bStart, andbEndare re-expressed inaStart’s time zone before comparing — Temporal refuses to compute day-granularity differences directly across two zones, since day length varies with DST/offset changes. As a result this function is NOT commutative: swapping the two intervals can change the answer when their zones differ.- Zones whose calendar skips a date entirely (e.g.
Pacific/Apia’s 2011 dateline change) still count the skipped date — this matchesintervalCountZoned’s calendar-arithmetic rule, so the two functions never disagree about what a day is. - Adjacent intervals (e.g.
aEnd === bStart) share one date and count as1. - Returns
0when the intervals do not overlap at all (a well-defined answer, not invalid input). - Returns
nullif either interval is invalid (start > end). - Returns
nullon invalid input (wrong type, malformed strings, leap seconds). - Accepts mixed calendar systems (E7’s D4-zoned, issue #152): both bare ISO zoned strings and GMT calendar-annotated ones (
"5784-06-15T14:30:00-05:00[u-ca=hebrew][America/New_York]"), and the two endpoints need not agree on a calendar. Ordering is calendar-independent — verified thatTemporal.Instantcarries no calendar field at all and thatInstant.compare/ZonedDateTime.compareboth return0for the same instant expressed in hebrew, islamic-civil, japanese and iso8601. - Still rejects Temporal’s own
[timeZone][u-ca=...]RFC 9557 ordering, which reads GMT’s calendar-native digits as ISO digits — seeregex/calendar-zoned-date-time.ts. - Diverges from date-fns’s
getOverlappingDaysInIntervals, which rounds up elapsed 24-hour periods instead of counting calendar dates. To reproduce date-fns’s number, composeintervalIntersectionZonedwithintervalCountZoned:const span = intervalIntersectionZoned(aStart, aEnd, bStart, bEnd); span ? intervalCountZoned(span.start, span.end, "day") : 0;
Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
aStart |
string |
ISO 8601 zoned datetime string for the first interval start |
aEnd |
string |
ISO 8601 zoned datetime string for the first interval end |
bStart |
string |
ISO 8601 zoned datetime string for the second interval start |
bEnd |
string |
ISO 8601 zoned datetime string for the second interval end |
Returns
Section titled “Returns”number of shared calendar dates (counted in aStart’s zone), 0 when disjoint, or null on invalid input
Examples
Section titled “Examples”intervalOverlappingDaysZoned("2024-03-09T12:00:00-05:00[America/New_York]", "2024-03-11T12:00:00-04:00[America/New_York]", "2024-03-09T12:00:00-05:00[America/New_York]", "2024-03-11T12:00:00-04:00[America/New_York]") // 3 (spring-forward, 47 real hours)intervalOverlappingDaysZoned("2024-01-01T00:00:00+00:00[UTC]", "2024-01-02T00:00:00+00:00[UTC]", "2024-01-03T00:00:00+00:00[UTC]", "2024-01-04T00:00:00+00:00[UTC]") // 0 (disjoint)intervalOverlappingDaysZoned("invalid", "2024-06-30T23:59:59+00:00[UTC]", "2024-04-01T00:00:00+00:00[UTC]", "2024-12-31T23:59:59+00:00[UTC]") // null