Timestamp includes helpers for calendar-style workflows without depending on a UI framework.
Date math
import { addToDate, addToDateClamped, nextDay, parseTimestamp, prevDay } from '@timestamp-js/core'
const current = parseTimestamp('2026-06-08')!
const tomorrow = nextDay(current)
const yesterday = prevDay(current)
const nextMonth = addToDate(current, { month: 1 })
const lastYear = addToDate(current, { year: -1 })
const monthEnd = parseTimestamp('2026-01-31')!
const billingDate = addToDateClamped(monthEnd, { month: 1 }) // 2026-02-28These helpers default to Gregorian. When date fields belong to another calendar, pass that calendar as the final argument where the helper accepts one, for example nextDay(timestamp, calendar), addToDate(timestamp, { month: 1 }, calendar), or getEndOfMonth(timestamp, calendar).
Lists
import { createDayList, createIntervalList, parseTimestamp } from '@timestamp-js/core'
const start = parseTimestamp('2026-06-01')!
const end = parseTimestamp('2026-06-07')!
const days = createDayList(start, end)
const intervals = createIntervalList(start, 0, 60, 24, start)createDayList() also accepts a CalendarSystem as its final argument for adapter-native day generation. The createCalendarDayList() helper below is often clearer in adapter-specific code.
Adapter calendar lists
Use the calendar-aware helpers when date fields belong to an optional calendar adapter rather than the built-in Gregorian calendar.
import {
createCalendarDayList,
getCalendarEndOfMonth,
getCalendarEndOfWeek,
parseCalendarTimestamp,
getCalendarStartOfMonth,
getCalendarStartOfWeek,
} from '@timestamp-js/core'
import { indianNationalCalendar } from '@timestamp-js/calendar-saka'
const visible = parseCalendarTimestamp('1946-01-15', indianNationalCalendar)!
const weekdays = [0, 1, 2, 3, 4, 5, 6]
const weekStart = getCalendarStartOfWeek(visible, weekdays, indianNationalCalendar)
const weekEnd = getCalendarEndOfWeek(visible, weekdays, indianNationalCalendar)
const weekDays = createCalendarDayList(weekStart, weekEnd, visible, indianNationalCalendar)
weekStart.date // '1946-01-11'
weekEnd.date // '1946-01-17'
weekDays.map((day) => day.date)
// [
// '1946-01-11',
// '1946-01-12',
// '1946-01-13',
// '1946-01-14',
// '1946-01-15',
// '1946-01-16',
// '1946-01-17',
// ]
const monthStart = getCalendarStartOfMonth(visible, indianNationalCalendar)
const monthEnd = getCalendarEndOfMonth(visible, indianNationalCalendar)
const monthDays = createCalendarDayList(monthStart, monthEnd, visible, indianNationalCalendar)
monthStart.date // '1946-01-01'
monthEnd.date // '1946-01-31'
monthDays.length // 31Islamic civil ranges
The same helpers work with Islamic civil dates. The input and output dates stay in Islamic civil year/month/day fields, while the adapter supplies stable serial-day comparison under the hood.
import {
createCalendarDayList,
getCalendarEndOfMonth,
getCalendarEndOfWeek,
getCalendarStartOfMonth,
getCalendarStartOfWeek,
parseCalendarTimestamp,
} from '@timestamp-js/core'
import { islamicCivilCalendar } from '@timestamp-js/calendar-islamic'
const visible = parseCalendarTimestamp('1445-09-15', islamicCivilCalendar)!
const weekdays = [0, 1, 2, 3, 4, 5, 6]
const weekStart = getCalendarStartOfWeek(visible, weekdays, islamicCivilCalendar)
const weekEnd = getCalendarEndOfWeek(visible, weekdays, islamicCivilCalendar)
const weekDays = createCalendarDayList(weekStart, weekEnd, visible, islamicCivilCalendar)
weekStart.date // '1445-09-14'
weekEnd.date // '1445-09-20'
weekDays.map((day) => day.date)
// [
// '1445-09-14',
// '1445-09-15',
// '1445-09-16',
// '1445-09-17',
// '1445-09-18',
// '1445-09-19',
// '1445-09-20',
// ]
const monthStart = getCalendarStartOfMonth(visible, islamicCivilCalendar)
const monthEnd = getCalendarEndOfMonth(visible, islamicCivilCalendar)
const monthDays = createCalendarDayList(monthStart, monthEnd, visible, islamicCivilCalendar)
monthStart.date // '1445-09-01'
monthEnd.date // '1445-09-30'
monthDays.length // 30Calendar interop
Use conversion helpers when a UI works with one calendar system but storage, APIs, or another UI surface expects another calendar.
import {
convertCalendarDate,
convertCalendarTimestamp,
getCalendarDatePartsIdentity,
isCalendarEndOfMonth,
isCalendarStartOfMonth,
isOutsideCalendarMonth,
parseCalendarTimestampSafe,
toCalendarTimestamp,
toGregorianTimestamp,
} from '@timestamp-js/core'
import { islamicCivilCalendar } from '@timestamp-js/calendar-islamic'
const gregorian = parseCalendarTimestampSafe('2024-03-11')!
const hijri = toCalendarTimestamp(gregorian, islamicCivilCalendar)
const stored = toGregorianTimestamp(hijri, islamicCivilCalendar)
hijri.date // '1445-09-01'
stored.date // '2024-03-11'
convertCalendarTimestamp(hijri, islamicCivilCalendar).date // '2024-03-11'
convertCalendarDate('1445-09-01', islamicCivilCalendar) // '2024-03-11'
const identity = getCalendarDatePartsIdentity(
{ year: 1445, month: 9, day: 1 },
islamicCivilCalendar,
)
identity.nativeDate // '1445-09-01'
identity.gregorianDate // '2024-03-11'
identity.epochDay // stable cross-calendar comparison key
isCalendarStartOfMonth(hijri, islamicCivilCalendar) // true
isCalendarEndOfMonth(hijri, islamicCivilCalendar) // false
isOutsideCalendarMonth(
parseCalendarTimestampSafe('1445-10-01', islamicCivilCalendar)!,
hijri,
islamicCivilCalendar,
) // trueparseCalendarTimestampSafe() is intended for component model watchers and form-like workflows. It returns a fallback instead of throwing when a value is empty, stale, outside the adapter-supported range, or temporarily invalid while a user is editing.
Labels
Use Intl.DateTimeFormat-backed helpers for month and weekday labels.
import { getMonthNames, getWeekdayNames } from '@timestamp-js/core'
const weekdays = getWeekdayNames('long', 'en-US')
const months = getMonthNames('long', 'en-US')For adapter calendar labels, use the calendar-aware helpers so Timestamp can combine the adapter’s defaultLocale, defaultWeekdays, and intlCalendar metadata with Intl.DateTimeFormat.
import {
formatCalendarDateLabel,
getCalendarMonthName,
getCalendarMonthNames,
getCalendarWeekdayNames,
parseCalendarTimestamp,
} from '@timestamp-js/core'
import { islamicCivilCalendar } from '@timestamp-js/calendar-islamic'
const visible = parseCalendarTimestamp('1445-09-15', islamicCivilCalendar)!
getCalendarMonthName(islamicCivilCalendar, visible.month, 'long', 'en-US', visible.year)
// 'Ramadan'
getCalendarMonthNames(islamicCivilCalendar, 'short', 'en-US', visible.year)
// ['Muh.', 'Saf.', 'Rab. I', ...]
getCalendarWeekdayNames(islamicCivilCalendar, 'short', 'en-US')
// ['Sat', 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri']
formatCalendarDateLabel(
visible,
islamicCivilCalendar,
{
year: 'numeric',
month: 'long',
day: 'numeric',
},
'en-US',
)
// 'Ramadan 15, 1445 AH'If an adapter does not publish an intlCalendar, month labels fall back to Month 1, Month 2, and so on. Date labels fall back to the adapter-native YYYY-MM-DD string.
Use compact masks when you only need fixed numeric output and do not need localized names.
import { formatTimestamp, parseTimestamp } from '@timestamp-js/core'
const timestamp = parseTimestamp('2036-06-08T09:30:15.250Z')!
formatTimestamp(timestamp, 'YYYY-MM-DD') // '2036-06-08'
formatTimestamp(timestamp, 'HH:mm:ss.SSS') // '09:30:15.250'Identifiers
Identifiers give stable numeric comparisons without converting to native Date objects repeatedly.
import {
getCalendarDayIdentifier,
getDayIdentifier,
getDayTimeIdentifier,
parseTimestamp,
} from '@timestamp-js/core'
const timestamp = parseTimestamp('2026-06-08 09:30')!
getDayIdentifier(timestamp)
getDayTimeIdentifier(timestamp)
getCalendarDayIdentifier(timestamp)