Skip to main content
iVentureTeam

date

Every date field in Odoo renders through the Date widget. Here is its full option set as shipped in the source: accepted date limits, future warnings, picker precision, display format, and the range pairing the documentation never mentions.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 24, 2026Updated August 24, 20268 min read
Studio nameDate
Technical namedate
Field typesdate
Viewsform, list, kanban
Also registered assame file registers datetime and daterange
Moduleweb, present in every Odoo database
Used in coreThe implicit default for every date field; 3 explicit widget="date" occurrences, in purchase_requisition and l10n_it_edi_doi
VersionsOdoo 20.0, Odoo 19.0, Odoo 18.0, Odoo 17.0, Odoo 16.0
No-code setupYes, via Odoo Studio (Enterprise), including most options
Alternativesdatetime, daterange, remaining_days, formatted_date

What the Date field does

The Date widget is the workhorse nobody names: any fields.Date in any view renders through it automatically, which is why explicit widget="date" appears only three times in core, in views that spell it out for clarity, while the widget itself runs on practically every screen in Odoo. Since Odoo 17 it lives in the same source file as datetime and daterange, one component with three registrations, differing in options and supported types.

In editing state it is a text input plus the calendar overlay; readonly, it prints the formatted date. Two formats exist, the localized long form, Jan 31, 2026, and the numeric form, 31/01/2026, switched by the numeric option. In Odoo 19 list views the widget also declares fixed column widths, one per format, which is why date columns stopped jittering between renders in 19.

What makes the widget worth a reference page is its option surface: seven declared options, three more that only exist in the code, and a picker whose granularity is configurable from days to decades.

What this means for your team

Date fields are where silent data errors breed. A delivery promised for 2062 because someone fat-fingered a year, a birthday in the future, a contract start before the company existed: all of them are one min_date, max_date or warn_future away from impossible. Those three options are the cheapest data validation in Odoo, they live entirely in the view, need no server constraint, and stop the error at the keyboard.

The precision options solve a different business problem: fields that are conceptually a month or a year but stored as dates. A reporting period, a budget year, a planning month. Setting min_precision="months" gives users a month grid instead of a day grid, so nobody has to explain that the day part does not matter.

Worth budgeting a thought for the difference between view-level and database-level rules: min_date guards the picker, not the ORM. Imports, API writes and server code bypass it. When a date rule is a business rule, mirror it in a Python constraint; when it is an entry aid, the widget option alone is the right weight.

Setting it up in Odoo Studio (no code)

Date fields are fully at home in Odoo Studio, and unusually, most of this widget's options are editable there because Odoo declares them with labels and help texts that Studio's properties panel renders directly.

  1. Open the form in Studio.

  2. Drag a Date field from the Add a field panel onto the form, or select an existing date field.

  3. In the Properties panel, the widget is already Date. The panel lists the option set: Earliest accepted date, Latest accepted date, Warning for future dates, Minimal precision, Maximal precision and Date Format.

  4. Type ISO dates or the word today into the accepted-date limits, and pick precisions from the dropdowns. Changes apply to this view immediately.

What Studio cannot do here

Three things stay outside Studio's reach on this widget.

Range pairing. The undocumented start_date_field, end_date_field and always_range options that link two date fields into one range editor are not in the properties panel; they are XML-only, and mostly the territory of the daterange widget.

Dynamic limits. min_date and max_date accept a fixed date or today, nothing record-dependent. A rule like "delivery date after order date" needs a Python constraint or an onchange, not a widget option.

Hard enforcement. Studio edits the view, and view options only guard interactive entry. Data arriving by import, API or automation ignores them, which is the point where a customization adds the matching server-side constraint.

Supported options in Odoo 19

Verified against datetime_field.js in the Odoo 19.0 web module, reading both the declared supportedOptions and the extractProps function. The last three rows appear in no documentation and no Studio panel: they are read straight from the code, which shares its extractProps with the daterange widget.

