Duration
Durations in GMT can be ISO 8601 strings, unit objects, or normalized arrays. Confusing the representations is the most common source of duration bugs.
Mistakes
Section titled “Mistakes”Confusing duration strings with unit objects
'P1Y2M' and `{ years: 1, months: 2 }` are not interchangeable. Duration strings are ISO 8601 format; unit objects are plain objects with unit keys. Passing the wrong shape to a function produces an empty string or wrong result.
Wrong
normalizeDuration({ years: 1, months: 2 }); // unit object — works for some functions
formatDuration("P1Y2M"); // string format — also works, but mixing them in the same pipeline is error-proneRight
import { normalizeDuration } from "@northguild/gmt";
// pick one representation and stick with it:
const d = normalizeDuration("P1Y2M"); // duration stringNot validating before parsing
parseDuration returns an empty string for invalid input. Feeding unvalidated user input straight into duration arithmetic produces silent failures.
Wrong
const d = parseDuration(userInput); // userInput = "PX" → "" — no error thrownRight
import { isValidDuration, parseDuration } from "@northguild/gmt";
if (isValidDuration(userInput)) {
const d = parseDuration(userInput);
}Expecting a best-effort answer for calendar units without relativeTo
Converting a calendar-unit duration (years, months) to days requires a reference date. Without `relativeTo`, the conversion is ambiguous — different months have different lengths.
Wrong
diffDateAsDuration("2024-02-01", "2024-03-01", { unit: "days" });
// 28 or 29 days depending on leap year — but without relativeTo, which month?Right
import { diffDateAsDuration } from "@northguild/gmt";
diffDateAsDuration("2024-02-01", "2024-03-01", { unit: "days", relativeTo: "2024-02-01" });
// 29 days — February 2024 is a leap monthReading a component with getDurationUnit when you wanted a total
getDurationUnit returns one component of a normalized duration (e.g. just the hours). If you need the total duration in a specific unit, use durationAs instead.
Wrong
const d = normalizeDuration("P1DT2H3M");
const hours = getDurationUnit(d, "hours"); // 2 — just the hours component, not the totalRight
import { normalizeDuration, durationAs } from "@northguild/gmt";
const d = normalizeDuration("P1DT2H3M");
const totalHours = durationAs(d, "hours"); // 26 — full duration convertedAssuming normalizeDuration's default is always relativeTo-free
normalizeDuration converts calendar units (years, months) to days by default, using today's date as the implicit relativeTo. If you want to preserve calendar units, pass `{ relativeTo: null }`.
Wrong
normalizeDuration("P1M"); // converts to days using today — 30 or 31 depending on the current monthRight
import { normalizeDuration } from "@northguild/gmt";
normalizeDuration("P1M", { relativeTo: null }); // preserves months — no implicit conversionExpecting formatDuration to match native Intl.DurationFormat output exactly
GMT's formatDuration produces a human-readable string with a fixed style. Intl.DurationFormat output varies by locale, unit set, and style options. They are not drop-in replacements for each other.
Wrong
// assuming formatDuration("PT1H30M") matches Intl.DurationFormatRight
import { formatDuration } from "@northguild/gmt";
formatDuration("PT1H30M"); // "1 hour 30 minutes" — GMT's stable formatPassing an array of units to a *AsDuration bridge function
durationAs takes a single unit name, not an array. Passing a list of unit names returns an empty string or the conversion for the first element only.
Wrong
durationAs(d, ["hours", "minutes"]); // wrong — expects a single unit stringRight
import { durationAs } from "@northguild/gmt";
durationAs(d, "hours"); // correct — single unit