Skip to content

diffUnix

diffUnix(value1: string | number, value2: string | number, units: keyof DurationLike | DateTimeUnit | (keyof DurationLike | DateTimeUnit)[], options?: ({ epochUnit?: UnixUnit; timeZone?: string; } & RoundingOptions<DateTimeUnit>)): number | Record<keyof DurationLike, number> | null

Return the difference between two Unix timestamps measured in the given unit.

  • Converts both epochs to a Temporal.ZonedDateTime in timeZone and uses its until(), so calendar units (days, weeks, months, years) are measured on that zone’s wall clock — a 23-hour DST day is 1 day — while time units (hours and smaller) are exact elapsed time. Temporal.Instant.until() is not used: it rejects every calendar largestUnit.
  • Supports single unit or array of units.
  • 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 wall clock of timeZone (a 23-hour DST day is 23 hours).
  • Nanosecond precision: the result is a JavaScript number, so past about 104 days a nanosecond count exceeds Number.MAX_SAFE_INTEGER. Every value this function can return is still exact — its inputs are whole milliseconds or seconds — but it is no longer a safe integer, so arithmetic on it silently loses nanoseconds: diffUnix(0, 9072000000, "nanoseconds") returns 9072000000000000, and adding 1 to that gives the same number back. For an exact count use the bigint APIs: spanNs in span/, or toNanoseconds in precision/.
  • Each value is a safe integer or a digit string ("1706659200000"); anything else is invalid.
  • Unit names may be singular or plural ("day" or "days"), as in Temporal; a record result keeps the plural keys.
  • Limit at an offset with seconds. The instant is placed in the offset’s whole-minute zone, moved by its seconds, and the moved instant must be inside Temporal’s range. So within the offset’s seconds (under a minute) of the last instant Temporal supports (+275760-09-13T00:00:00Z) for an offset east of UTC, or of the first (-271821-04-20T00:00:00Z) for one west, this returns null. An offset to the minute has no such limit.
ParameterTypeDescription
value1string | numberfirst Unix epoch: a safe integer, or a string of optionally negative ASCII digits
value2string | numbersecond Unix epoch, in the same form and unit
unitskeyof DurationLike | DateTimeUnit | (keyof DurationLike | DateTimeUnit)[]DateTimeDurationUnit | DateTimeDurationUnit[] to measure the difference

options

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

OptionTypeDefaultDescription
epochUnit?"seconds" | "milliseconds" | "second" | "millisecond" (UnixUnit)"milliseconds"The unit the epoch values are counted in: "seconds" or "milliseconds", singular or plural. Any other value returns null.
timeZone?string"UTC"The time zone calendar units are measured in: an IANA name, a UTC offset (a time zone identifier such as +05:30, +0530 or -08, or a stored offset ±HH:MM[:SS], what getTimeZoneOffset returns), or "local" for the system time zone. An unknown zone returns null.
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 { diffUnix } from "@northguild/gmt/unix/calculate";
diffUnix(1706745600000, 1706659200000, "days", { timeZone: "UTC" }) // -1 (measured from the first value to the second)
output 

unix/calculate/diffUnix.ts