Datepicker

A date, a range, a week, a month, a quarter or a year, picked from a panel or typed into the field.

Usage

When to use a date picker, which mode to pick, and the props that change what the reader can pick.

When to use

Use a date picker when the reader has to find the date on a calendar: a check-in, a deadline, a report window. When the date is one they already know, or one of a few fixed options, another field is faster.
  • Three number fields for a date the reader knows by heart, like a birthday or a card expiry. Typing it is quicker than paging back through years.
  • Calendar when the reader is reading a month with events on it, not filling in a field.
  • Select when there are only a handful of fixed dates, like four delivery slots.
  • Two separate pickers instead of a RangePicker when the two ends are decided at different times, or one of them is often empty.

Picker modes

picker sets which panel opens and what one click picks: date (the default), week, month, quarter, year or time.
  • Match the mode to the decision. A monthly report picked with picker="month" cannot be off by a day.
  • week still stores a date (a day inside the week) and shows it as a week number. Store the date and label the week.
  • The old DatePicker.MonthPicker, WeekPicker, YearPicker, QuarterPicker and TimePicker statics are not included. Use picker instead, and the time-picker item for a time on its own.
  • Do not change the mode once the field has a value. A date picked as a day means something else when read back as a month.

Ranges and times

RangePicker is two fields sharing one panel, which highlights the days in between while the reader picks the second end.
  • Use it when the two ends are chosen together, like a report window or a hotel stay. The second pick is read against the first.
  • Use two pickers bounded by each other's minDate and maxDate when the ends are entered at different times. A range with an open end takes allowEmpty={[false, true]}.
  • When disabled locks one end that has no value, set allowEmpty for that end too, or the other end never commits.
  • order defaults to true, so a range picked backwards still comes back sorted.
  • showTime adds hour, minute and second columns to a date panel. It also turns on the OK button (see Committing the value).
  • multiple does not work with showTime or picker="time", and nothing warns you.

Format and typing

format only changes what the field shows. The value is always a date object, and onChange gives you both the object and the formatted string.
  • A string formats the field and is what typed text must match: format="YYYY/MM/DD".
  • An array shows the first pattern and accepts all of them when the reader types, so format={["YYYY-MM-DD", "MM-DD-YYYY"]} lets them paste either. This is usually the one to use.
  • A function formats the field and makes it read-only, because the text cannot be parsed back.
  • format={{ format: "YYYY-MM-DD", type: "mask" }} splits the field into segments that arrow keys step through. It helps keyboard entry and gets in the way of pasting. It supports YYYY, MM, DD, HH, mm, ss and SSS.
  • Use the placeholder to show the format to type, like “YYYY-MM-DD”. The label already says which date it is.
  • Leave format off to let the locale decide the order of day, month and year.

Limiting what can be picked

minDate and maxDate set a window. disabledDate sets a rule, like no weekends.
  • minDate and maxDate also disable the header arrows that would page out of the window. disabledDate only grays out cells, so prefer the window when it is enough.
  • Two fields that bound each other need no callback: give the start field maxDate={end} and the end field minDate={start}.
  • disabledDate runs for every cell on every render. Keep it fast: reading a Set is fine, calling an API is not.
  • It receives (date, { type, from }). type is the open panel, so a rule written for days can gray out whole years in the year panel. from is the end already picked in a range, which is how you cap the length of a stay.
  • Say why a date is unavailable, in help text under the field or in renderExtraFooter. A gray cell does not explain itself.

Presets

presets adds a column of shortcuts beside the panel, each { label, value }.
  • Pass value a function for anything relative to today, so it is worked out on click. A value computed at render goes stale if the panel stays open past midnight.
  • Keep it to three to five presets, named by the window: “Last 30 days”, not “Today minus 29”.
  • Presets suit a RangePicker best, where one click fills both ends.
  • Presets cannot be reached with the keyboard, so offer the same windows another way too. See the Accessibility tab.

Committing the value

needConfirm decides whether a pick commits at once or waits for an OK button. It defaults to true when the panel has a time (showTime or picker="time") and false otherwise.
  • Keep the default for times. Picking a time takes several clicks, and committing on the first would save an hour with no minutes.
  • Turn it on for a plain date when a change is expensive, like one that reloads a dashboard.
  • Turn it off for a time only when the value is cheap to change, like a filter.
  • Save on onChange, which is the commit. onCalendarChange fires on every click before it.

Variant, status and size

variant (outlined, filled, borderless, underlined), status (error, warning) and size work as they do on every other input.
  • Use one variant across a form. A picker that looks different from the text field beside it reads as a different kind of control. Set it once on the provider, not per field.
  • Inside a Form.Item, status is set from the item's validation, so do not set it by hand there.
  • Pair status with help text that says what is wrong. “Invalid date” and “Outside the booking window” look the same in red.
  • On a RangePicker, disabled takes a pair, [boolean, boolean], to lock one end.

dayjs and time zones

The picker works with dayjs objects. Pass value={dayjs("2026-08-18")}, not the string, and read either the object or the formatted string back from onChange.
  • dayjs is installed with antd, but add it to your own dependencies before you import it. pnpm will not resolve it otherwise. For the same reason DatePickerProps defaults its value type to any. Write DatePickerProps<Dayjs> to narrow it.
  • To use another date library, build a picker with DatePicker.generatePicker and a config for date-fns, luxon or moment. Use that one picker everywhere in the app.
  • The picker has no time zone of its own. A plain dayjs() is in the browser's zone, so a hotel in Istanbul and a guest in Chicago can disagree about which day it is.
  • Pick the zone once for the app. Convert values at the boundary, or add dayjs's utc and timezone plugins and set a default zone.
  • Store a whole-day value (a birthday, a check-in date) as a calendar date string, not a UTC timestamp. Midnight in one zone is the day before in another.
  • disabledDate and minDate compare in the value's zone too. A “no past dates” rule built from the browser's dayjs() can let a reader in another zone pick yesterday.