intervalOverlappingDaysZoned
Signature
Section titled “Signature”intervalOverlappingDaysZoned(aStart: string, aEnd: string, bStart: string, bEnd: string): number | nullReturn how many distinct calendar dates two zoned intervals share, counted in the first interval’s zone.
- Counts the local dates that hold at least one instant of the half-open intersection
[max(aStart, bStart), min(aEnd, bEnd)). The end is excluded, so an intersection ending at local midnight does not touch the date that midnight starts. 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.- Each instant in the intersection contributes its own local date, and each date counts once. A date the zone deleted is not counted, because no instant has it (
Pacific/Apiaskipped 2011-12-30). A fall-back that sends the clock back into the previous date does not lose that date (America/Goose_Bayfell back at 00:01 on 2010-11-07 into 2010-11-06). - Returns
nullwhen the intersection crosses more than 10,000 zone transitions (the same cap asintervalCountZoned). - Compatibility: before 1.16.0 the count was the calendar difference of the two endpoint dates plus one, which counts a deleted date and can be 0 or 1 across a fall-back into the previous date. To get that number, with
start/endthe intersection endpoints inaStart’s zone:diffDate(parseDateFromZoned(start), parseDateFromZoned(end), "days") + 1. - Returns
0when the intersection is empty (a well-defined answer, not invalid input): when the intervals are disjoint, when they touch (e.g.aEndthe same instant asbStart), or when either is empty. - Returns
nullif either interval is invalid (start > end). - Returns
nullon invalid input (wrong type, malformed strings, leap seconds). - Accepts RFC 9557 calendar-annotated zoned strings (
"2024-02-24T14:30:00-05:00[America/New_York][u-ca=hebrew]"; E7, issue #152). All four arguments must name the same calendar (a bare string namesiso8601): the count is a day difference, so different calendars returnnull, as Temporal’suntilthrows whenCalendarEqualsis false. Before 1.16.0 the arguments could name different calendars. - 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; - Compatibility: since 1.16.0 calendar strings are RFC 9557 (ISO digits, the
[u-ca=<id>]annotation after the zone, canonical calendar ids); seeisValidCalendarZonedDateTime.
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”import { intervalOverlappingDaysZoned } from "@northguild/gmt/zoned/interval";
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)