Skip to content

diffDateAsDuration

diffDateAsDuration(date1: string, date2: string, unit: "years" | "months" | "weeks" | "days" | DateUnit, options?: (RoundingOptions<DateUnit> & DurationStringOptions)): string

Return the difference between two PlainDate values as an ISO 8601 duration string, bridging to the duration namespace (see parseDuration, normalizeDuration).

  • Returns "" for invalid inputs (negative diffs are valid and render with a leading -).
  • Uses Temporal’s until semantics with largestUnit set to unit (TC39 CalendarDateUntil; for non-ISO calendars the Intl era/monthCode proposal’s NonISODateUntil), then .toString().
  • Accepts RFC 9557 calendar-annotated PlainDate strings. Same calendar rule as diffDate (see its JSDoc): measured in the shared calendar when date1 and date2 name the same calendar, "" when they name different calendars (TC39 CalendarEquals; before 1.16.0 measured in ISO).
  • Unlike diffDate, unit is a single unit (not an array) — an ISO duration string already expresses a full multi-unit breakdown via largestUnit alone, so there’s no array-of-units overload here. smallestUnit, roundingIncrement, and roundingMode control optional rounding of the underlying difference before it’s rendered, per Temporal’s DifferenceOptions — same as diffDate. toStringSmallestUnit, fractionalSecondDigits, and toStringRoundingMode control the precision of the rendered string itself, per Temporal’s ToStringPrecisionOptions (mirroring parseDuration’s options) — kept separate from the .until() rounding options above because both option sets have colliding smallestUnit/roundingMode keys with different Temporal types.
  • Compatibility: since 1.16.0 calendar strings are RFC 9557 (ISO digits, [u-ca=<id>], canonical calendar ids); see isValidCalendarDate.
ParameterTypeDescription
date1stringISO PlainDate string for the start, optionally calendar-annotated
date2stringISO PlainDate string for the end, optionally calendar-annotated
unit"years" | "months" | "weeks" | "days" | DateUnitdate unit, singular or plural ("day" or "days"), to use as the duration’s largestUnit

options

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

OptionTypeDefaultDescription
smallestUnit?DateUnit | PluralUnit<DateUnit>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.
toStringSmallestUnit?SmallestUnit<"minute" | "second" | "millisecond" | "microsecond" | "nanosecond">None. The precision comes from fractionalSecondDigits.The smallest unit written in the string: "second", "millisecond", "microsecond" or "nanosecond". It sets how many fractional-second digits appear and takes precedence over fractionalSecondDigits. "minute" is refused, as Temporal.Duration refuses it.
fractionalSecondDigits?0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | "auto" | 8 | 9"auto", Temporal’s default.The number of fractional-second digits written: 0 to 9 writes exactly that many, and "auto" writes as many as the duration needs, with no trailing zeros. It has no effect when toStringSmallestUnit is given.
toStringRoundingMode?RoundingMode"trunc", Temporal’s default.How the duration is rounded when the precision asked for drops digits. "trunc" cuts them off; "halfExpand" rounds to the nearest value, a half going away from zero.

ISO 8601 duration string, or "" on invalid input

import { diffDateAsDuration } from "@northguild/gmt/plain/calculate";
diffDateAsDuration("2024-03-10", "2024-04-05", "days") // "P26D"
output 

plain/calculate/diffDateAsDuration.ts