website is under construction
Standard Library

Date

import "ghost:date"
import { now, format } from "ghost:date"

The date module works with instants in time.

Two things shape the whole module:

Every date is immutable. Nothing here changes a date in place. Every function takes a date and returns a new one, which is why the operations are functions in this module rather than methods on the value.

Every date is UTC. Ghost does not model time zones at all, so a date built once compares the same everywhere the program runs.

import "ghost:date"

launch = date.of(2024, 1, 31)

console.log(date.format(launch, "EEEE, MMMM d, yyyy"))
// >> Wednesday, January 31, 2024

console.log(date.format(date.addMonths(launch, 1), "yyyy-MM-dd"))
// >> 2024-02-29

A date's own toString() gives ISO-8601, which is also what printing one shows:

console.log(date.of(2024, 1, 31))
// >> 2024-01-31T00:00:00Z

Comparing dates

Dates support ==, !=, <, <=, >, and >= directly, comparing instants:

if (date.now() > deadline) {
  console.log("late")
}

Arithmetic operators do not work on dates — a + b on two dates is a type error. Use addDays() and the rest below.

Building and converting

MethodWhat it does
now()The current instant.
today()Midnight UTC today.
of(year, month, day, [hour, minute, second])A date from its parts. The month is 1–12.
parseISO(text)Parses RFC3339, or a bare YYYY-MM-DD.
fromUnix(seconds)A date from a Unix timestamp.
toUnix(date)Seconds since the Unix epoch.
toUnixNano(date)Nanoseconds since the Unix epoch.
format(date, pattern)The date as a string — see Formatting.

An out-of-range day, hour, minute, or second given to of() is a value error rather than silently rolling into the next period.

console.log(date.toUnix(date.of(2024, 1, 31)))
// >> 1706659200

console.log(date.parseISO("2024-03-01"))
// >> 2024-03-01T00:00:00Z

Arithmetic

Each takes a date and a count, and returns a new date.

Method
addDays(date, n) / subDays(date, n)
addWeeks(date, n) / subWeeks(date, n)
addMonths(date, n) / subMonths(date, n)
addYears(date, n) / subYears(date, n)
addHours(date, n)
addMinutes(date, n)
addSeconds(date, n)
Adding months clamps to the target month's last day rather than rolling over. January 31 plus one month is February 28 — or the 29th in a leap year — not March 2. That is almost always what a calendar-shaped calculation means.

There is no subHours, subMinutes, or subSeconds yet; pass a negative count to the matching add.

Differences

Each takes two dates and returns a whole number, truncated toward zero — so differenceInDays(a, b) is always exactly -differenceInDays(b, a).

differenceInDays(a, b), differenceInHours(a, b), differenceInMinutes(a, b), differenceInSeconds(a, b).

console.log(date.differenceInDays(date.of(2024, 3, 1), date.of(2024, 1, 31)))
// >> 30

Components

year(date), month(date), day(date), hour(date), minute(date), second(date), weekday(date).

weekday() counts from 0 for Sunday.

Predicates

isSameDay(a, b), isWeekend(date), isLeapYear(date).

Period boundaries

startOfDay(date), endOfDay(date), startOfMonth(date), endOfMonth(date).

console.log(date.endOfMonth(date.of(2024, 1, 31)))
// >> 2024-01-31T23:59:59Z

There is no startOfWeek, endOfWeek, startOfYear, or endOfYear yet.

Formatting

format(date, pattern) builds a string from pattern letters. A run of the same letter is one token, and anything else in the pattern copies through literally.

LetterMeansLonger runs
yyearyyyy2024
MmonthM1, MM01, MMMJan, MMMMJanuary
ddaypadded at two or more
Eweekdayabbreviated below four letters, full name at four or more
Hhour, 24-hour
hhour, 12-hour
mminute
ssecond
aAM/PM
d = date.of(2024, 1, 31)

date.format(d, "yyyy-MM-dd")           // '2024-01-31'
date.format(d, "EEEE, MMMM d, yyyy")   // 'Wednesday, January 31, 2024'
date.format(d, "h:mm a")               // '12:00 AM'

Pausing a program

Sleeping is not a date operation and does not live here — it belongs to the program itself. See os.sleep().