Skip to main content

CalendarDate

Avoid JavaScript's Date Class

Never use JavaScript's native Date class in Psychic applications. For dates (year-month-day), always use Dream's CalendarDate. For timestamps, use DateTime. JavaScript's Date has numerous timezone and parsing issues that can cause subtle bugs. Dream's classes provide built-in math, formatting, and reliable date operations.

// ❌ DON'T DO THIS
const badDate = new Date('2024-01-15')
const badToday = new Date()

// ✅ DO THIS INSTEAD - Built-in math and formatting
import { CalendarDate, DateTime } from '@rvoh/dream'
const goodDate = CalendarDate.fromISO('2024-01-15')
const goodToday = CalendarDate.today()
const nextWeek = goodToday.plus({ weeks: 1 })
const formatted = goodDate.toFormat('MMM dd, yyyy')

Date fields in the database are returned as CalendarDate objects. CalendarDate provides a clean way to deal with dates without worrying about timezone math (though several methods accept an optional zone option when setting the CalendarDate). The name CalendarDate was chosen because Date was already taken by Javascript's time class, and we wanted to emphasize that this class deals with days as the fundamental unit of time.

Creating a CalendarDate

import { CalendarDate } from '@rvoh/dream'

// relative to today
CalendarDate.today()
CalendarDate.today({ zone: 'America/Chicago' })
CalendarDate.tomorrow()
CalendarDate.yesterday()

// from an ISO string
CalendarDate.fromISO('2024-03-02')
CalendarDate.fromISO('2024-05-05T22:43:36.032-05:00')
CalendarDate.fromISO('2024-05-05T22:43:36.032-08:00', {
zone: 'America/Chicago',
})

// from an object
CalendarDate.fromObject({ year: 2023, month: 6, day: 16 })

// from a Luxon DateTime
const dateTime = DateTime.fromISO('2024-05-05T17:53:07.397Z')
CalendarDate.fromDateTime(dateTime)

// check validity of the CalendarDate
const calendarDate = CalendarDate.fromISO('2023-02-29')
calendarDate.isValid // false

Converting from a CalendarDate

const calendarDate = CalendarDate.fromISO('2024-03-02')

// to a string
calendarDate.toISO() // '2024-03-02'
calendarDate.toISODate() // '2024-03-02'
calendarDate.toJSON() // '2024-03-02'
calendarDate.toString() // '2024-03-02'
calendarDate.toLocaleString({ month: 'short', day: 'numeric' }) // 'Mar 2'

// to a Luxon DateTime
calendarDate.toDateTime()

// to a Javascript Date
calendarDate.toJSDate()

// year/month/day parts
calendarDate.year
calendarDate.month
calendarDate.day

Date math

const calendarDate = CalendarDate.fromISO('2024-03-02')
const otherCalendarDate = CalendarDate.fromISO('2024-02-27')

calendarDate.plus({ days: 4 })
calendarDate.minus({ days: 4 })

CalendarDate.max(calendarDate, otherCalendarDate)
CalendarDate.min(calendarDate, otherCalendarDate)

calendarDate.diff(otherCalendarDate, 'days') // 4
otherCalendarDate.diff(calendarDate, 'days') // -4
calendarDate.diffNow('days')

calendarDate > otherCalendarDate // true
calendarDate < otherCalendarDate // false
calendarDate.equals(otherCalendarDate) // false