Skip to main content
iVentureTeam

time_period_selection

A selection whose labels are written when the page loads. Instead of "last year, month plus one" it says "February 2025", which is the difference between a setting people use and one they avoid.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 27, 2026Updated September 7, 20265 min read
Technical nametime_period_selection
Field typesselection
Viewsform
Modulepurchase_stock, the bridge between Purchase and Inventory
Used in core1 occurrence, the replenishment information dialog in stock
VersionsOdoo 20.0, Odoo 19.0
No-code setupNo. The selection values it rewrites are specific to the replenishment model
Alternativesselection, filterable_selection, dynamic_selection, date

What the time period selector does

When Odoo estimates future demand for a replenishment, it offers to base that estimate on a past period. Expressed as stored selection values those periods are unreadable: last year, last year plus one month, last year plus two, last year's quarter. Nobody can hold that in their head while deciding.

This widget rewrites those four labels into what they actually mean, computed from today's date. Open the dialog in January and the options read as the named months of the previous year; open it in March and they have shifted accordingly.

It also tidies the list. The underlying field carries entries with an empty key or an empty label, used as separators or placeholders, and the widget drops them so the dropdown contains only real choices.

What this means for your team

This is a small piece of interface work with an outsized effect on whether a feature gets used. A buyer choosing a demand baseline needs to compare periods, and comparing "last year plus two" against "last year quarter" is guesswork. Comparing "March 2025" against "Jan-Mar 2025" is not.

It is also a good argument for computing labels in the browser rather than on the server. The months are relative to today, so a server-computed label would be wrong the moment the record was cached or the day rolled over. Doing it at render time makes the question of staleness disappear.

Supported options in Odoo 19

The widget declares no options of its own and inherits the selection widget's descriptor. What it does add is a prop that is never populated, and a set of selection values it recognizes by name. Read from time_period_selection_fields.js and the selection field, Odoo 19.0.

OptionTypeWhat it does
placeholder_fieldfieldInherited from the selection widget. Shows another field's value as a hint when this one is empty.
onChangeprop, not an optionDeclared and called after the standard change handling, but never extracted from the view, so it can only be supplied by a parent component rendering the field directly.(since Odoo 19.0)

The four rewritten values are hardcoded. The widget matches them by key and produces the corresponding label; any other value is passed through unchanged, and any entry whose key is false or whose label is empty is removed. It also declares an onChange prop, but nothing in the descriptor extracts one, so that hook can only be reached by a parent component passing it directly.

Working examples

The core usage

<field name="based_on" class="oe_inline"
       widget="time_period_selection"/>

No options. The widget recognizes the field's selection keys and rewrites the four it knows about.

The keys it rewrites

last_year            # e.g. "January 2025"
last_year_m_plus_1   # e.g. "February 2025"
last_year_m_plus_2   # e.g. "March 2025"
last_year_quarter    # e.g. "Jan-Mar 2025"

Anything else in the selection is shown with its declared label.

Values that disappear

# dropped from the rendered list
(False, "")
("anything", "")

Entries with a false key or an empty label are filtered out before rendering.

Labels computed from today, and a dead callback

The label computation starts from the first day of the current month a year ago, then adds one and two months for the next two options. That means the three month labels are always consecutive and always in the previous year relative to today, regardless of when the record was created.

The quarter label is built with a little more care. It uses short month names for both ends, and only prints the year on the opening month when the range crosses a year boundary, so a quarter inside one year reads as a compact range rather than repeating the year twice.

Two things about this widget are worth knowing if you plan to extend it. It declares a callback prop and calls it after the standard change handling, but the descriptor never extracts one from the view, so the prop can only arrive from a parent component that renders the field directly. In its core usage nothing does, which makes the hook dead in practice.

And its declared display name contains a spelling mistake, present since the widget was added. That string is what appears in developer tooling listing available widgets, so it is worth recognizing rather than assuming you have found a different widget.

