Validation
GMT’s public functions never throw on invalid input — they return a sentinel. But when you need to reject invalid input at a system boundary (a form, an API parameter, a config file), use these validators to check first.
Scalar validation
Section titled “Scalar validation”import { isValidDate, isValidTime, isValidDateTime } from "@northguild/gmt";
isValidDate("2024-03-15"); // trueisValidDate("2024-02-30"); // false — invalid dayisValidTime("14:30:45"); // trueisValidTime("25:00:00"); // false — invalid hourisValidDateTime("2024-03-15T14:30:45"); // trueTimezone and zoned-datetime validation
Section titled “Timezone and zoned-datetime validation”import { isValidTimeZone, isValidZonedDateTime } from "@northguild/gmt/zoned";
isValidTimeZone("America/New_York"); // trueisValidTimeZone("Invalid/Zone"); // false
isValidZonedDateTime("2024-03-15T14:30:45[America/New_York]"); // trueisValidZonedDateTime("2024-02-30T14:30:45[America/New_York]"); // falseisValidZonedDateTime accepts [u-ca=iso8601] and rejects any other calendar annotation,
so a function that has not opted in to calendars fails closed. To check a value that carries
a calendar, use isValidCalendarZonedDateTime. The calendar annotation must follow the zone:
import { isValidCalendarZonedDateTime, isValidUtc } from "@northguild/gmt";
isValidCalendarZonedDateTime("2024-02-24T14:30:00-05:00[America/New_York][u-ca=hebrew]"); // trueisValidCalendarZonedDateTime("2024-02-24T14:30:00-05:00[u-ca=hebrew][America/New_York]"); // false — the zone comes first
isValidUtc("2024-01-01T00:00:00Z[u-ca=hebrew]"); // true — a UTC string's calendar annotation is ignoredSee Calendar Systems for the rules on calendar annotations.
UTC timestamps for other readers
Section titled “UTC timestamps for other readers”isValidUtc is true for a UTC instant in ISO 8601 extended form with an upper-case T and
Z. That includes four forms outside RFC 3339, which other readers do not all take: a time
without seconds, a comma before the fraction, an expanded ±YYYYYY year and an RFC 9557
annotation. When the string goes on to a database, a JSON client or any reader that is not
Temporal, check it with isValidUtcTimestamp:
import { isValidUtc, isValidUtcTimestamp } from "@northguild/gmt";
isValidUtcTimestamp("2026-10-06T12:00:00Z"); // trueisValidUtcTimestamp("2026-10-06T12:00:00.123456789Z"); // true
isValidUtc("2026-10-06T12:00:00Z[Europe/Paris]"); // trueisValidUtcTimestamp("2026-10-06T12:00:00Z[Europe/Paris]"); // false — the annotationisValidUtcTimestamp("2026-10-06T12:00:00,5Z"); // false — comma before the fractionisValidUtcTimestamp("-005000-01-01T00:00:00Z"); // false — expanded yearisValidUtcTimestamp("2026-10-06T12:00Z"); // false — no secondsisValidUtcTimestamp("2026-02-30T00:00:00Z"); // false — February has no 30thIt accepts one spelling of the RFC 3339 date-time: a four-digit year, an upper-case T,
seconds, an optional fraction of one to nine digits, and an upper-case Z with nothing after
it. A reader may still refuse or round a string that is true here: PostgreSQL has no year
0000 and keeps microseconds. See Nanosecond Precision. To accept
the other RFC 3339 spellings, numeric offsets included, use isValidRfc3339DateTime.
Daylight saving time
Section titled “Daylight saving time”import { hasDaylightSaving, getDstTransitions } from "@northguild/gmt/zoned";
hasDaylightSaving("America/New_York", { at: "2024-01-15T12:00:00Z" }); // truehasDaylightSaving("Asia/Tokyo", { at: "2024-01-15T12:00:00Z" }); // false
getDstTransitions("America/New_York", 2024);// [// { instant: "2024-03-10T07:00:00Z", offsetBefore: "-05:00", offsetAfter: "-04:00" },// { instant: "2024-11-03T06:00:00Z", offsetBefore: "-04:00", offsetAfter: "-05:00" }// ]
getDstTransitions("Asia/Tokyo", 2024); // [] — no transitionsgetDstTransitions("Invalid/Zone", 2024); // [] — invalid inputhasDaylightSaving is true when the zone is in daylight time at at, or a daylight period
begins less than 365 days after it. An invalid zone, an invalid at and a fixed offset
return false:
import { hasDaylightSaving } from "@northguild/gmt/zoned";
hasDaylightSaving("Invalid/Zone", { at: "2024-01-15T12:00:00Z" }); // falseat is an ISO 8601 instant string. With it, the answer does not depend on the day the code
runs. Without it, the reference is the current instant. See
Zoned Operations
for the rule behind both functions.
Named machine format validators
Section titled “Named machine format validators”Each fixed interchange format has a validator that is true exactly when its parser returns
a value. A pattern proves the shape alone:
import { isValidHttpDate, isValidRfc2822DateTime, isValidRfc3339DateTime, isValidSqlDateTime,} from "@northguild/gmt";
isValidRfc3339DateTime("2023-02-29T10:00:00Z"); // false — 2023 has no 29 FebruaryisValidRfc2822DateTime("Sat, 15 Mar 2024 14:30:00 -0400"); // false — a FridayisValidHttpDate("Sun Nov 6 08:49:37 1994"); // true — asctime-dateisValidHttpDate("Fri, 15 Mar 2024 24:00:00 GMT"); // false — hour 24isValidSqlDateTime("2024-03-15 14:30:00"); // trueSee Parsing for the formats themselves.
Duration-unit validation
Section titled “Duration-unit validation”import { isValidDateUnit, isValidTimeUnit } from "@northguild/gmt";
isValidDateUnit("day"); // trueisValidTimeUnit("hour"); // trueisValidDateUnit("invalid"); // falseInterval validation (positional args, start ≤ end)
Section titled “Interval validation (positional args, start ≤ end)”import { isValidDateInterval, isValidTimeInterval, isValidDateTimeInterval,} from "@northguild/gmt";
isValidDateInterval("2024-01-01", "2024-12-31"); // trueisValidDateInterval("2024-12-31", "2024-01-01"); // false — start > endisValidTimeInterval("09:00:00", "17:00:00"); // trueisValidDateTimeInterval("2024-01-01T10:00:00", "2024-12-31T23:59:59"); // trueThere are isValidUtcInterval, isValidUnixInterval, and isValidZonedInterval
siblings. isValidZonedInterval takes two zoned datetimes:
import { isValidZonedInterval } from "@northguild/gmt";
isValidZonedInterval("2024-01-01T10:00:00+00:00[UTC]", "2024-12-31T23:59:59+00:00[UTC]"); // trueisValidZonedInterval("2024-12-31T10:00:00+00:00[UTC]", "2024-01-01T10:00:00+00:00[UTC]"); // false — start > endAll return false on invalid input: a wrong type, a malformed string, a leap second, an
inverted interval, mixed kinds for the plain interval validators, or an epoch outside the
unix/ grammar (not a safe integer or a digit string). An interval whose start equals its
end is valid: it is empty.
Range validation (object params)
Section titled “Range validation (object params)”Range validators take { value1, value2, options? } — a different shape from the
interval validators above:
import { isValidDateRange, isValidTimeRange, isValidZonedRange } from "@northguild/gmt";
isValidDateRange({ value1: "2024-01-01", value2: "2024-12-31" }); // trueisValidTimeRange({ value1: "09:00:00", value2: "17:00:00" }); // trueisValidZonedRange({ value1: "2024-01-01T10:00:00+00:00[UTC]", value2: "2024-12-31T23:59:59+00:00[UTC]",}); // trueA range requires value1 strictly before value2. Pass options: { allowEqual: true } to
accept two equal values:
isValidTimeRange({ value1: "12:00:00", value2: "12:00:00" }); // false — equal values are not a rangeisValidTimeRange({ value1: "12:00:00", value2: "12:00:00", options: { allowEqual: true } }); // trueThe other range validators (isValidDateTimeRange, isValidUtcRange, isValidUnixRange)
take the same object, and isValidDateRange and isValidZonedRange accept allowEqual too.
Don’t confuse the two: isValidDateInterval takes positional (start, end) args;
isValidDateRange takes an object { value1, value2 }.
See also
Section titled “See also”- Parsing — extracting components from validated strings
- Intervals — containment, overlap, and set operations on validated ranges
isValidDatereferenceisValidTimeZonereferenceisValidUtcTimestampreferencehasDaylightSavingreference