Skip to content

normalizeDuration

normalizeDuration(value: string, options?: { largestUnit?: LargestUnit<DateTimeUnit>; smallestUnit?: SmallestUnit<DateTimeUnit>; roundingIncrement?: number; roundingMode?: RoundingMode; relativeTo?: DurationRelativeTo; }): string

Roll an ISO 8601 duration string’s small units into larger ones.

  • Uses Temporal.Duration.from and .round to rebalance, then .toString() to re-emit.
  • With no options, units are promoted only up to a unit already present: “PT90M” stays “PT90M”, but “P1DT25H” becomes “P2DT1H” and “PT1H90M” becomes “PT2H30M”. Pass an explicit largestUnit to promote further.
  • A zoned relativeTo string resolves its wall time with disambiguation “compatible” and offset “reject”, as Temporal does: an ambiguous wall time takes the earlier instant, a nonexistent one the later instant, and an offset that does not match the zone returns "". Pass an explicit offset to pick the other reading of an ambiguous wall time.
  • A relativeTo string is ISO 8601 extended format before its first [: a date, a date-time, or with a time zone annotation a zoned date-time (<date>T<time>, then nothing, Z or ±HH:MM). Basic format ("20240101"), a space or lower-case t separator, a lower-case z, a UTC offset without a zone and a zoned date without a time are invalid.
  • A relativeTo string takes a calendar in RFC 9557 form, as convertDateToCalendar and convertZonedToCalendar write it: ISO digits and a [u-ca=<id>] annotation, after the zone for a zoned string ("2024-02-24[u-ca=hebrew]", "2024-02-24T00:00:00-05:00[America/New_York][u-ca=hebrew]"). The annotations are read as Temporal reads them: the critical flag and the id’s letter case are accepted, elective unknown annotations are ignored, the first u-ca names the calendar, and a string with a time zone annotation is zoned. An unknown critical annotation, a critical duplicate calendar, a calendar before the zone, an unsupported calendar and a leap second in any spelling return "". Compatibility: before 1.16.0 the digits were read as the calendar’s own year, month and day.
  • Returns "" for invalid input: non-string value, invalid duration string, or invalid relativeTo.
ParameterTypeDescription
valuestringISO 8601 duration string

options

The units to balance between, the rounding, and the anchor for calendar units, as Temporal’s Duration.round takes them

OptionTypeDefaultDescription
largestUnit?DateTimeUnit | "auto" | PluralUnit<DateTimeUnit>"auto"The largest unit the result may carry; smaller units are rolled up into it. "auto" is the larger of smallestUnit and the duration’s own largest nonzero unit, so nothing is promoted past a unit already present.
smallestUnit?DateTimeUnit | PluralUnit<DateTimeUnit>"nanosecond", Temporal’s default.The smallest unit the result may carry; anything smaller is rounded into it.
roundingIncrement?number1, Temporal’s default.The step smallestUnit is rounded to. It must evenly divide, and be less than, 24 for hour, 60 for minute and second, and 1000 for the sub-second units. For year, month, week and day it has no maximum, but an increment above 1 is rejected unless largestUnit is that same unit; an invalid increment returns "".
roundingMode?"ceil" | "floor" | "expand" | "trunc" | "halfCeil" | "halfFloor" | "halfExpand" | "halfTrunc" | "halfEven""halfExpand", Temporal’s default.Which way a value between two steps goes when smallestUnit or roundingIncrement rounds the duration. "halfExpand" rounds to the nearest step, a half going away from zero, and "trunc" rounds toward zero.
relativeTo?DurationRelativeToNone. Days are 24 hours, and a duration or unit that involves a year, month or week returns "".The date or zoned date-time the duration is measured from. It is required whenever a year, month or week is involved, as largestUnit or smallestUnit or as a nonzero field of the duration, even under the "auto" default.

rebalanced ISO 8601 duration string, or "" on invalid input

import { normalizeDuration } from "@northguild/gmt/duration/normalize";
normalizeDuration("PT90M", { largestUnit: "hour" }) // "PT1H30M"
output 

duration/normalize/normalizeDuration.ts