Date Comparison
Comparison functions in GMT are string-in, string-out. They never throw — invalid
input yields false. Knowing what false means is half the battle.
Mistakes
Section titled “Mistakes”Using string comparison for dates
Lexicographic string comparison ('2024-03-01' < '2024-02-15') works for ISO 8601 dates but breaks the moment your input includes timezones, offsets, or calendar annotations. Use isBeforeDate and isAfterDate instead.
Wrong
"2024-03-01" < "2024-02-15"; // false — string order is not date order for all formatsRight
import { isBeforeDate } from "@northguild/gmt";
isBeforeDate("2024-02-15", "2024-03-01"); // true — correct date comparisonNot handling invalid input
All comparison functions return false for invalid input. A false result means either 'not the case' or 'invalid input' — you cannot tell which without checking the inputs first.
Wrong
const r = isBeforeDate(badInput, "2024-03-15");// r is false — but was badInput invalid, or is it genuinely not before?Right
import { isValidDate, isBeforeDate } from "@northguild/gmt";
if (isValidDate(a) && isValidDate(b)) {isBeforeDate(a, b); // now false means genuinely not before}Comparing different date formats
isBeforeDate compares two plain dates. A zoned datetime string is invalid input to it, so the result is false whatever the dates are. Convert first so both inputs have the same shape.
Wrong
isBeforeDate("2024-03-14", "2024-03-15T10:00:00-04:00[America/New_York]"); // false — the zoned string is invalid inputRight
import { isBeforeDate, parseDateFromZoned } from "@northguild/gmt";
isBeforeDate("2024-03-14", parseDateFromZoned("2024-03-15T10:00:00-04:00[America/New_York]"));// true — both are plain datesAssuming weekends are always Saturday/Sunday
isWeekend follows the locale's weekend definition. In Israel, the weekend is Friday-Saturday. In some Gulf states, it is Friday-Saturday or Saturday-Sunday depending on recent policy changes.
Wrong
const isWeekend = (d) => {const day = new Date(d).getDay();return day === 0 || day === 6; // Saturday/Sunday only — wrong for many locales};Right
import { isWeekend } from "@northguild/gmt";
isWeekend("2024-03-15", "en-US"); // falseisWeekend("2024-03-15", "he-IL"); // true — 2024-03-15 is a Friday, and he-IL's weekend is Friday–SaturdayConfusing isBusinessDay with isWeekend
isWeekend follows the locale's weekend. isBusinessDay takes no locale: it defaults to Monday–Friday with no holidays, or takes a business calendar with its own weekend and holidays. So !isWeekend(d, locale) and isBusinessDay(d) disagree wherever the locale's weekend is not Saturday–Sunday, and on every holiday.
Wrong
// assuming !isWeekend(d, locale) === isBusinessDay(d)Right
import { isWeekend, isBusinessDay } from "@northguild/gmt";
isWeekend("2024-03-15", "he-IL"); // true — FridayisBusinessDay("2024-03-15"); // true — the default calendar is Monday–FridayisBusinessDay("2024-03-15", { weekend: [5, 6], holidays: [], timeZone: "Asia/Jerusalem" }); // falseAssuming 'same month' ignores the year
'Same month' means same month and same year. March 2024 and March 2025 are different months. areDatesEqualBy with 'month' compares both the month and the year.
Wrong
areDatesEqualBy("2024-03-15", "2025-03-15", "month"); // false — different yearsRight
import { areDatesEqualBy } from "@northguild/gmt";
areDatesEqualBy("2024-03-15", "2024-03-20", "month"); // true — same month and yearAssuming isRelativeDay/isThisUnit/isPast/isFuture are timeZone-independent
The plain predicates resolve 'today' in the system time zone, and a plain date has no zone to pass. A date that is 'today' in New York is 'tomorrow' in Tokyo. When the result must not depend on the host, use the zoned variants: isZonedRelativeDay and isZonedThisUnit resolve 'today' in the value's own time zone, and isZonedPast and isZonedFuture compare instants.
Wrong
isPast("2024-03-15"); // depends on the system timezone at runtimeRight
import { isZonedPast } from "@northguild/gmt";
isZonedPast("2024-03-15T00:00:00-04:00[America/New_York]"); // compares instants — no host time zone involvedAssuming nextWeekday/previousWeekday return the input when it's already on the target day
nextWeekday on a Friday with target day 5 (Friday) returns the *next* Friday, not the input. For 'the next occurrence, including this day', pass { inclusive: true }.
Wrong
nextWeekday("2024-03-15", 5); // "2024-03-22" — even though it's already FridayRight
import { nextWeekday } from "@northguild/gmt";
nextWeekday("2024-03-15", 5, { inclusive: true }); // "2024-03-15" — already a Friday