QCalendar uses Gregorian dates by default. When you pass a Timestamp calendar adapter with calendar-system, date-bearing component APIs use that adapter’s native YYYY-MM-DD calendar dates while QCalendar keeps Gregorian interop metadata available for storage, APIs, export, analytics, and debugging.
This is different from locale. Locale changes language and regional formatting. A calendar adapter changes the calendar math: year, month, day, month length, leap-year rules, and weekday calculation.
Calendar-specific examples live with the Timestamp adapter docs:
- Islamic Civil (Hijri) shows Hijri week and month ranges, RTL layout, localized weekday names, and selectable Hijri month names.
- Indian National (Saka) shows Saka week and month ranges, localized labels, and selectable Saka month names.
- Hebrew shows Hebrew week and month ranges, RTL layout, civil/CLDR month numbering, and Gregorian interop metadata.
- Persian (Jalali) shows Persian week and month ranges, RTL layout, localized month names, and Gregorian interop metadata.
Use this page when you are ready to connect those adapters to QCalendar.
Install only the adapter packages your app needs beside @timestamp-js/core. QCalendar does not install non-Gregorian adapters for you; the published QCalendar package only depends on @timestamp-js/core.
pnpm add @timestamp-js/core @timestamp-js/calendar-islamicAdd additional adapters explicitly when your app uses them:
pnpm add @timestamp-js/calendar-sakapnpm add @timestamp-js/calendar-hebrewpnpm add @timestamp-js/calendar-persianIntegration Boundary
There are two date identities in play:
- A Timestamp calendar adapter owns native calendar math: month starts, month ends, month lengths, native day numbers, and native month names.
- QCalendar parses and emits adapter-native
YYYY-MM-DDvalues for model values, selections, disabled dates, slots, and events whencalendar-systemis active. - QCalendar also exposes stable identity metadata for the same day, including a Gregorian date and an
epochDayserial key.
That means native calendar views can feel native end to end. When an app still stores or exchanges Gregorian dates, use the identity metadata from the slot or event scope as the bridge instead of making the visible calendar state Gregorian.
QCalendar Contract
Pass calendar-system to QCalendar when a view should expose adapter-native date data. QCalendar reads the adapter’s default locale, text direction, and visible weekday order from Timestamp when those props are omitted. Pass locale, dir, or weekdays only when the app needs to override that presentation, such as rendering a five-day work week.
<script setup>
import { ref } from 'vue'
import { islamicCivilCalendar } from '@timestamp-js/calendar-islamic'
const selectedHijriDate = ref('1445-09-15')
</script>
<q-calendar-month v-model="selectedHijriDate" :calendar-system="islamicCivilCalendar">
<template #day="{ scope }">
<strong>{{ scope.calendarTimestamp.day }}</strong>
<span>Gregorian {{ scope.calendarIdentity.gregorianDate }}</span>
</template>
</q-calendar-month>Date-bearing slot and mouse-event scopes include native values and interop identity metadata:
scope.timestampis the timestamp used by the active view. Withcalendar-system, it is adapter-native.scope.calendarTimestampis the same day represented in the configured calendar system. Withcalendar-system, it matches the active native calendar.scope.calendarIdentitycontains stable identity metadata, includingnativeDate,gregorianDate, andepochDay.scope.calendarSystemis the adapter that createdcalendarTimestamp.
Use scope.timestamp or scope.calendarTimestamp for labels, selected dates, disabled dates, and native-keyed app data. Use scope.calendarIdentity.gregorianDate only at integration boundaries that still require Gregorian dates.
If you do not pass calendar-system, QCalendar uses the Gregorian calendar from @timestamp-js/core. The adapter fields are still present, and both timestamp fields represent the same Gregorian day.
If you do pass calendar-system, explicit presentation props still win. For example, a Saka, Hijri, Hebrew, or Persian view can render a local five-day work week with :weekdays="[1, 2, 3, 4, 5]" while keeping adapter-native date math and model values.
Adapter Fields
Timestamp adapters publish identity, presentation defaults, and native date math. QCalendar reads the adapter as one contract, but the fields show up in different parts of the integration:
| Timestamp adapter field | Used for |
|---|---|
id | Stable adapter identity used by scope metadata and transition keys |
intlCalendar | Intl calendar id for locale-aware formatting when the adapter provides one |
label | Human-readable adapter name for docs, tools, and custom UI |
defaultLocale | Fallback locale for weekday, month, and date labels |
defaultDirection | Fallback dir for the rendered calendar root |
defaultWeekdays | Fallback weekdays for visible weekday order and week navigation |
The adapter’s date-math methods, such as monthsInYear, daysInMonth, toEpochDay, and fromEpochDay, drive native month boundaries, outside-day state, previous/next navigation, and cross-calendar identity metadata.
QCalendar uses presentation defaults only when the matching prop is omitted:
| Timestamp adapter field | QCalendar prop |
|---|---|
defaultLocale | locale |
defaultDirection | dir |
defaultWeekdays | weekdays |
This keeps the common case small:
<q-calendar-month v-model="selectedHijriDate" :calendar-system="islamicCivilCalendar" />And it keeps application-specific presentation explicit:
<q-calendar-month
v-model="selectedHijriDate"
:calendar-system="islamicCivilCalendar"
:weekdays="[1, 2, 3, 4, 5]"
/>The second example still uses Hijri date math and Hijri YYYY-MM-DD model values, but it displays a five-day work week instead of the adapter’s normal visible week.
The change event follows the same pattern. It includes days for the visible range and calendarDays for the same visible dates represented in the configured calendar system.
import type { const Timestamp: TimestampImmutable timestamp data used by all parser, comparison, and date math helpers.
Core parser helpers produce Gregorian calendar fields and preserve optional
ISO timezone suffixes without converting the wall-clock values into another
zone. Calendar adapter helpers can also produce timestamp-shaped values whose
year/month/day fields belong to the adapter identified by `calendarId`.
Frozen empty timestamp template.
Use copyTimestamp or parser helpers to create new timestamp objects
instead of mutating this shared default.Timestamp } from '@timestamp-js/core'
interface QCalendarChangePayload {
QCalendarChangePayload.start: stringstart: string
QCalendarChangePayload.end: stringend: string
QCalendarChangePayload.days: Timestamp[]days: Timestamp[]
QCalendarChangePayload.calendarStart: stringcalendarStart: string
QCalendarChangePayload.calendarEnd: stringcalendarEnd: string
QCalendarChangePayload.calendarDays: Timestamp[]calendarDays: Timestamp[]
QCalendarChangePayload.calendarSystem: unknowncalendarSystem: unknown
}
function function onChange(payload: QCalendarChangePayload): voidonChange(payload: QCalendarChangePayloadpayload: QCalendarChangePayload) {
var console: Consoleconsole.Console.log(...data: any[]): voidThe **`console.log()`** static method outputs a message to the console.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log_static)log(payload: QCalendarChangePayloadpayload.QCalendarChangePayload.start: stringstart, payload: QCalendarChangePayloadpayload.QCalendarChangePayload.end: stringend)
var console: Consoleconsole.Console.log(...data: any[]): voidThe **`console.log()`** static method outputs a message to the console.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log_static)log(payload: QCalendarChangePayloadpayload.QCalendarChangePayload.calendarStart: stringcalendarStart, payload: QCalendarChangePayloadpayload.QCalendarChangePayload.calendarEnd: stringcalendarEnd)
}Adapter Bridge
Use the epoch-day bridge only when you are outside a QCalendar slot or event, such as turning a stored Gregorian value into a native timestamp for summary text:
import {
function createCalendarTimestampFromEpochDay(epochDay: number, calendar?: CalendarSystem, options?: CalendarTimestampOptions): TimestampCreates a calendar timestamp from a stable serial day.createCalendarTimestampFromEpochDay,
function getEpochDay(timestamp: Timestamp, calendar?: CalendarSystem): numberConverts a Timestamp date into a stable serial day for a calendar system.
The default Gregorian value is the number of UTC days since 1970-01-01.
Alternate calendar adapters should map their year/month/day fields to the
same serial day space so ranges and comparisons can be calendar-agnostic.getEpochDay,
function parseTimestamp(input: string, now?: Timestamp | null): Timestamp | nullConverts a supported date or date-time string into a formatted Timestamp object.
If `now` is supplied, the returned timestamp also includes relative flags
such as `past`, `current`, `future`, and `currentWeekday`.parseTimestamp,
type const Timestamp: TimestampImmutable timestamp data used by all parser, comparison, and date math helpers.
Core parser helpers produce Gregorian calendar fields and preserve optional
ISO timezone suffixes without converting the wall-clock values into another
zone. Calendar adapter helpers can also produce timestamp-shaped values whose
year/month/day fields belong to the adapter identified by `calendarId`.
Frozen empty timestamp template.
Use copyTimestamp or parser helpers to create new timestamp objects
instead of mutating this shared default.Timestamp,
} from '@timestamp-js/core'
import { const islamicCivilCalendar: CalendarSystemDeterministic tabular Islamic civil calendar.
This adapter intentionally models the arithmetic/civil Hijri calendar. It
does not model observational calendars or Umm al-Qura adjustments.islamicCivilCalendar } from '@timestamp-js/calendar-islamic'
function function toHijri(timestamp: Timestamp): TimestamptoHijri(timestamp: Timestamptimestamp: Timestamp) {
return function createCalendarTimestampFromEpochDay(epochDay: number, calendar?: CalendarSystem, options?: CalendarTimestampOptions): TimestampCreates a calendar timestamp from a stable serial day.createCalendarTimestampFromEpochDay(function getEpochDay(timestamp: Timestamp, calendar?: CalendarSystem): numberConverts a Timestamp date into a stable serial day for a calendar system.
The default Gregorian value is the number of UTC days since 1970-01-01.
Alternate calendar adapters should map their year/month/day fields to the
same serial day space so ranges and comparisons can be calendar-agnostic.getEpochDay(timestamp: Timestamptimestamp), const islamicCivilCalendar: CalendarSystemDeterministic tabular Islamic civil calendar.
This adapter intentionally models the arithmetic/civil Hijri calendar. It
does not model observational calendars or Umm al-Qura adjustments.islamicCivilCalendar)
}
const const selectedGregorian: TimestampselectedGregorian = function parseTimestamp(input: string, now?: Timestamp | null): Timestamp | nullConverts a supported date or date-time string into a formatted Timestamp object.
If `now` is supplied, the returned timestamp also includes relative flags
such as `past`, `current`, `future`, and `currentWeekday`.parseTimestamp('2024-03-25')!
const const selectedHijri: TimestampselectedHijri = function toHijri(timestamp: Timestamp): TimestamptoHijri(const selectedGregorian: TimestampselectedGregorian)Use the same bridge in the other direction when you need a Gregorian date for an external system from a native adapter timestamp:
import {
function createCalendarTimestampFromEpochDay(epochDay: number, calendar?: CalendarSystem, options?: CalendarTimestampOptions): TimestampCreates a calendar timestamp from a stable serial day.createCalendarTimestampFromEpochDay,
function getEpochDay(timestamp: Timestamp, calendar?: CalendarSystem): numberConverts a Timestamp date into a stable serial day for a calendar system.
The default Gregorian value is the number of UTC days since 1970-01-01.
Alternate calendar adapters should map their year/month/day fields to the
same serial day space so ranges and comparisons can be calendar-agnostic.getEpochDay,
type const Timestamp: TimestampImmutable timestamp data used by all parser, comparison, and date math helpers.
Core parser helpers produce Gregorian calendar fields and preserve optional
ISO timezone suffixes without converting the wall-clock values into another
zone. Calendar adapter helpers can also produce timestamp-shaped values whose
year/month/day fields belong to the adapter identified by `calendarId`.
Frozen empty timestamp template.
Use copyTimestamp or parser helpers to create new timestamp objects
instead of mutating this shared default.Timestamp,
} from '@timestamp-js/core'
import { const islamicCivilCalendar: CalendarSystemDeterministic tabular Islamic civil calendar.
This adapter intentionally models the arithmetic/civil Hijri calendar. It
does not model observational calendars or Umm al-Qura adjustments.islamicCivilCalendar } from '@timestamp-js/calendar-islamic'
function function toGregorian(hijriTimestamp: Timestamp): TimestamptoGregorian(hijriTimestamp: TimestamphijriTimestamp: Timestamp) {
return function createCalendarTimestampFromEpochDay(epochDay: number, calendar?: CalendarSystem, options?: CalendarTimestampOptions): TimestampCreates a calendar timestamp from a stable serial day.createCalendarTimestampFromEpochDay(function getEpochDay(timestamp: Timestamp, calendar?: CalendarSystem): numberConverts a Timestamp date into a stable serial day for a calendar system.
The default Gregorian value is the number of UTC days since 1970-01-01.
Alternate calendar adapters should map their year/month/day fields to the
same serial day space so ranges and comparisons can be calendar-agnostic.getEpochDay(hijriTimestamp: TimestamphijriTimestamp, const islamicCivilCalendar: CalendarSystemDeterministic tabular Islamic civil calendar.
This adapter intentionally models the arithmetic/civil Hijri calendar. It
does not model observational calendars or Umm al-Qura adjustments.islamicCivilCalendar))
}Native Week Ranges
When a user chooses a native calendar date, calculate the native week with the same adapter and weekday order that the view receives. Convert the boundaries to Gregorian only when you need to query an API or compare against Gregorian stored app data.
import {
function createCalendarTimestampFromEpochDay(epochDay: number, calendar?: CalendarSystem, options?: CalendarTimestampOptions): TimestampCreates a calendar timestamp from a stable serial day.createCalendarTimestampFromEpochDay,
function getCalendarEndOfWeek(timestamp: Timestamp, weekdays: number[], calendar?: CalendarSystem, now?: Timestamp | null): TimestampReturns the end of a calendar week for a timestamp and weekday set.getCalendarEndOfWeek,
function getCalendarWeekdays(calendar?: CalendarSystem): number[]Returns the recommended visible weekday order for a calendar system.
Calendar adapters can use this to publish their normal visible week. Callers can still pass an
explicit weekday list for application-specific layouts such as a five-day work week.getCalendarWeekdays,
function getCalendarStartOfWeek(timestamp: Timestamp, weekdays: number[], calendar?: CalendarSystem, now?: Timestamp | null): TimestampReturns the start of a calendar week for a timestamp and weekday set.getCalendarStartOfWeek,
function getEpochDay(timestamp: Timestamp, calendar?: CalendarSystem): numberConverts a Timestamp date into a stable serial day for a calendar system.
The default Gregorian value is the number of UTC days since 1970-01-01.
Alternate calendar adapters should map their year/month/day fields to the
same serial day space so ranges and comparisons can be calendar-agnostic.getEpochDay,
function parseTimestamp(input: string, now?: Timestamp | null): Timestamp | nullConverts a supported date or date-time string into a formatted Timestamp object.
If `now` is supplied, the returned timestamp also includes relative flags
such as `past`, `current`, `future`, and `currentWeekday`.parseTimestamp,
type const Timestamp: TimestampImmutable timestamp data used by all parser, comparison, and date math helpers.
Core parser helpers produce Gregorian calendar fields and preserve optional
ISO timezone suffixes without converting the wall-clock values into another
zone. Calendar adapter helpers can also produce timestamp-shaped values whose
year/month/day fields belong to the adapter identified by `calendarId`.
Frozen empty timestamp template.
Use copyTimestamp or parser helpers to create new timestamp objects
instead of mutating this shared default.Timestamp,
} from '@timestamp-js/core'
import { const islamicCivilCalendar: CalendarSystemDeterministic tabular Islamic civil calendar.
This adapter intentionally models the arithmetic/civil Hijri calendar. It
does not model observational calendars or Umm al-Qura adjustments.islamicCivilCalendar } from '@timestamp-js/calendar-islamic'
// Use the same visible weekday order that the QCalendar view receives by default.
const const hijriWeekdays: number[]hijriWeekdays = function getCalendarWeekdays(calendar?: CalendarSystem): number[]Returns the recommended visible weekday order for a calendar system.
Calendar adapters can use this to publish their normal visible week. Callers can still pass an
explicit weekday list for application-specific layouts such as a five-day work week.getCalendarWeekdays(const islamicCivilCalendar: CalendarSystemDeterministic tabular Islamic civil calendar.
This adapter intentionally models the arithmetic/civil Hijri calendar. It
does not model observational calendars or Umm al-Qura adjustments.islamicCivilCalendar)
function function toHijri(timestamp: Timestamp): TimestamptoHijri(timestamp: Timestamptimestamp: Timestamp) {
// The epoch day lets the adapter describe the same absolute day in the
// native calendar system.
return function createCalendarTimestampFromEpochDay(epochDay: number, calendar?: CalendarSystem, options?: CalendarTimestampOptions): TimestampCreates a calendar timestamp from a stable serial day.createCalendarTimestampFromEpochDay(function getEpochDay(timestamp: Timestamp, calendar?: CalendarSystem): numberConverts a Timestamp date into a stable serial day for a calendar system.
The default Gregorian value is the number of UTC days since 1970-01-01.
Alternate calendar adapters should map their year/month/day fields to the
same serial day space so ranges and comparisons can be calendar-agnostic.getEpochDay(timestamp: Timestamptimestamp), const islamicCivilCalendar: CalendarSystemDeterministic tabular Islamic civil calendar.
This adapter intentionally models the arithmetic/civil Hijri calendar. It
does not model observational calendars or Umm al-Qura adjustments.islamicCivilCalendar)
}
function function toGregorian(hijriTimestamp: Timestamp): TimestamptoGregorian(hijriTimestamp: TimestamphijriTimestamp: Timestamp) {
// Convert native adapter boundaries before using them as Gregorian-backed
// route params or API query boundaries.
return function createCalendarTimestampFromEpochDay(epochDay: number, calendar?: CalendarSystem, options?: CalendarTimestampOptions): TimestampCreates a calendar timestamp from a stable serial day.createCalendarTimestampFromEpochDay(function getEpochDay(timestamp: Timestamp, calendar?: CalendarSystem): numberConverts a Timestamp date into a stable serial day for a calendar system.
The default Gregorian value is the number of UTC days since 1970-01-01.
Alternate calendar adapters should map their year/month/day fields to the
same serial day space so ranges and comparisons can be calendar-agnostic.getEpochDay(hijriTimestamp: TimestamphijriTimestamp, const islamicCivilCalendar: CalendarSystemDeterministic tabular Islamic civil calendar.
This adapter intentionally models the arithmetic/civil Hijri calendar. It
does not model observational calendars or Umm al-Qura adjustments.islamicCivilCalendar))
}
const const selectedGregorian: TimestampselectedGregorian = function parseTimestamp(input: string, now?: Timestamp | null): Timestamp | nullConverts a supported date or date-time string into a formatted Timestamp object.
If `now` is supplied, the returned timestamp also includes relative flags
such as `past`, `current`, `future`, and `currentWeekday`.parseTimestamp('2024-03-25')!
const const selectedHijri: TimestampselectedHijri = function toHijri(timestamp: Timestamp): TimestamptoHijri(const selectedGregorian: TimestampselectedGregorian)
// Calculate week boundaries in the native calendar, not the Gregorian calendar.
const const weekStartHijri: TimestampweekStartHijri = function getCalendarStartOfWeek(timestamp: Timestamp, weekdays: number[], calendar?: CalendarSystem, now?: Timestamp | null): TimestampReturns the start of a calendar week for a timestamp and weekday set.getCalendarStartOfWeek(const selectedHijri: TimestampselectedHijri, const hijriWeekdays: number[]hijriWeekdays, const islamicCivilCalendar: CalendarSystemDeterministic tabular Islamic civil calendar.
This adapter intentionally models the arithmetic/civil Hijri calendar. It
does not model observational calendars or Umm al-Qura adjustments.islamicCivilCalendar)
const const weekEndHijri: TimestampweekEndHijri = function getCalendarEndOfWeek(timestamp: Timestamp, weekdays: number[], calendar?: CalendarSystem, now?: Timestamp | null): TimestampReturns the end of a calendar week for a timestamp and weekday set.getCalendarEndOfWeek(const selectedHijri: TimestampselectedHijri, const hijriWeekdays: number[]hijriWeekdays, const islamicCivilCalendar: CalendarSystemDeterministic tabular Islamic civil calendar.
This adapter intentionally models the arithmetic/civil Hijri calendar. It
does not model observational calendars or Umm al-Qura adjustments.islamicCivilCalendar)
const const weekStartGregorian: TimestampweekStartGregorian = function toGregorian(hijriTimestamp: Timestamp): TimestamptoGregorian(const weekStartHijri: TimestampweekStartHijri)
const const weekEndGregorian: TimestampweekEndGregorian = function toGregorian(hijriTimestamp: Timestamp): TimestamptoGregorian(const weekEndHijri: TimestampweekEndHijri)Use the native range for QCalendar model values, native labels, and native-keyed data. Use the converted Gregorian range for integrations that still expect Gregorian dates.
Native Month Views
With calendar-system, supported month-style views use native calendar math for:
- the first and last native day of the visible month
- the leading and trailing outside days
outsideslot state- previous and next month navigation
This matters for native users. For example, Ramadan day 1 must appear in the first visible week of the Ramadan grid, even when that day is not the first day of the Gregorian month.
QCalendarMonth and mini-mode perform this range math internally when calendar-system is supplied. If you are building a custom month surface, preparing an API query, or showing summary text, calculate both the native month boundaries and the visible grid boundaries:
import {
function createCalendarTimestampFromEpochDay(epochDay: number, calendar?: CalendarSystem, options?: CalendarTimestampOptions): TimestampCreates a calendar timestamp from a stable serial day.createCalendarTimestampFromEpochDay,
function getCalendarEndOfMonth(timestamp: Timestamp, calendar?: CalendarSystem): TimestampReturns the end of the calendar month for a timestamp.getCalendarEndOfMonth,
function getCalendarEndOfWeek(timestamp: Timestamp, weekdays: number[], calendar?: CalendarSystem, now?: Timestamp | null): TimestampReturns the end of a calendar week for a timestamp and weekday set.getCalendarEndOfWeek,
function getCalendarWeekdays(calendar?: CalendarSystem): number[]Returns the recommended visible weekday order for a calendar system.
Calendar adapters can use this to publish their normal visible week. Callers can still pass an
explicit weekday list for application-specific layouts such as a five-day work week.getCalendarWeekdays,
function getCalendarStartOfMonth(timestamp: Timestamp, calendar?: CalendarSystem): TimestampReturns the start of the calendar month for a timestamp.getCalendarStartOfMonth,
function getCalendarStartOfWeek(timestamp: Timestamp, weekdays: number[], calendar?: CalendarSystem, now?: Timestamp | null): TimestampReturns the start of a calendar week for a timestamp and weekday set.getCalendarStartOfWeek,
function getEpochDay(timestamp: Timestamp, calendar?: CalendarSystem): numberConverts a Timestamp date into a stable serial day for a calendar system.
The default Gregorian value is the number of UTC days since 1970-01-01.
Alternate calendar adapters should map their year/month/day fields to the
same serial day space so ranges and comparisons can be calendar-agnostic.getEpochDay,
function parseTimestamp(input: string, now?: Timestamp | null): Timestamp | nullConverts a supported date or date-time string into a formatted Timestamp object.
If `now` is supplied, the returned timestamp also includes relative flags
such as `past`, `current`, `future`, and `currentWeekday`.parseTimestamp,
type const Timestamp: TimestampImmutable timestamp data used by all parser, comparison, and date math helpers.
Core parser helpers produce Gregorian calendar fields and preserve optional
ISO timezone suffixes without converting the wall-clock values into another
zone. Calendar adapter helpers can also produce timestamp-shaped values whose
year/month/day fields belong to the adapter identified by `calendarId`.
Frozen empty timestamp template.
Use copyTimestamp or parser helpers to create new timestamp objects
instead of mutating this shared default.Timestamp,
} from '@timestamp-js/core'
import { const islamicCivilCalendar: CalendarSystemDeterministic tabular Islamic civil calendar.
This adapter intentionally models the arithmetic/civil Hijri calendar. It
does not model observational calendars or Umm al-Qura adjustments.islamicCivilCalendar } from '@timestamp-js/calendar-islamic'
// Use the same visible weekday order that the QCalendar view receives by default.
const const hijriWeekdays: number[]hijriWeekdays = function getCalendarWeekdays(calendar?: CalendarSystem): number[]Returns the recommended visible weekday order for a calendar system.
Calendar adapters can use this to publish their normal visible week. Callers can still pass an
explicit weekday list for application-specific layouts such as a five-day work week.getCalendarWeekdays(const islamicCivilCalendar: CalendarSystemDeterministic tabular Islamic civil calendar.
This adapter intentionally models the arithmetic/civil Hijri calendar. It
does not model observational calendars or Umm al-Qura adjustments.islamicCivilCalendar)
function function toHijri(timestamp: Timestamp): TimestamptoHijri(timestamp: Timestamptimestamp: Timestamp) {
// Bridge from the stored Gregorian date to the same absolute day in Hijri.
return function createCalendarTimestampFromEpochDay(epochDay: number, calendar?: CalendarSystem, options?: CalendarTimestampOptions): TimestampCreates a calendar timestamp from a stable serial day.createCalendarTimestampFromEpochDay(function getEpochDay(timestamp: Timestamp, calendar?: CalendarSystem): numberConverts a Timestamp date into a stable serial day for a calendar system.
The default Gregorian value is the number of UTC days since 1970-01-01.
Alternate calendar adapters should map their year/month/day fields to the
same serial day space so ranges and comparisons can be calendar-agnostic.getEpochDay(timestamp: Timestamptimestamp), const islamicCivilCalendar: CalendarSystemDeterministic tabular Islamic civil calendar.
This adapter intentionally models the arithmetic/civil Hijri calendar. It
does not model observational calendars or Umm al-Qura adjustments.islamicCivilCalendar)
}
function function toGregorian(hijriTimestamp: Timestamp): TimestamptoGregorian(hijriTimestamp: TimestamphijriTimestamp: Timestamp) {
// Bridge native adapter results for Gregorian-backed APIs.
return function createCalendarTimestampFromEpochDay(epochDay: number, calendar?: CalendarSystem, options?: CalendarTimestampOptions): TimestampCreates a calendar timestamp from a stable serial day.createCalendarTimestampFromEpochDay(function getEpochDay(timestamp: Timestamp, calendar?: CalendarSystem): numberConverts a Timestamp date into a stable serial day for a calendar system.
The default Gregorian value is the number of UTC days since 1970-01-01.
Alternate calendar adapters should map their year/month/day fields to the
same serial day space so ranges and comparisons can be calendar-agnostic.getEpochDay(hijriTimestamp: TimestamphijriTimestamp, const islamicCivilCalendar: CalendarSystemDeterministic tabular Islamic civil calendar.
This adapter intentionally models the arithmetic/civil Hijri calendar. It
does not model observational calendars or Umm al-Qura adjustments.islamicCivilCalendar))
}
const const selectedGregorian: TimestampselectedGregorian = function parseTimestamp(input: string, now?: Timestamp | null): Timestamp | nullConverts a supported date or date-time string into a formatted Timestamp object.
If `now` is supplied, the returned timestamp also includes relative flags
such as `past`, `current`, `future`, and `currentWeekday`.parseTimestamp('2024-03-25')!
const const selectedHijri: TimestampselectedHijri = function toHijri(timestamp: Timestamp): TimestamptoHijri(const selectedGregorian: TimestampselectedGregorian)
// These are the first and last days of the native month itself.
const const monthStart: TimestampmonthStart = function getCalendarStartOfMonth(timestamp: Timestamp, calendar?: CalendarSystem): TimestampReturns the start of the calendar month for a timestamp.getCalendarStartOfMonth(const selectedHijri: TimestampselectedHijri, const islamicCivilCalendar: CalendarSystemDeterministic tabular Islamic civil calendar.
This adapter intentionally models the arithmetic/civil Hijri calendar. It
does not model observational calendars or Umm al-Qura adjustments.islamicCivilCalendar)
const const monthEnd: TimestampmonthEnd = function getCalendarEndOfMonth(timestamp: Timestamp, calendar?: CalendarSystem): TimestampReturns the end of the calendar month for a timestamp.getCalendarEndOfMonth(const selectedHijri: TimestampselectedHijri, const islamicCivilCalendar: CalendarSystemDeterministic tabular Islamic civil calendar.
This adapter intentionally models the arithmetic/civil Hijri calendar. It
does not model observational calendars or Umm al-Qura adjustments.islamicCivilCalendar)
// These include leading/trailing outside days needed by a full month grid.
const const gridStart: TimestampgridStart = function getCalendarStartOfWeek(timestamp: Timestamp, weekdays: number[], calendar?: CalendarSystem, now?: Timestamp | null): TimestampReturns the start of a calendar week for a timestamp and weekday set.getCalendarStartOfWeek(const monthStart: TimestampmonthStart, const hijriWeekdays: number[]hijriWeekdays, const islamicCivilCalendar: CalendarSystemDeterministic tabular Islamic civil calendar.
This adapter intentionally models the arithmetic/civil Hijri calendar. It
does not model observational calendars or Umm al-Qura adjustments.islamicCivilCalendar)
const const gridEnd: TimestampgridEnd = function getCalendarEndOfWeek(timestamp: Timestamp, weekdays: number[], calendar?: CalendarSystem, now?: Timestamp | null): TimestampReturns the end of a calendar week for a timestamp and weekday set.getCalendarEndOfWeek(const monthEnd: TimestampmonthEnd, const hijriWeekdays: number[]hijriWeekdays, const islamicCivilCalendar: CalendarSystemDeterministic tabular Islamic civil calendar.
This adapter intentionally models the arithmetic/civil Hijri calendar. It
does not model observational calendars or Umm al-Qura adjustments.islamicCivilCalendar)
// Use these Gregorian dates when querying Gregorian-backed integrations.
const const gridStartGregorian: TimestampgridStartGregorian = function toGregorian(hijriTimestamp: Timestamp): TimestamptoGregorian(const gridStart: TimestampgridStart)
const const gridEndGregorian: TimestampgridEndGregorian = function toGregorian(hijriTimestamp: Timestamp): TimestamptoGregorian(const gridEnd: TimestampgridEnd)Use monthStart and monthEnd when you need native month labels or native boundary badges. Use gridStart and gridEnd when you need the full visible native calendar grid, including outside days. Convert those values back to Gregorian before feeding ranges into a Gregorian-backed API.
Gregorian Interop
Use native adapter dates for user-facing calendar state. Keep Gregorian interop available for the boundaries that still need it:
- Existing apps may store records keyed by Gregorian dates.
- APIs, databases, exports, and analytics often expect Gregorian ISO dates even when the UI is native Saka, Hijri, or another calendar.
- Cross-calendar comparisons need a neutral serial key. Use
scope.calendarIdentity.epochDayrather than a Gregorian display string. - Debugging and migration are easier when you can inspect
scope.calendarIdentity.gregorianDatebeside the native date. - Integrations can move to native calendar UI without forcing every backend boundary to change at the same time.
In slots, prefer scope.timestamp or scope.calendarTimestamp for native UI and native-keyed data. Use scope.calendarIdentity.gregorianDate only when an external boundary needs a Gregorian date.
Labels And Data
Use scope.calendarTimestamp for native labels and native-keyed data:
import type { const Timestamp: TimestampImmutable timestamp data used by all parser, comparison, and date math helpers.
Core parser helpers produce Gregorian calendar fields and preserve optional
ISO timezone suffixes without converting the wall-clock values into another
zone. Calendar adapter helpers can also produce timestamp-shaped values whose
year/month/day fields belong to the adapter identified by `calendarId`.
Frozen empty timestamp template.
Use copyTimestamp or parser helpers to create new timestamp objects
instead of mutating this shared default.Timestamp } from '@timestamp-js/core'
import { const indianNationalCalendar: CalendarSystemDeterministic Indian National Calendar (Saka) adapter.
Saka year `1` begins in Gregorian year `79`. A Saka year starts on March 21
when the corresponding Gregorian year is leap, and March 22 otherwise.indianNationalCalendar } from '@timestamp-js/calendar-saka'
const const eventsBySakaDate: {
'1946-01-01': string[];
}
eventsBySakaDate = {
'1946-01-01': ['New Saka year'],
}
function function getSakaEvents(calendarTimestamp: Timestamp): string[]getSakaEvents(calendarTimestamp: TimestampcalendarTimestamp: Timestamp): string[] {
return const eventsBySakaDate: {
'1946-01-01': string[];
}
eventsBySakaDate[calendarTimestamp: TimestampcalendarTimestamp.Timestamp.date: stringDate string in `YYYY-MM-DD` form when the timestamp has a day.date as keyof typeof const eventsBySakaDate: {
'1946-01-01': string[];
}
eventsBySakaDate] ?? []
}
void const indianNationalCalendar: CalendarSystemDeterministic Indian National Calendar (Saka) adapter.
Saka year `1` begins in Gregorian year `79`. A Saka year starts on March 21
when the corresponding Gregorian year is leap, and March 22 otherwise.indianNationalCalendarView Examples
Calendar adapter examples live on the view pages where users are already learning that calendar type:
- QCalendar wrapper shows how the wrapper forwards adapter-aware props to the selected view.
- QCalendarDay shows adapter labels in a single-day interval view.
- QCalendarDay week view shows adapter labels and native-keyed data across a visible week.
- QCalendarDay intervals shows native context in interval labels.
- QCalendarMonth shows a native month grid where the first native day appears in the first visible week, outside days follow the native month, and previous/next navigation moves by native months.
- QCalendarMonth mini-mode shows the same native month behavior in a compact picker.
- QCalendarAgenda shows adapter labels in a week-style planning view.
- QCalendarResource shows adapter labels in a resource interval timeline.
- QCalendarScheduler shows native labels and native-keyed data in resource/day cells.
- QCalendarTask shows native labels and native-keyed work items in task day cells.
Add future adapter examples to the specific view page that owns the behavior rather than on this overview page.
Native User Checklist
When you build a production non-Gregorian calendar view, check these pieces deliberately:
- Choose the adapter package for the actual calendar rule set, not just the display language.
- Let the adapter provide locale, text direction, and visible weekday defaults when they match the target users.
- Override
locale,dir, orweekdayswhen the app needs a different presentation, such as a five-day work week. - Pass
calendar-systemto views that should exposescope.calendarTimestamp. - Use adapter-native
YYYY-MM-DDstrings forv-model, selected dates, disabled dates, native labels, and native-keyed data. - Use
scope.calendarIdentity.gregorianDatefor external systems that still expect Gregorian dates. - Use the epoch-day bridge outside QCalendar slots/events when you need to convert between stored Gregorian dates and native adapter dates.
- Test the first and last day of the native month, especially when those days fall in the middle of a Gregorian month.
- Test previous and next month navigation against native month names, not Gregorian month names.