Skip to content

diffZoned

diffZoned(value1: string, value2: string, units: keyof DurationLike | DateTimeUnit | (keyof DurationLike | DateTimeUnit)[], options?: RoundingOptions<DateTimeUnit>): number | Record<keyof DurationLike, number> | null

Return the difference between two zoned datetimes measured in the given date-time unit.

  • Uses Temporal.ZonedDateTime.until to calculate difference.
  • Follows Temporal’s DifferenceZonedDateTime: calendar units (days, weeks, months, years) are measured on the zone’s own wall clock, so a 23-hour DST day is 1 day and a month from Jan 31 follows the local date; time units (hours and smaller) are exact elapsed time.
  • Two values in different time zones (by TC39 TimeZoneEquals, so UTC equals Etc/UTC) can only be differenced in time units: a calendar largest unit returns null, because day lengths differ between zones.
  • Compatibility: before 1.16.0 both values were converted to UTC first, so calendar units were measured on the UTC clock and mixed zones were accepted. To get that value, difference the UTC instants: diffUtc(convertZonedToUtc(value1), convertZonedToUtc(value2), units).
  • Supports single unit or array of units.
  • Accepts RFC 9557 calendar-annotated zoned strings (as convertZonedToCalendar writes them; E7, issue #152). When BOTH endpoints name the same calendar, calendar units are measured in that calendar (a Hebrew leap year spans 13 months, not 12). When they name different calendars (a bare ISO string names iso8601), the result is null for every unit, hours included, as TC39 DifferenceTemporalZonedDateTime throws when CalendarEquals is false.
  • Compatibility: before 1.16.0 two different calendars were measured in ISO. To get that value, convert both to one calendar first: convertZonedToCalendar(value, "iso8601").
  • Returns null for invalid input. smallestUnit, roundingIncrement, and roundingMode control optional rounding of the result, per Temporal’s DifferenceOptions — e.g. { smallestUnit: "hour", roundingMode: "halfExpand" } rounds the difference to the nearest hour before extracting the requested unit.
  • When units is an array, smallestUnit must not be coarser than the largest unit in the array (e.g. ["days", "hours"] with smallestUnit: "week") — this combination is rejected by Temporal and returns null, same as other invalid input.
  • With an array of units, the record is the whole difference: the largest listed unit is Temporal’s largestUnit, and the amount of each unlisted unit between two listed units is carried into the next smaller listed unit, measured from the start moved by the larger listed amounts (so adding the record to the start reaches the end). Units smaller than the smallest listed unit are truncated, as for a single unit. For example, ["years", "days"] over 1 year 59 days returns { years: 1, days: 59 }. Days carried into a time unit follow the zone’s wall clock (a 23-hour DST day is 23 hours).
  • Compatibility: since 1.16.0 calendar strings are RFC 9557 (ISO digits, the [u-ca=<id>] annotation after the zone, canonical calendar ids); see isValidCalendarZonedDateTime.
ParameterTypeDescription
value1stringzoned ISO 8601 datetime string (start), optionally calendar-annotated
value2stringzoned ISO 8601 datetime string (end), optionally calendar-annotated
unitskeyof DurationLike | DateTimeUnit | (keyof DurationLike | DateTimeUnit)[]date-time unit or units to measure the difference, singular or plural ("day" or "days"); a record result keeps the plural keys

options

optional: how the difference is rounded; a non-object value (such as null) is invalid

Type: RoundingOptions.

OptionTypeDefaultDescription
smallestUnit?DateTimeUnit | PluralUnit<DateTimeUnit>None. The difference is not rounded: Temporal uses the smallest unit the values have, "day" for dates and "nanosecond" otherwise.The smallest unit kept in the difference; anything smaller is rounded into it. It may not be larger than the largest unit asked for.
roundingIncrement?number1, Temporal’s default.The step the smallest unit is rounded to, so 15 with "minute" rounds to a quarter of an hour. For a time unit it must divide the next larger unit evenly and be smaller than it (15 or 30 minutes, not 7 or 60); a date unit takes any whole number from 1 up. A non-integer is truncated first, as Temporal does, and any other value is invalid input.
roundingMode?"ceil" | "floor" | "expand" | "trunc" | "halfCeil" | "halfFloor" | "halfExpand" | "halfTrunc" | "halfEven""trunc", Temporal’s default for a difference.Which way a value between two steps goes. "trunc" rounds toward zero and "halfExpand" to the nearest step, a half going away from zero; the other modes are those of Temporal’s roundingMode option.

numeric difference in the requested unit, or null on invalid input

import { diffZoned } from "@northguild/gmt/zoned/calculate";
diffZoned("2024-02-28T14:30:00+00:00[UTC]", "2024-03-01T15:30:00+00:00[UTC]", "days") // 2
output 

zoned/calculate/diffZoned.ts