Skip to content

Converting Between Types

  • The core functions, which every industry uses.

Use these functions when you need to move between representations: a plain datetime to a zoned one, a UTC string to a Unix epoch, a date in a non-Gregorian calendar.

import { convertPlainDateTimeToZoned, convertZonedToPlainDateTime } from "@northguild/gmt/zoned";
convertPlainDateTimeToZoned("2024-03-15T14:30:45", "America/New_York");
// "2024-03-15T14:30:45.000-04:00[America/New_York]"
convertZonedToPlainDateTime("2024-03-15T14:30:45[America/New_York]");
// "2024-03-15T14:30:45"

The plain-to-zoned direction accepts disambiguation for DST gap/overlap control — see Zoned Operations.

import { convertUtcToUnix } from "@northguild/gmt/utc";
import { convertUnixToUtc } from "@northguild/gmt/unix";
convertUtcToUnix("2024-03-15T14:30:45Z"); // 1710513045000 — milliseconds
convertUnixToUtc(1710513045000); // "2024-03-15T14:30:45Z"
// Seconds: pass the unit explicitly, in both directions
convertUtcToUnix("2024-03-15T14:30:45Z", { epochUnit: "seconds" }); // 1710513045
convertUnixToUtc(1710513045, { epochUnit: "seconds" }); // "2024-03-15T14:30:45Z"

To read a Unix timestamp as a calendar date, use convertUnixToPlainDate. It reads the date in UTC unless you pass { timeZone }, and it takes epochUnit like the others:

import { convertUnixToPlainDate } from "@northguild/gmt";
convertUnixToPlainDate(1710685845000, { timeZone: "UTC" });
// "2024-03-17"
convertUnixToPlainDate(1710685845000, { timeZone: "Pacific/Kiritimati" });
// "2024-03-18" — the same instant is already the next day at UTC+14
convertUnixToPlainDate(1710685845000);
// "2024-03-17" — UTC by default

convertUtcToPlainDate does the same for a UTC string. Both write the year as Temporal does: four digits from 0000 to 9999, and a sign and six digits outside that range:

import { convertUtcToPlainDate } from "@northguild/gmt";
convertUtcToPlainDate("2024-03-17T14:30:45Z"); // "2024-03-17"
convertUtcToPlainDate("+010000-01-01T00:00:00Z"); // "+010000-01-01"
convertUtcToPlainDate("-000005-01-01T00:00:00Z"); // "-000005-01-01"

Both directions above default to milliseconds and take an optional { epochUnit: "seconds" } — there are no separate …Ms functions. Name the unit whenever you store or send a value, and be consistent: mixing the two is a common source of 1000x errors.

import { convertZonedToUtc } from "@northguild/gmt/zoned";
import { convertUtcToZoned } from "@northguild/gmt/utc";
convertZonedToUtc("2024-03-15T14:30:45[America/New_York]"); // "2024-03-15T18:30:45Z"
convertUtcToZoned("2024-03-15T14:30:45Z", "America/New_York"); // "2024-03-15T10:30:45-04:00[America/New_York]"
import { convertZonedToZoned } from "@northguild/gmt/zoned";
convertZonedToZoned("2024-03-15T14:30:45[America/New_York]", "Europe/London");
// "2024-03-15T18:30:45+00:00[Europe/London]"
import { convertDateToCalendar } from "@northguild/gmt/plain";
convertDateToCalendar("2024-10-03", "hebrew");
// "2024-10-03[u-ca=hebrew]"
convertDateToCalendar("2024-10-03", "japanese");
// "2024-10-03[u-ca=japanese]"

The string is the RFC 9557 form Temporal.PlainDate.prototype.toString() writes: the ISO digits, then a [u-ca=<id>] annotation naming the calendar. Calendar fields such as the Hebrew year or the Japanese era are read values, never string content. Convert with convertDateToCalendar(value, "iso8601") to get back to a bare ISO string.

For zoned values, use convertZonedToCalendar (zoned namespace) — it keeps the instant, offset, and IANA zone unchanged. See Calendar Systems for the full calendar-aware arithmetic story.