Parsing Date and Time
GMT’s parse functions accept ISO 8601 strings and common wire formats, returning
plain or zoned components. They never throw — invalid input yields an empty string
or null.
Mistakes
Section titled “Mistakes”Not handling the empty string on invalid input
parseRfc2822, parseHttpDate, and parseSqlDateTime return an empty string for invalid input and never throw. Passing the result on unchecked turns bad input into an empty value somewhere downstream.
Wrong
const result = parseRfc2822(invalidInput); // ""save({ sentAt: result }); // stores an empty timestampRight
import { parseRfc2822 } from "@northguild/gmt/zoned";
const result = parseRfc2822(invalidInput);if (result === "") {// invalid RFC 2822 input}Checking a wire format with its regex
A pattern such as rfc3339DateTime proves the shape of a string, not that its date exists. It matches 29 February in a year that has none. The validator for the format is true exactly when the parser returns a value.
Wrong
rfc3339DateTime.test("2023-02-29T10:00:00Z"); // true — but 2023 has no 29 FebruaryRight
import { isValidRfc3339DateTime } from "@northguild/gmt/zoned";
isValidRfc3339DateTime("2023-02-29T10:00:00Z"); // falseisValidRfc3339DateTime("2024-03-15T14:30:00-04:00"); // trueUsing string manipulation instead of parse functions
Splitting a date string on '-' and indexing the parts works for ISO 8601 today, but it breaks the moment your input includes a calendar annotation, a different separator, or fractional seconds.
Wrong
const [y, m, d] = dateStr.split("-"); // fragile — breaks on annotations or edge formatsRight
import { parseYearFromDate, parseMonthFromDate, parseDayFromDate } from "@northguild/gmt";
const y = parseYearFromDate(dateStr);const m = parseMonthFromDate(dateStr);const d = parseDayFromDate(dateStr);Assuming month is 1-indexed in arithmetic
parseMonthFromDate returns the 1-indexed month as a two-digit string, '01' to '12'. Adding or subtracting months on that number without a date-aware function can produce invalid month values.
Wrong
const m = parseMonthFromDate("2024-12-15"); // "12"const next = Number(m) + 1; // 13 — not a valid monthRight
import { addDate } from "@northguild/gmt";
addDate("2024-12-15", { months: 1 }); // "2025-01-15" — handles overflowConfusing getWeekOfMonth with parseWeekFromDate
getWeekOfMonth tells you which week-of-month a date falls in (1-6). parseWeekFromDate returns the ISO week number (1-53). They answer different questions and produce different numbers for the same input.
Wrong
const wom = getWeekOfMonth("2024-01-31", "en-US"); // 5// used as if it were an ISO week numberRight
import { getIsoWeekDate, parseWeekFromDate } from "@northguild/gmt";
const isoWeek = parseWeekFromDate("2024-01-31"); // 5getIsoWeekDate("2024-01-31"); // { year: 2024, week: 5, weekday: 3 } — year is the week-yearWeek number without week-year is a bug in waiting
'Wait until week 35' is ambiguous without a week-year. ISO week 35 of 2024 and week 35 of 2025 are 52 weeks apart. Always pair the week number with its week-year.
Wrong
const week = parseWeekFromDate(startDate); // 35// wait until week 35 — but which year?parseYearFromDate("2024-12-30"); // "2024" — the calendar year, but that date is in week 1 of 2025Right
import { getIsoWeekDate } from "@northguild/gmt";
getIsoWeekDate("2024-12-30"); // { year: 2025, week: 1, weekday: 1 }const { year: weekYear, week } = getIsoWeekDate(startDate);// wait until week <week> of <weekYear>Checking for null on parseRfc2822/parseHttpDate/parseSqlDateTime/parseRfc3339
These functions return an empty string for invalid input, never null. A null check never fires, so invalid input passes straight through it. Check for the empty string.
Wrong
const r = parseRfc3339(input);if (r === null) { /* never true — invalid input returns "" */ }Right
import { parseRfc3339 } from "@northguild/gmt/zoned";
const r = parseRfc3339(input);if (r === "") {// invalid input}