dwellTime
Signature
Section titled “Signature”dwellTime(entry: string, exit: string, targetZone?: string): Dwell | nullMeasure how long something sat somewhere, and how many local calendar days it sat there.
- Terminals, depots, yards, stations, gates and berths all charge dwell, and none of them charge by elapsed hours. They count the local calendar days the thing was present, so a container that gates in at 23:00 and out at 01:00 has been there two hours and two days.
dwellTimereturns both, and is the one “local days crossed” primitive in the library: free time and demurrage (INT-12), laytime day counts (MAR-19) and hospital length of stay all take their day boundary from here rather than each deciding what a midnight is. durationis exact elapsed time. A dwell spanning a DST transition reports the hours that actually elapsed; the local wall clocks at either end can be an hour apart from that. Hours is the largest unit, so the value never depends on a calendar.calendarDaysis notdurationrounded up. It is the number of distinct local dates intargetZonethat the half-open interval[entry, exit)touches: entry and exit on the same local date is1, across one local midnight is2, and so on. A dwell that ends exactly at a local midnight does not touch the new day, because the exit instant itself is excluded — the same half-open rule asbucketRangeand CORE-6’s intervals. A zero-length dwell touches one date. The count walks the zone’s real transitions: between two of them the wall clock runs forward without a break, so each stretch touches every date from its first instant to its last, and the count is the size of the union of those dates. A 23- or 25-hour local day is one day, not 0.96 or 1.04 of one; a date the zone deleted is never touched (Pacific/Apiaskipped 2011-12-30); and a date the clock falls back into is still one date (America/Goose_Bayfell back from 00:01 on 7 November 2010 into the 6th).- The zone decides the count, so it has to be stated.
targetZoneis used when given. Without it, the entry’s bracketed IANA zone is used. A bracketed zone is otherwise not validated: the entry’s must exist and agree with its offset only when it supplies the dwell zone, becausetargetZoneis omitted, and the exit’s never supplies it. If the entry and exit are bare instants —Zor an offset — and notargetZoneis given, the result isnull: an offset is not a zone (CORE-4), and a day count in an unstated locality would be a guess. - The offset fixes each instant; a bracketed zone only resolves a rounded one. An offset written to the minute that is the bracketed zone’s sub-minute offset rounded (
-00:45[Africa/Monrovia], for −00:44:30) names the instant the zone gives, asTemporal.ZonedDateTime.fromreads it, on the entry and the exit alike. A zone that does not exist, or that disagrees with the offset, changes nothing. enterandexitare the two instants rendered in the dwell zone, so a charging record shows the local times the terminal’s own clock showed.targetZoneis whateverisValidTimeZoneaccepts, which is what Temporal accepts: an IANA identifier, or a fixed offset such as"+02:00", asetaAtZonealso takes. Days are then counted in that offset, which observes no DST, so pass the place’s IANA zone when there is one.- GMT does not resolve a port, terminal or station code to a zone; the caller supplies the identifier.
- Long dwells stay cheap: the walk visits zone transitions, not days. A dwell that crosses more than 10,000 transitions (about 5,000 years of twice-yearly DST) returns
null. - Returns
nullwhen either instant is invalid, whenexitis beforeentry(an inverted dwell is a data error, not a negative stay), or when no zone can be determined. - An offset with seconds (
-00:44:30) returnsnull. A written zone cannot carry seconds (RFC 9557 §4.1), so the result could not name it. Pass the IANA name, or callfromOffsetInstant({ instant, offset })for the local time with its full offset and no bracket.
Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
entry | string | ISO 8601 zoned datetime or instant string of the gate-in, arrival or admission |
exit | string | ISO 8601 zoned datetime or instant string of the gate-out, departure or discharge |
targetZone | string | IANA name or a UTC offset to the minute (what isValidTimeZone accepts) the days are counted in; defaults to entry’s bracketed zone |
Returns
Section titled “Returns”exact duration, zone-local entry and exit, and the local calendar days touched, or null on invalid input
What dwellTime returns: exact elapsed time plus the local view every charging regime counts in.
import type { Dwell } from "@northguild/gmt";| Member | Type | Description |
|---|---|---|
duration | string | The exact elapsed time from entry to exit, as an ISO 8601 duration with hours as the largest unit. |
enter | string | The entry, rendered in the dwell zone. |
exit | string | The exit, rendered in the dwell zone. |
calendarDays | number | The number of distinct local calendar dates the dwell touched, counted half-open at the exit. |
Examples
Section titled “Examples”import { dwellTime } from "@northguild/gmt/transport/calculate";
dwellTime("2024-06-15T23:00:00-04:00[America/New_York]", "2024-06-16T01:00:00-04:00[America/New_York]") // { duration: "PT2H", enter: "2024-06-15T23:00:00-04:00[America/New_York]", exit: "2024-06-16T01:00:00-04:00[America/New_York]", calendarDays: 2 }