OptionTypeWhat it does
min_datestringEarliest accepted date, ISO-formatted like 2026-01-31, or the literal string today. Blocks both picking and typing earlier dates.(since Odoo 17.0)
max_datestringLatest accepted date, same formats as min_date.(since Odoo 17.0)
warn_futurebooleanShows a warning icon with the message This date is in the future whenever the value lies after today.(since Odoo 17.0)
min_precisionselection: days, months, years, decadesFinest level the picker offers. months turns the picker into a month selector; the stored value becomes the first day of the chosen unit.(default: days)(since Odoo 18.0)
max_precisionselection: days, months, years, decadesCoarsest level the picker can zoom out to, capping navigation.(since Odoo 18.0)
numericbooleanSwitches display from the localized long form (Jan 31, 2026) to the numeric form (31/01/2026), and selects the matching fixed column width in list views.(default: false)(since Odoo 19.0)
placeholder_fieldfield nameDate or char field on the record whose value becomes the placeholder, formatted per the numeric setting when it is a date.(since Odoo 19.0)
start_date_fieldfield nameUndocumented. Pairs this field as the END of a range whose start lives in the named field; the partner field is auto-added to the view, editable. Shared machinery with daterange.(since Odoo 17.0)
end_date_fieldfield nameUndocumented. Pairs this field as the START of a range whose end lives in the named field. Setting both range options logs a console warning and start_date_field wins.(since Odoo 17.0)
always_rangebooleanUndocumented. With a paired field, always renders the two-sided range input even while one side is empty.(default: false)(since Odoo 17.0)

Do not set both range options on one field. If start_date_field and end_date_field are both present, the source logs a console warning and start_date_field wins. Each of the two also injects the partner field into the view's field list automatically, with readonly: false, a detail that occasionally surprises people who see a field they never added being written by the form.

Working examples

Guarded entry: no past dates, warn on far future

<field name="delivery_date" widget="date"
       options="{'min_date': 'today', 'warn_future': True}"/>

Past dates become unpickable and unparseable; future dates work but carry the warning icon with "This date is in the future".

A month selector on a date field

<field name="period_start" widget="date"
       options="{'min_precision': 'months'}"/>

The picker opens on the month grid and never descends to days.

Compact numeric display for dense lists

<field name="invoice_date" widget="date" options="{'numeric': True}"/>

The hidden range pairing

<field name="date_start" widget="date"
       options="{'end_date_field': 'date_end'}"/>

One widget now edits both fields as a range, with the paired field pulled into the view automatically. This is the same machinery daterange formalizes, exposed here through options the documentation does not list.

today, precision, and the knobs that share a file

What "today" really does. The limit parser special-cases the literal string today and passes it through to the picker, which resolves it at open time. Any other value goes through date deserialization, so a typo like 2026-13-01 is an invalid limit, not a fallback to no limit. Keep limits ISO-formatted or literal today.

The future warning is day-based. warn_future compares the value against today, so tomorrow already warns. The message and icon render per input, and on a paired range each side is checked independently.

Precision is a picker constraint, not a storage change. With min_precision="months" the user picks a month and Odoo stores the first day of it; the field remains a full date. Reports grouping by exact date will show the 1st of each month, which is usually what you want for period fields but worth saying out loud.

One dead knob. extractProps also parses a rounding option, but it configures the time selector, so on a pure date field it changes nothing; it exists here because date, datetime and daterange share one extractProps. If you need it, you are looking for the datetime page.

Dirty-state plumbing. The widget reports dirtiness over the model bus on every render, comparing against the record value with date-aware equality. That is why abandoning an unchanged picker does not trigger the unsaved-changes banner, while typing one character does.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentNot released. Option set unchanged on the development branch; adds relative typing like +=7. See below.
Odoo 19.0VerifiedVerified against the shipped source: numeric and placeholder_field added, condensed removed, fixed list column widths.
Odoo 18.0VerifiedAdds min_precision, max_precision and the 18-only condensed option.
Odoo 17.0VerifiedUnified into the datetime component: min_date, max_date, warn_future and the hidden range options arrive; datetime type support dropped.
Odoo 16.0Partial / changedSeparate legacy widget: single datepicker options object, also accepted datetime fields. None of the modern options exist.

Upgrade note for 16 to 17 and later. Odoo 16 had a separate date widget file whose only option was a datepicker object passed to the old bootstrap picker, and it also accepted datetime fields. The 17 rewrite merged date into the unified datetime component, introduced the current option names, and dropped datetime from the supported types, with show_time on the datetime widget taking over that job. Views migrated from 16 with options="{'datepicker': ...}" lose those settings silently; re-express them with the modern options during an Odoo migration. The 18-only condensed option was removed in 19, replaced in spirit by numeric.

What is changing in Odoo 20

Odoo 20 is expected at Odoo Experience in Brussels, 24 to 26 September 2026. What follows reads the public development branch, which is unstable until release; we re-verify against the shipped version before touching the option table above.

The option set is unchanged on master: all seven declared options, the three undocumented range options, and all three registrations carry over as they are today.

Typing gains relative operations. The input runs through a new date operation parser: typing +=7 moves the date seven days forward, -=2w two weeks back, with the smart-date units and days as the default unit. It is the same idea the float widget's +=10 operations introduced in 19, extended to dates, and it lands exactly where power users live, in list-view bulk editing.

