useDateTimePicker

Hook for combined date and time selection. Extends useDatePicker with time state (hour, minute, second, period) and a nested time picker.

Import

import { useDateTimePicker } from "react-date-range-picker-headless";

Usage

import { useState } from "react";
import { useDateTimePicker } from "react-date-range-picker-headless";
function MyDateTimePicker() {
const [dateTime, setDateTime] = useState<Date | null>(null);
const picker = useDateTimePicker({
value: dateTime,
onChange: setDateTime,
time: { precision: "minute", hourFormat: "24", minuteStep: 5 },
});
return (
<div ref={picker.containerRef}>
<button onClick={picker.handleToggle}>
{picker.displayValue || picker.locale.dateTimePlaceholder}
</button>
{picker.isOpen && (
<div ref={picker.popupRef} onKeyDown={picker.handleKeyDown}>
{/* Calendar (same as useDatePicker) */}
<div>
<button onClick={picker.handlePrevMonth}>{picker.locale.prevMonth}</button>
<span>{picker.locale.formatMonthYear(picker.calendar.month)}</span>
<button onClick={picker.handleNextMonth}>{picker.locale.nextMonth}</button>
</div>
{/* ...calendar grid... */}
{/* Time display */}
<div>
<span>Time: {picker.timeDisplayValue}</span>
</div>
{/* Time controls */}
<div>
<input
type="number"
value={picker.tempHour}
onChange={(e) => picker.handleHourChange(Number(e.target.value))}
/>
<span>:</span>
<input
type="number"
value={picker.tempMinute}
onChange={(e) => picker.handleMinuteChange(Number(e.target.value))}
/>
</div>
<button onClick={picker.handleConfirm}>{picker.locale.confirm}</button>
</div>
)}
</div>
);
}

Options

OptionTypeDefaultDescription
valueDate | nullRequired. Current date-time value.
onChange(dateTime: Date | null) => voidRequired. Called when the date-time changes.
timeTimeConfig{ precision: "minute", hourFormat: "24", minuteStep: 5, secondStep: 1 }Time picker configuration.
minDateDateEarliest selectable date.
maxDateDateLatest selectable date.
localePartial<Locale>DEFAULT_LOCALEOverride locale strings.
initialMonthDateInitial month to display.
sizeDatePickerSizeUI pass-through.
weekStartsOnWeekDay"sunday"First day of the week.
isDateUnavailable(date: Date) => booleanCustom function to disable specific dates.
displayFormatstringCustom format string for the display value.
openbooleanControlled open state.
initialOpenbooleanfalseInitial open state.
onOpenChange(open: boolean) => voidCallback when open state changes.
requiredbooleanfalseWhen true, handleClear is a no-op.
todayDatenew Date()Override today’s date.
onMonthChange(month: Date) => voidCallback when month changes.
disablePastbooleanfalseDisable past dates.
disableFuturebooleanfalseDisable future dates.
showOutsideDaysbooleanfalseShow adjacent month days.
highlightDatesDate[]Dates to highlight.
shouldCloseOnSelectbooleanfalseFor date-time pickers, only applies to preset clicks, not date clicks.
numberOfMonthsnumber1Number of calendar months.
captionLayoutCaptionLayout"buttons"Caption layout mode.
fromYearnumbercurrent year - 100Start year for dropdown.
toYearnumbercurrent year + 10End year for dropdown.

Return Values

Date State

NameTypeDescription
isOpenbooleanWhether the popup is open.
tempDateDate | nullTemporary selected date.
currentMonthDateCurrently displayed month.
localeLocaleResolved locale object.

Time State

NameTypeDescription
isTimePickerOpenbooleanWhether the time picker sub-panel is open.
tempHournumberCurrent temporary hour value.
tempMinutenumberCurrent temporary minute value.
tempSecondnumberCurrent temporary second value.
tempPeriodTimePeriodCurrent AM/PM period ("AM" or "PM").

Date Actions

NameTypeDescription
handleDateClick(date: Date) => voidHandle day cell click.
handlePrevMonth() => voidNavigate to previous month.
handleNextMonth() => voidNavigate to next month.
handleOpen() => voidOpen the popup.
handleClose() => voidClose the popup.
handleToggle() => voidToggle the popup.
handleConfirm() => voidConfirm date + time and close.
handleCancel() => voidCancel and revert.
handleClear() => voidClear the value.
handleGoToToday() => voidNavigate to today.

Time Actions

NameTypeDescription
handleHourChange(hour: number) => voidUpdate the hour.
handleMinuteChange(minute: number) => voidUpdate the minute.
handleSecondChange(second: number) => voidUpdate the second.
handlePeriodChange(period: TimePeriod) => voidToggle AM/PM.
handleTimePickerOpen() => voidOpen the time picker sub-panel.
handleTimePickerClose() => voidClose the time picker sub-panel.
handleTimePickerConfirm() => voidConfirm time picker sub-panel.
handleTimePickerCancel() => voidCancel time picker sub-panel.

Computed

NameTypeDescription
calendarCalendarMonthCalendar data for current month.
calendarsCalendarMonth[]Array of calendar months.
getDayProps(date: Date, referenceMonth?: Date) => DayPropsDay cell props.
displayValuestringFormatted date-time string.
timeDisplayValuestringFormatted time string.
hasValuebooleanWhether a value is confirmed.
canConfirmbooleanWhether confirmation is valid.
containerRefRefObject<HTMLDivElement | null>Container ref.
popupRefRefObject<HTMLDivElement | null>Popup ref.
timePickerRefRefObject<HTMLDivElement | null>Time picker sub-panel ref.
focusedDateDate | nullKeyboard-focused date.
handleKeyDown(e: KeyboardEvent<HTMLElement>) => voidKeyboard handler.
resolvedTimeConfigRequired<TimeConfig>Resolved time configuration with defaults filled in.
yearsnumber[]Years for dropdown mode.
monthsnumber[]Months for dropdown mode.
handleYearSelect(year: number, calendarIndex?: number) => voidSet year.
handleMonthSelect(month: number, calendarIndex?: number) => voidSet month.

Key Behaviors

Time Configuration

The time option accepts a TimeConfig object:

interface TimeConfig {
precision?: "hour" | "minute" | "second"; // default: "minute"
hourFormat?: "12" | "24"; // default: "24"
minuteStep?: 1 | 2 | 3 | 5 | 10 | 15 | 20 | 30; // default: 5
secondStep?: 1 | 2 | 3 | 5 | 10 | 15 | 20 | 30; // default: 1
itemHeight?: number; // default: 32
}

shouldCloseOnSelect

For date-time pickers, shouldCloseOnSelect only triggers on preset clicks, not on date clicks. This is because the user still needs to set the time after selecting a date.

resolvedTimeConfig

The resolvedTimeConfig return value contains the fully resolved time configuration with all defaults filled in. Use this when building time-related UI components to avoid re-computing defaults.