Skip to content

Date Validation

  • The core functions, which every industry uses.

GMT’s validation functions return booleans. They never throw — invalid input yields false. The ambiguity of false (invalid vs. genuinely not-the-case) is the core mistake.

HIGH

Not validating before parsing

Feeding an unvalidated user input string into parseYearFromDate or any other parser produces an empty string or null silently. Validate first, then parse.

Wrong

const year = parseYearFromDate(userInput); // "not-a-date" → ""

Right

import { isValidDate, parseYearFromDate } from "@northguild/gmt";
if (isValidDate(userInput)) {
const year = parseYearFromDate(userInput); // safe — input is known-valid
}
HIGH

Not validating timezone before use

Passing an invalid IANA timezone to getZonedNow or any zoned function returns an empty string. Always validate the timezone with isValidTimeZone first.

Wrong

getZonedNow("not-a-zone"); // ""

Right

import { isValidTimeZone, getZonedNow } from "@northguild/gmt/zoned";
if (isValidTimeZone(tz)) {
getZonedNow(tz); // safe
}
MEDIUM

Using try-catch for validation

GMT functions never throw — they return sentinel values. A try-catch block around a GMT call will never fire, giving a false sense of safety.

Wrong

try {
const r = parseRfc3339(input); // never throws
} catch (e) {
// never reached
}

Right

import { parseRfc3339 } from "@northguild/gmt/zoned";
const r = parseRfc3339(input);
if (r === "") {
// handle invalid input
}
MEDIUM

Confusing range validators with interval validators

isValidDateRange takes one object, { value1, value2 }, and by default requires value1 strictly before value2 (pass options: { allowEqual: true } to accept equal dates). isValidDateInterval takes two positional dates and accepts start === end, an empty interval. Neither takes a range string. They are not interchangeable.

Wrong

isValidDateRange("2024-03-15/2024-03-20"); // false — not a range string
isValidDateInterval({ start: "2024-03-15", end: "2024-03-20" }); // false — not an object

Right

import { isValidDateRange, isValidDateInterval } from "@northguild/gmt";
isValidDateRange({ value1: "2024-03-15", value2: "2024-03-20" }); // true
isValidDateInterval("2024-03-15", "2024-03-20"); // true
isValidDateRange({ value1: "2024-03-15", value2: "2024-03-15" }); // false — equal dates need allowEqual
isValidDateInterval("2024-03-15", "2024-03-15"); // true — an interval may be empty
MEDIUM

Assuming intervals accept reversed bounds

isValidDateInterval returns false when start > end. GMT intervals do not auto-normalize reversed bounds — fix the order before validation.

Wrong

isValidDateInterval("2024-03-20", "2024-03-15"); // false — start > end

Right

import { isValidDateInterval } from "@northguild/gmt";
isValidDateInterval("2024-03-15", "2024-03-20"); // true — correct order