Internals are rewritten on the new signals and props system, the placeholder formatting helper is gone, and patches against the 19 component will need review. XML views should carry over untouched.

Common problems and fixes

SymptomCause and fix
min_date or max_date seems ignored on importsWidget options only guard interactive entry; imports and API writes bypass the view. Add a Python constraint for real enforcement.
Both range options set, only one worksThe source warns and prefers start_date_field when both are present. Set exactly one of start_date_field or end_date_field.
A field you never added appears and gets writtenRange pairing injects the partner field into the view with readonly false. Expected behavior of start_date_field and end_date_field.
Users pick a month but the record shows the 1stmin_precision months stores the first day of the selected unit; the field is still a date. Expected; format reports accordingly.
Dates display as Jan 31 style but you want 31/01numeric defaults to false. Set options="{'numeric': True}" on the field.
widget="date" on a datetime field warns in developer modeSince 17, the date widget declares only the date type. Use the datetime widget with show_time false to display a datetime as date-only.
options="{'datepicker': {...}}" stopped working after upgradeThe 16-era option object was dropped in the 17 rewrite. Re-express the rules with min_date, max_date and precision options.

Date field vs the alternatives

WidgetBest forKey difference
dateEvery plain date fieldThe default date input and calendar, with view-level limits and precision control
datetimeTimestamps with a time componentAdds time selection, show_time and seconds handling in the same source file
daterangeStart and end dates edited as one controlThe declared, documented form of the range pairing this widget hides in options
remaining_daysDeadlines shown as Today, Tomorrow, In 3 daysReadonly relative display with urgency coloring instead of an input
formatted_dateCustom readonly date compositionsToken-based display formatting, no editing

The split inside the family: plain dates here, timestamps on datetime, two-field periods on daterange, and countdown-style coloring on remaining_days.

Frequently asked questions

How do I restrict which dates users can pick in Odoo?+
Set options="{'min_date': '2026-01-01', 'max_date': 'today'}" on the field, both accept ISO dates or the literal today. In Studio, the same limits appear as Earliest and Latest accepted date. Remember they guard the UI only; imports need a Python constraint.
How do I warn users about future dates without blocking them?+
Use warn_future. The widget shows a warning icon and the message "This date is in the future" whenever the value is after today, while still accepting the entry. To block instead of warn, use max_date: 'today'.
Can the Odoo date picker select just a month or a year?+
Yes. min_precision="months" (or years, decades) stops the picker at that level, and Odoo stores the first day of the chosen unit. The companion max_precision caps how far users can zoom out.
What is the difference between the date and datetime widgets?+
Same component, different registrations: date supports date fields only and has no time handling, while datetime adds show_time, seconds and interval options for datetime fields. Since Odoo 17 the date widget no longer accepts datetime fields at all.
Can one date field edit a whole range?+
Yes, undocumented but shipped: set end_date_field (or start_date_field) to the partner field's name and the widget becomes a two-sided range editor, auto-injecting the partner field into the view. The daterange widget is the declared interface to the same machinery.
How do I show dates as 31/01/2026 instead of Jan 31, 2026?+
Set options="{'numeric': True}", new in Odoo 19, also available in Studio as Date Format. In list views it selects a narrower fixed column width as well.
Are the widget's limits enforced on the database?+
No. min_date, max_date and warn_future live in the view layer. Records created by import, API, automation or server code skip them entirely, so duplicate any real business rule as an SQL or Python constraint.
What changes for date fields in Odoo 20?+
The development branch keeps every option and registration unchanged and adds relative typing through an operation parser: +=7 advances a week, -=1m goes back a month, defaulting to days. Unstable until the September 2026 release; we re-verify this page then.

Date logic that holds up beyond the picker

View options catch typos; real calendars need more. We implement date rules end to end in Odoo, picker limits mirrored by server constraints, period fields with month precision, and range views that reconcile with reporting, so scheduling data stays trustworthy from form to dashboard.

Get my date handling reviewed

How this page was produced

Every option in the table was read from datetime_field.js in the Odoo 19.0 web module, covering the declared supportedOptions, the shared extractProps, the dynamic fieldDependencies and the both-options console warning, then cross-checked against the 16.0, 17.0 and 18.0 branches for the version table and against the public development branch for the Odoo 20 section, where the relative-typing parser was found. The Studio walkthrough follows the current field properties panel, which renders these labeled options. Spotted a difference on your database? Tell us and we will correct the page.