Skip to main content
iVentureTeam

day_selection

In time off accrual plans, Odoo lets you say on the 30th of April but never on the 31st. That guard is day_selection, an hr_holidays widget that trims a day dropdown to the days its companion month actually has.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 20, 2026Updated August 20, 20265 min read
Technical nameday_selection
Field typesselection
Viewsform
Modulehr_holidays
Used in core4 occurrences across 1 module: hr_holidays (accrual plan carryover and milestone forms)
VersionsOdoo 20.0, Odoo 19.0
No-code setupNo. Studio offers the plain Selection widget; the month filter needs the month_field attribute in XML.
Alternativesselection, date, radio

What the Day Selection widget does

day_selection is a small subclass of the standard selection widget that solves a calendar problem: a day of month dropdown should not offer the 31st when the month is April, or the 30th when it is February.

The widget reads a second field on the same record, named by the month_field attribute, and filters its own selection entries down to the days that month actually has. The cutoff is computed with new Date(2020, month, 0).getDate(), deliberately anchored to 2020, a leap year, so February offers days 1 through 29 rather than 28.

Everything else, rendering, saving, the dropdown itself, is inherited unchanged from the selection widget, and the month field is registered as a field dependency so the record always loads it.

What this means for your team

The widget exists because HR data entry mistakes here are expensive. An accrual plan that grants days on the 31st of a 30 day month silently skips allocations, and nobody notices until an employee's balance is short. Trimming the dropdown makes the invalid configuration impossible to type instead of merely discouraged.

The same pattern applies to any custom model with a month plus day pair: contract anniversary dates, recurring billing days, maintenance schedules. Reusing this widget (or its pattern) beats validating after the fact with constraints.

Supported options in Odoo 19

The widget declares no options. Its single knob is an XML attribute, read in extractProps from attrs.month_field, and it is effectively mandatory: the component declares monthField as a required prop.

OptionTypeWhat it does
month_field (attribute)field nameRequired XML attribute naming the selection field on the same record that holds the month (numeric keys 1 to 12). The widget filters its day entries to that month's length and auto declares the field as a dependency so it is always loaded.(since Odoo 19.0)

month_field is an attribute on the field tag, not an entry in options="{...}". Omitting it renders the widget with a missing prop: the day list falls back to unfiltered and Owl logs a props validation error in debug mode. Always pair the attribute.

Working examples

The biyearly carryover configuration from hr_leave_accrual_views.xml, two day fields each bound to their own month:

<field nolabel="1" name="first_month_day" widget="day_selection"
       month_field="first_month" placeholder="select a day"
       required="frequency == 'biyearly'"/>

<field nolabel="1" name="second_month_day" widget="day_selection"
       month_field="second_month" placeholder="select a day"
       required="frequency == 'biyearly'"/>

For your own model: make the day field a selection with keys 1 to 31, the month field a selection whose values are month numbers, and bind them with the attribute.

Why February keeps 29 days, and other filter mechanics

Two source details determine whether the filter works on custom models:

The month value must be numeric. The filter runs new Date(2020, month, 0), where JavaScript treats the value as a month index for which day 0 yields the previous month's last day. Odoo's accrual month selections store numeric strings (1 through 12), which coerce cleanly; a month selection storing keys like jan would make every comparison false and hide the entire day list.

The comparison is on selection keys. The filter keeps entries where option[0] <= lastDay, comparing the day field's selection keys against the computed day count. Your day selection keys must therefore be the day numbers themselves, as hr_holidays defines them.

The leap year anchor is a quiet product decision: by computing February against 2020 the dropdown always offers the 29th, and Odoo's server side handles the day in non leap years. If your business rule is stricter (never allow 29), this widget will not enforce it.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentNot released. Present in the development branch with mechanical framework changes only; see below.
Odoo 19.0VerifiedWidget introduced; verified against the shipped source and tested on a clean database.
Odoo 18.0Not availableDoes not exist; accrual day fields render as plain selection dropdowns.
Odoo 17.0Not availableDoes not exist.
Odoo 16.0Not availableDoes not exist.

Migrating accrual customizations from 18 to 19: views that used a plain selection for these day fields can adopt the widget by adding widget="day_selection" and the month_field attribute; the fields themselves are unchanged.

What is changing in Odoo 20

Odoo 20 is expected at Odoo Experience in Brussels, 24 to 26 September 2026. The changes below are read from the public development branch and are not final until release.

The widget survives unchanged in behavior. The diff is purely mechanical: the props declaration migrates to the new useProps and selectionFieldProps framework style, with the same required monthField and the same 2020 anchored filter. We will re verify this page against the released branch after the launch.

Common problems and fixes

SymptomCause and fix
The dropdown shows no days at allThe month field's selection keys are not numeric, so the length computation produces NaN and every entry is filtered out. Store month values as numeric keys (1 to 12) in the month selection field.
Props validation error about monthField in debug modeThe month_field attribute is missing on the field tag; the component declares it as a required prop. Add month_field="your_month_field" to the XML.
February offers the 29th and you need it blockedThe filter is computed against 2020, a leap year, by design. Add a server side constraint or override the widget; the source always allows day 29 for February.
Day list does not shrink when the month changesThe widget reads the month from record data; if another widget on the month field does not commit its change, the day list cannot react. Keep the month field in the same view and let it save normally; the day options recompute on render.

Day Selection widget vs the alternatives

WidgetBest forKey difference
day_selectionDay of month dropdowns that must respect a month picked on the same recordFilters selection entries by the companion month's real length, leap year included
selectionPlain dropdowns with no cross field logicOffers every entry regardless of other fields
datePicking a full calendar dateReal date field with a calendar popover instead of two selections
radioShort choice lists shown all at onceRenders buttons side by side and cannot filter by another field

day_selection is the right tool when a day dropdown must respect a month chosen on the same record. When the user should pick a full calendar date, or the value is a real date field, the widgets below fit better.

Frequently asked questions

What does the day_selection widget do in Odoo?+
It renders a day of month selection field as a dropdown whose entries are filtered by a companion month field, so a 30 day month never offers the 31st. It ships in the hr_holidays module for accrual plan carryover dates.
How do I link the day dropdown to my month field?+
Add the month_field attribute on the field tag: <field name="first_month_day" widget="day_selection" month_field="first_month"/>. It is an attribute, not an options entry, and it is required.
Why does February show 29 days?+
The source computes month length against the year 2020, a leap year, on purpose. The dropdown therefore always includes the 29th for February and the server decides what happens in non leap years.
Can I use day_selection outside HR?+
Yes, on any model where hr_holidays is installed: give the day field selection keys 1 to 31 and the month field numeric keys 1 to 12, then bind them with month_field. Both fields must live on the same record.
Is day_selection available in Odoo 18?+
No. The widget is new in Odoo 19; the file does not exist on the 16, 17 or 18 branches, where these fields render as plain selection dropdowns.

Accrual plans that never miscount a day

Time off accruals, carryover rules and month day edge cases are where HR configurations quietly leak days. We implement and audit Odoo HR setups so balances match policy, February 29 included.

Review my time off setup

How this page was produced

This page was verified by reading the Odoo 19.0 hr_holidays source at components/day_selection/day_selection.js, including the extractProps attribute read and the fieldDependencies declaration, and the shipped usages in hr_leave_accrual_views.xml. Absence in earlier versions was checked against the 16.0, 17.0 and 18.0 trees; the Odoo 20 section against the public development branch on the day of writing. Corrections via our contact page are welcome.