Date pickers
Date pickers let users choose a date from a calendar while keeping the input editable. Use them when calendar context matters; for dates users already know, typing is often faster.
DockedDatePicker opens a calendar below the field, DatePickerDialog opens it in a modal, and DateRangePicker selects a start and end date. For date and time selection, see the date and time picker.
All pickers use ISO YYYY-MM-DD values based on local calendar fields. The docked and
modal pickers also support form submission through name.
Usage
value is bindable and stays in sync with typing and calendar selection. Calendar
changes are confirmed with OK or discarded with Cancel. Invalid or
incomplete input does not update value.
Value: 2025-08-17
<script lang="ts">
import { DockedDatePicker } from 'noph-ui'
let basic = $state<string | undefined>('2025-08-17')
</script>
<DockedDatePicker bind:value={basic} label="Date" />
<p>Value: <code>{basic ?? 'undefined'}</code></p>
Reacting to a change
onchange fires whenever the committed value changes, whether it came from the
calendar or from typing. It receives the ISO string, or undefined when the field is cleared.
Last event: none yet
<script lang="ts">
import { DockedDatePicker } from 'noph-ui'
let watched = $state<string | undefined>('2025-08-17')
let watchedLog = $state('')
</script>
<DockedDatePicker
bind:value={watched}
label="Date"
onchange={(next) => (watchedLog = next ? `changed to ${next}` : 'cleared')}
/>
<p>Last event: <code>{watchedLog || 'none yet'}</code></p>
Text field variants
The field is the library's TextField, so variant takes outlined (the default) or filled.
<script lang="ts">
import { DockedDatePicker } from 'noph-ui'
let basic = $state<string | undefined>('2025-08-17')
let filled = $state<string | undefined>()
</script>
<DockedDatePicker bind:value={basic} label="Outlined" />
<DockedDatePicker bind:value={filled} label="Filled" variant="filled" />
Localisation
Month names, weekday names and the numeric input order all come from Intl. Without a locale the runtime's own locale is used; pass one to pin it. The supporting text
under the field is generated from the same pattern, so a German picker asks for DD.MM.YYYY and parses 17.08.2025.
<script lang="ts">
import { DockedDatePicker } from 'noph-ui'
let german = $state<string | undefined>('2025-08-17')
let japanese = $state<string | undefined>('2025-08-17')
</script>
<DockedDatePicker bind:value={german} label="Datum" locale="de-DE" />
<DockedDatePicker bind:value={japanese} label="日付" locale="ja-JP" />
First day of the week
The first column is derived from the locale through Intl.Locale#getWeekInfo. On an
engine that does not implement it the calendar falls back to Sunday, so set firstDayOfWeek explicitly (0 = Sunday … 6 = Saturday) when the week start has to be certain.
<script lang="ts">
import { DockedDatePicker } from 'noph-ui'
let mondayFirst = $state<string | undefined>('2025-08-17')
</script>
<DockedDatePicker bind:value={mondayFirst} label="Week starts Monday" firstDayOfWeek={1} />
Bounding the selection
min and max are inclusive ISO days. They grey out the days outside the window,
stop the month and year steppers at the edge, and disable the months and years that fall entirely outside
it.
<script lang="ts">
import { DockedDatePicker } from 'noph-ui'
const thisYear = new Date().getFullYear()
let bounded = $state<string | undefined>()
</script>
<DockedDatePicker
bind:value={bounded}
label="Within {thisYear}"
min="{thisYear}-01-01"
max="{thisYear}-12-31"
/>
Disabling individual days
isDateEnabled runs for every rendered day; return false to disable it. Use
it for rules a range cannot express, such as weekends, public holidays or days already fully booked.
<script lang="ts">
import { DockedDatePicker } from 'noph-ui'
const today = new Date()
const isoToday = `${today.getFullYear()}-${`${today.getMonth() + 1}`.padStart(2, '0')}-${`${today.getDate()}`.padStart(2, '0')}`
const weekdaysOnly = (date: Date) => date.getDay() !== 0 && date.getDay() !== 6
let booking = $state<string | undefined>()
</script>
<DockedDatePicker
bind:value={booking}
label="Appointment"
min={isoToday}
isDateEnabled={weekdaysOnly}
/>
Restricting the year menu
yearRange sets the years offered in the year menu, defaulting to [1900, 2100]. Narrowing it keeps a long scroll from getting in the way. For a date of
birth, pair it with a max of today.
<script lang="ts">
import { DockedDatePicker } from 'noph-ui'
const today = new Date()
const isoToday = `${today.getFullYear()}-${`${today.getMonth() + 1}`.padStart(2, '0')}-${`${today.getDate()}`.padStart(2, '0')}`
let birthday = $state<string | undefined>()
</script>
<DockedDatePicker
bind:value={birthday}
label="Date of birth"
yearRange={[1920, today.getFullYear()]}
max={isoToday}
/>
Days of neighbouring months
By default the calendar shows only the days of the displayed month and leaves the surrounding
cells empty. Set adjacentMonthDays to fill those cells with the leading and trailing days
of the neighbouring months instead. Keyboard navigation crosses the month boundary either way.
<script lang="ts">
import { DockedDatePicker } from 'noph-ui'
let adjacent = $state<string | undefined>('2025-08-17')
</script>
<DockedDatePicker bind:value={adjacent} label="With adjacent days" adjacentMonthDays />
Controlling the calendar
displayMonth is the month on screen. It follows the selection until the person navigates,
and binding it lets you park the calendar on a specific month, such as the start of a booking season.
It also reports where they browsed to while the calendar is open, but closing it restores whatever you
set, so the picker always reopens where you put it.
<script lang="ts">
import { Button, DockedDatePicker } from 'noph-ui'
let steeredMonth: string | undefined = $state()
let steeredOpen = $state(false)
</script>
<div class="top-down">
<DockedDatePicker bind:displayMonth={steeredMonth} bind:open={steeredOpen} label="Season" />
<div>
<Button
variant="tonal"
onclick={() => {
steeredMonth = '2026-12-01'
steeredOpen = true
}}
>
Show December
</Button>
</div>
</div>
<style>
.top-down {
flex-direction: column;
gap: 1rem;
display: flex;
}
</style>
Opening it yourself
The docked pickers keep their calendar in a popover of their own, so there is no id for a trigger to point at. Open them with show() and close(), the pair every overlay in the library exports: bind a reference with bind:this, type it with ReturnType<typeof DockedDatePicker>, and
call through ?. since it is undefined until the component has mounted. show() on a disabled or readonly field does nothing.
<script lang="ts">
import { Button, DockedDatePicker } from 'noph-ui'
let programmaticOpen = $state(false)
let programmaticPicker = $state<ReturnType<typeof DockedDatePicker>>()
</script>
<div class="top-down">
<DockedDatePicker bind:this={programmaticPicker} bind:open={programmaticOpen} label="Date" />
<div>
<Button variant="tonal" onclick={() => programmaticPicker?.show()}>Open the calendar</Button>
</div>
</div>
<style>
.top-down {
flex-direction: column;
gap: 1rem;
display: flex;
}
</style>
Forms and validation
Passing a name includes the ISO date value in form submissions. Validation stays on the
visible field, so browser validation feedback works as expected.
Invalid dates are reported after submission or when the field loses focus. Use invalidDateMessage to customize the validation message. issues replaces the supporting text with your own messages and turns the field red, so
it pairs with whatever validation library the form already uses.
A SvelteKit remote form field can be spread straight in with {...field.as('date')}, alongside issues={field.issues()}. See Remote functions for a form that wires several components
up that way.
Nothing submitted yet.
<script lang="ts">
import { Button, DockedDatePicker } from 'noph-ui'
const today = new Date()
const isoToday = `${today.getFullYear()}-${`${today.getMonth() + 1}`.padStart(2, '0')}-${`${today.getDate()}`.padStart(2, '0')}`
let formValue = $state<string | undefined>()
let formIssues = $state<{ message: string }[]>([])
let submitted = $state('')
const handleSubmit = (event: SubmitEvent) => {
event.preventDefault()
const data = new FormData(event.currentTarget as HTMLFormElement)
const value = data.get('deliveryDate')
formIssues = value ? [] : [{ message: 'Pick a delivery date.' }]
submitted = value ? `Submitted deliveryDate=${value}` : ''
}
</script>
<form onsubmit={handleSubmit} novalidate>
<DockedDatePicker
bind:value={formValue}
label="Delivery date"
name="deliveryDate"
issues={formIssues}
min={isoToday}
required
/>
<Button type="submit" variant="filled">Submit</Button>
</form>
<p>{submitted || 'Nothing submitted yet.'}</p>
<style>
form {
display: flex;
align-items: flex-start;
gap: 1rem;
flex-wrap: wrap;
}
</style>
Modal
DatePickerDialog is the same calendar in a modal, with the selection echoed in a headline
and a three-column year grid behind the month button. Prefer it on small screens, or when picking the
date is the main task of the step rather than one field among many.
Value: 2025-08-17
<script lang="ts">
import { Button, DatePickerDialog } from 'noph-ui'
let dialogValue = $state<string | undefined>('2025-08-17')
</script>
<Button variant="filled" command="show-modal" commandfor="pick-a-date">Pick a date</Button>
<DatePickerDialog id="pick-a-date" bind:value={dialogValue} />
<p>Value: <code>{dialogValue ?? 'undefined'}</code></p>
The dialog is a native <dialog>, so a trigger opens it with command="show-modal" pointed at its id, and command="close" closes it. No state and no handler are involved, and it works before
the page has hydrated. Where there is no trigger to point at it, call show() and close() on the component instead; bind:open is there to report the state rather
than to set it.
Keyboard entry and custom wording
modeToggle adds the header button that swaps the calendar for a text field, for
people who would rather type. title replaces the supporting line above the headline,
and headline overrides the formatted date itself. onconfirm fires on the
confirm button, and oncancel on every other way out: the cancel button, Escape, a click on the scrim, or setting open back to false yourself.
<script lang="ts">
import { Button, DatePickerDialog } from 'noph-ui'
const today = new Date()
const isoToday = `${today.getFullYear()}-${`${today.getMonth() + 1}`.padStart(2, '0')}-${`${today.getDate()}`.padStart(2, '0')}`
let entryOpen = $state(false)
let entryValue = $state<string | undefined>()
let submitted = $state('')
</script>
<Button variant="filled" onclick={() => (entryOpen = true)}>Choose arrival</Button>
<DatePickerDialog
bind:open={entryOpen}
bind:value={entryValue}
title="Arrival date"
modeToggle
min={isoToday}
onconfirm={(next) => (submitted = next ? `Arriving ${next}` : '')}
/>
{#if submitted}
<p>{submitted}</p>
{/if}
Range
DateRangePicker scrolls through months continuously and fills the days between the
two ends. The first tap sets the start, the second the end; tapping before the start restarts the
range. value is a { start, end } object of ISO days.
The month list is a window rather than the whole year range: it opens on a few months either side of the start day and grows as you scroll, and each month is only as tall as the week rows it needs. The seven grids share one tab stop, so the list is one stop in the tab order and the arrow keys carry focus from one month into the next.
The picker's presentation depends on the window width. Below 600dp it fills the screen, square
cornered and flat, and confirms from the top bar. From 600dp up it is an ordinary modal instead: a
rounded dialog the width of the calendar, sitting in the scrim with the month list scrolling
inside it and Cancel and Save at the bottom. The switch is a media query,
so the server can render the right one directly. Narrow the window to see it change.
Value: undefined → undefined
<script lang="ts">
import { Button, DateRangePicker } from 'noph-ui'
import type { DateRange } from 'noph-ui/types'
let range = $state<DateRange>({})
</script>
<Button variant="filled" command="show-modal" commandfor="pick-a-range">Pick a range</Button>
<DateRangePicker id="pick-a-range" bind:value={range} title="Select stay" />
<p>Value: <code>{range.start ?? 'undefined'} → {range.end ?? 'undefined'}</code></p>
Two fields
A booking form usually shows the range as two fields rather than a button, and the calendar is
what opens behind them. DateRangePicker is only the popup, so the pair of fields
stays yours: bind the same { start, end } to both, and the range is the single
place the two edges live.
The calendar is the only editor, so the fields are read-only and simply display the range through formatDate. Nothing needs to stay in sync, because the two edges only ever change in
one place. Clicking a field opens the picker, and the calendar button does the same for the
keyboard.
Value: undefined → undefined
<script lang="ts">
import { DateRangePicker, formatDate, IconButton, parseISODate, TextField } from 'noph-ui'
import { Icon } from 'noph-ui/icons'
import type { DateRange } from 'noph-ui/types'
let open = $state(false)
let stay = $state<DateRange>({})
const asText = (iso?: string) => {
const date = parseISODate(iso)
return date ? formatDate(date) : ''
}
</script>
{#snippet calendarButton(edge: string)}
<IconButton
type="button"
aria-label="Open the calendar for the {edge} date"
aria-haspopup="dialog"
aria-expanded={open}
onclick={() => (open = true)}
>
<Icon>calendar_today</Icon>
</IconButton>
{/snippet}
{#snippet startButton()}{@render calendarButton('start')}{/snippet}
{#snippet endButton()}{@render calendarButton('end')}{/snippet}
<TextField
label="Start"
readonly
value={asText(stay.start)}
onclick={() => (open = true)}
end={startButton}
/>
<TextField
label="End"
readonly
value={asText(stay.end)}
onclick={() => (open = true)}
end={endButton}
/>
<DateRangePicker bind:open bind:value={stay} title="Select stay" />
<p>Value: <code>{stay.start ?? 'undefined'} → {stay.end ?? 'undefined'}</code></p>
Theming
Colours and shapes come from the theme, and every part exposes a custom property for the cases the theme cannot reach. Set them on the picker itself; they inherit into the calendar.
| Property | Default |
|---|---|
--np-docked-date-picker-container-color | --np-color-surface-container-high |
--np-docked-date-picker-container-shape | --np-shape-corner-large |
--np-docked-date-picker-container-width | 22.5rem (360dp) |
--np-date-picker-header-color | --np-color-on-surface-variant |
--np-date-picker-weekday-label-color | --np-color-on-surface |
--np-date-picker-date-container-shape | --np-shape-corner-full |
--np-date-picker-date-selected-container-color | --np-color-primary |
--np-date-picker-date-selected-label-color | --np-color-on-primary |
--np-date-picker-date-today-outline-color | --np-color-primary |
--np-date-picker-date-today-label-color | --np-color-primary |
--np-date-picker-menu-selected-container-color | --np-color-surface-variant |
--np-date-picker-year-selected-container-color | --np-color-primary |
--np-date-picker-year-selected-label-color | --np-color-on-primary |
--np-date-picker-range-active-indicator-color | --np-color-secondary-container |
--np-date-picker-range-month-subhead-color | --np-color-on-surface-variant |
--np-date-picker-dialog-container-color | --np-color-surface-container-high |
--np-date-picker-dialog-container-shape | --np-shape-corner-extra-large |
--np-date-picker-dialog-container-width | 22.5rem (360dp) |
--np-date-range-picker-container-color | --np-color-surface full screen, --np-color-surface-container-high as a modal |
--np-date-range-picker-container-shape | --np-shape-corner-none full screen, --np-shape-corner-extra-large as a modal |
--np-date-range-picker-content-width | 25.5rem (408dp) full screen, 22.5rem (360dp) as a modal |
--np-date-range-picker-months-max-height | 20rem (320dp), the modal's scrolling month list |
Example
<script lang="ts">
import { DockedDatePicker } from 'noph-ui'
let themed = $state<string | undefined>('2025-08-17')
</script>
<DockedDatePicker
bind:value={themed}
label="Date"
--np-date-picker-date-selected-container-color="var(--np-color-tertiary)"
--np-date-picker-date-selected-label-color="var(--np-color-on-tertiary)"
--np-date-picker-date-today-outline-color="var(--np-color-tertiary)"
--np-date-picker-date-today-label-color="var(--np-color-tertiary)"
--np-date-picker-date-container-shape="var(--np-shape-corner-small)"
/>
Motion and gestures
Movement follows the Material 3 motion scheme, using the theme's own motion tokens: travel runs on the spatial tokens, fades on the effects tokens.
| What moves | How | Token |
|---|---|---|
| Month change | The grid slides in from the direction of travel and fades up. | --np-motion-expressive-default-spatial |
| Container resize | Height animates as the month's week-row count changes. | --np-motion-expressive-default-spatial |
| Month and year menus | The list slides down over the calendar and fades in from 60% opacity. The calendar stays underneath, so the panel never resizes, and the steppers fade out while it is covered. | --np-motion-expressive-default-effects |
| Day selection | Container and label colours cross-fade. Days inside a range change instantly. | --np-motion-expressive-default-effects |
| Calendar / keyboard entry | The text field slides up from below; the calendar slides down from a 48dp parallax. | --np-motion-expressive-default-spatial |
Swipe horizontally across the calendar to move between months, and scroll the year picker
vertically to move between years. Every transition above is wrapped in prefers-reduced-motion: no-preference, so the picker resizes and swaps views
instantly for anyone who has asked for less motion.
Accessibility
The grid is a role="grid" table named after the month it shows, with the weekday
names as column headers and a single roving tab stop, so the calendar is one stop in the tab order
rather than forty-two. Each day is labelled with its full date, today carries aria-current="date", and the selected day is aria-selected on its cell
and names itself "…, selected" so the state is announced on the day that has focus. selectedDateLabel translates that suffix.
| Key | Moves |
|---|---|
| ← → | One day |
| ↑ ↓ | One week |
| Home End | Start or end of the week |
| Page Up Page Down | One month |
| Shift + Page Up/Page Down | One year |
| Enter Space | Select the focused day |
| Esc | Close the calendar |
Navigating past the edge of the month moves to the neighbouring one and keeps focus on the day it
lands on, in the range picker too. A key that would leave the min and max window stops on the bound instead. The label strings are all props, including cancelLabel, confirmLabel, openCalendarLabel, selectedDateLabel and the month and year navigation labels, so a localised app can translate
the whole control.
While a month or year list covers the calendar, the grid is inert, so the list, the actions and nothing else are what Tab reaches. Picking from the list hands focus back to the grid.
The modal picker opens with focus on the grid rather than on the dialog, so the arrow keys work
straight away, and it names itself with its title.
API
Methods
All four pickers export the same pair, the one every overlay in the library exports. Bind a
reference with bind:this and type it with ReturnType<typeof DockedDatePicker> or whichever picker it is; it is undefined until the component has mounted, so call through ?..
Reach for these only where there is nothing to point a trigger at. DatePickerDialog and DateRangePicker are native <dialog> elements, so command="show-modal" and commandfor open them from markup with no script at all. The docked pickers keep their
calendar in a popover of their own, with no id to point at, so they need these.
| Method | Type | Description |
|---|---|---|
show | () => void | Opens the picker. Already open, it does nothing, and on a disabled or readonly docked field it does nothing either. |
close | () => void | Closes the picker and leaves focus where it is. Only a close the person asked for, through the field or the cancel button, hands focus back to the input. |
DockedDatePicker
Anything not listed here is forwarded to the picker's root element.
| Attribute | Type | Default | Description |
|---|---|---|---|
label | string | 'Date' | Label of the text field. |
variant | 'outlined' | 'filled' | 'outlined' | Text field variant. |
supportingText | string | generated | Replaces the generated MM/DD/YYYY hint. |
issues | { message: string }[] | undefined | Validation messages shown instead of the supporting text. Optimized to use with remote form field issues. |
defaultValue | string | number | null | undefined | Stands in for value while that is unset. Together with an accepted and ignored type, it lets {...field.as('date')} be spread onto the picker. |
locale | string | runtime locale | BCP 47 tag driving names and the input order. |
firstDayOfWeek | number | from locale | First column, 0 = Sunday … 6 = Saturday. |
min / max | string | undefined | Inclusive ISO bounds of the selectable window. |
yearRange | [number, number] | [1900, 2100] | Years offered in the year menu. |
isDateEnabled | (date: Date) => boolean | undefined | Return false to disable a day. |
adjacentMonthDays | boolean | false | Fill the leading and trailing cells with the neighbouring months. |
name / form | string | undefined | Wire the hidden native date input into a form. |
required | boolean | false | Marks the field required for native validation. |
disabled / readonly | boolean | false | Disables the field, or blocks opening the calendar. |
noAsterisk | boolean | false | Hides the asterisk on a required label. |
autocomplete | string | 'off' | Autocomplete hint for the text field. |
openCalendarLabel | string | 'Show date picker' | Accessible name of the calendar toggle. |
invalidDateMessage | string | 'Enter a valid date.' | Validation message reported when the typed text is not a date the picker can take. |
cancelLabel / confirmLabel | string | 'Cancel' / 'OK' | Action button text. |
previousMonthLabel / nextMonthLabel | string | 'Previous month' / 'Next month' | Accessible names of the month steppers. |
previousYearLabel / nextYearLabel | string | 'Previous year' / 'Next year' | Accessible names of the year steppers. |
selectMonthLabel / selectYearLabel | string | 'Select month' / 'Select year' | Accessible names of the menu buttons. |
selectedDateLabel | string | 'selected' | Appended to the accessible name of the selected day. |
onchange | (value?: string) => void | undefined | Fires when the committed value changes. |
Bindables
| Attribute | Type | Description |
|---|---|---|
value | string | null | undefined | Selected day as YYYY-MM-DD. |
displayMonth | string | Month on screen, as an ISO day. Follows value until navigated, and is restored to
what you set when the calendar closes. |
open | boolean | Whether the docked calendar is showing. |
element | HTMLSpanElement | The picker's root element, which is the text field itself. |
DatePickerDialog
Takes the same locale, firstDayOfWeek, min, max, yearRange, isDateEnabled, adjacentMonthDays, label, supportingText, name, form, cancelLabel, confirmLabel, previousMonthLabel, nextMonthLabel, selectYearLabel, selectedDateLabel and onchange props as DockedDatePicker. It has no year steppers or month menu, so those labels do not
apply, and it validates by disabling confirm rather than through the field, so required and invalidDateMessage do not either. On top of the shared props:
| Attribute | Type | Default | Description |
|---|---|---|---|
title | string | 'Select date' | Supporting line above the headline, and the accessible name of the dialog. |
headline | string | formatted date | Overrides the headline text. |
modeToggle | boolean | false | Shows the calendar / keyboard-entry toggle. |
inputModeLabel / calendarModeLabel | string | 'Switch to text input mode' / 'Switch to calendar mode' | Accessible name of that toggle, in each of its two states. |
onconfirm | (value?: string) => void | undefined | Fires when the confirm button is pressed. |
oncancel | () => void | undefined | Fires on any dismissal that is not a confirm, including Escape and the scrim. |
Bindable: value, displayMonth, open and element. Calendar navigation is not kept: the dialog reopens on the month it was
given, or on the month of value.
DateRangePicker
Takes the same locale, firstDayOfWeek, min, max, yearRange, isDateEnabled, adjacentMonthDays and selectedDateLabel props as the other pickers. It has
no text field and no month or year navigation, so none of those labels apply, and it does not submit
with a form.
| Attribute | Type | Default | Description |
|---|---|---|---|
title | string | 'Select range' | Accessible name of the dialog. |
startLabel / endLabel | string | 'Start date' / 'End date' | Headline placeholders before each end is chosen. |
cancelLabel / confirmLabel | string | 'Cancel' / 'Save' | Accessible name of the close button, and the confirm button's text. |
onchange / onconfirm | (value: DateRange) => void | undefined | Both fire when the range is saved, matching the other pickers. |
oncancel | () => void | undefined | Fires on any dismissal that is not a save, including Escape and the scrim. |
Bindable: value (a DateRange), open and element.
Calendar and YearGrid
The two grids the pickers are built from are exported as well, for a layout none of the three
covers, such as a calendar sitting permanently on a page. They are lower level than the pickers:
they hold no value, take Date objects rather than ISO strings, and leave the month on screen,
the selection and the keyboard entry points to the caller.
| Component | Attributes |
|---|---|
Calendar | month and firstDayOfWeek are required. Then selected, rangeStart, rangeEnd, min, max, todayDate and focusedDate as Date objects, plus locale, isDateEnabled, adjacentMonthDays, selectedLabel, weekdays to hide
the column headers, dynamicRows to size the grid to the month rather than
reserve six rows, and a monthSubhead snippet. It reports through onselect, onfocusday and onmonthstep. Several
calendars shown together share one tab stop through tabStopDate and hand focus
across a month boundary through focusRoot. |
YearGrid | yearRange and value are required, with optional minDate, maxDate and onselect. |
Date helpers
The date maths behind the pickers is exported too, so an app can share the same timezone-safe handling.
| Function | Description |
|---|---|
toISODate(date) | Serialises a Date to YYYY-MM-DD from local fields. |
parseISODate(value) | Parses to a local-midnight Date, or undefined if invalid. |
parseDateInput(text, locale) | Parses typed text in the locale's field order. |
formatDate / formatDateMedium / formatDateLong | Numeric, Aug 17, 2025 and full-weekday forms. |
getDatePattern(locale) | The MM/DD/YYYY style hint for a locale. |
getWeekdayLabels / getMonthNames | Localised weekday and month names. |
getFirstDayOfWeek(locale) | Week start as 0 = Sunday … 6 = Saturday. |
getCalendarDays(month, firstDayOfWeek) | The six-week grid for a month. |
addDays / addMonths / startOfMonth | Date maths; addMonths clamps short months. |
isSameDay / isSameMonth / isWithin / compareDays | Day-precision comparisons. |