Its placement is also slightly unusual: the file lives in the module that bridges Purchase and Inventory, but the only core usage is in an Inventory dialog. Both modules therefore have to be installed for the widget to resolve, which is normally the case but is worth checking on a stripped-down database.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentNot released. Behavior identical on the development branch; the unused callback prop is redeclared in the new syntax.
Odoo 19.0VerifiedFirst version. Verified against the shipped source.
Odoo 18.0Not availableWidget does not exist. The selector showed its stored labels.
Odoo 17.0Not availableWidget does not exist.
Odoo 16.0Not availableWidget does not exist.

Upgrade note. The widget is new in Odoo 19. On Odoo 18 and earlier the period selector showed its stored labels, so an upgrade improves the dialog with the standard views and nothing needs migrating.

What is changing in Odoo 20

Odoo 20 is expected at Odoo Experience in Brussels, 24 to 26 September 2026. The development branch is unstable and this may still change; we re-verify the page after release.

No behavior change. The four rewritten keys, the quarter formatting and the filtering of empty entries are identical. The props move to the new schema syntax, which is where the unused callback prop is redeclared, so it remains present and still unextracted.

Common problems and fixes

SymptomCause and fix
The labels are still the technical onesThe field is not using this widget, or its selection keys are not the four the widget recognizes. Check the widget attribute and the model's selection keys.
The months look wrongThey are computed from today's date, one year back, so they shift as the months pass. Expected. Reload the page if it has been open across a month boundary.
Some options are missingEntries with a false key or an empty label are filtered out. Expected. Give the value a real label if it should be selectable.
The onChange hook never fires my codeThe prop is declared but never extracted from the view. Render the field from a parent component that passes the callback, or patch the descriptor.
Missing widget errorThe bridge module between Purchase and Inventory is not installed. Install both Purchase and Inventory so the bridge module is present.
Tooling shows a misspelled widget nameThe declared display name contains a typo in the source. Nothing to fix; the registered name itself is correct.

Time period selector vs the alternatives

WidgetBest forKey difference
time_period_selectionSelections whose labels only make sense as dates computed from todayRewrites four known keys into real month and quarter names and drops empty entries
selectionAny selection whose stored labels are already meaningfulNo rewriting and no filtering
filterable_selectionLong selections the user should narrowInteractive filtering rather than computed labels
dynamic_selectionValues sourced from the serverThe server decides the list; here only the labels are computed
datePicking an actual dateA calendar rather than a fixed set of relative periods

Use the plain selection widget wherever the stored labels are already meaningful. Where labels depend on today's date, computing them in the browser as this widget does is the right approach; computing them server side produces labels that are wrong as soon as the day changes or the value is cached.

Frequently asked questions

Where do the month names come from?+
They are computed in the browser from today's date, one year back, each time the field renders. That is why they are always correct without any server recomputation.
Which values does it rewrite?+
Four, matched by key: the same month last year, the two following months, and the corresponding quarter. Anything else keeps its declared label.
Why did some options disappear?+
Entries whose key is false or whose label is empty are filtered out, which is how the field's placeholder entries are hidden.
What is the onChange prop for?+
It is declared and called after the standard change handling, but nothing extracts it from the view, so in its core usage it is never supplied. Only a parent component rendering the field directly could use it.
Which module provides it?+
The bridge module between Purchase and Inventory, even though its only core usage is an Inventory dialog. Both apps need to be installed.

Forecasts based on the right stretch of history

Which past period predicts your demand is a business question before it is a setting, and the answer differs by product line. We tune Odoo replenishment and demand estimation on versions 16 through 19.

Book a free consultation

How this page was produced

The four rewritten keys, the date arithmetic, the quarter formatting, the filtering of empty entries, the unextracted callback prop and the display name typo were read from time_period_selection_fields.js on the Odoo 19.0 branch, with the inherited option set read from the selection field in web. The usage comes from stock/wizard/stock_replenishment_info.xml. Version coverage comes from the absence of the file on 16.0, 17.0 and 18.0, and a comparison against the public development branch. Spotted an error? Tell us and we will correct the page.