Skip to main content
iVentureTeam

timesheet_uom

timesheet_uom is a dispatcher: it renders every timesheet duration with whichever widget matches your company's timesheet encoding unit, hh:mm for hours, a toggle for days.

August 11, 2026Updated August 11, 20265 min read
Technical nametimesheet_uom
Field typesfloat
Viewsform, list (timesheet views)
Modulehr_timesheet (Timesheets app)
Used in core114 occurrences across timesheet-related modules, including hr_timesheet, sale_timesheet, timesheet_grid, project
VersionsOdoo 20.0, Odoo 19.0, Odoo 18.0, Odoo 17.0, Odoo 16.0
No-code setupThe widget is preset on timesheet views; the rendering follows Settings > Timesheets > Encoding Unit
Alternativesfloat_time, float_toggle, float

What the timesheet_uom widget does

Most widgets decide how a field looks. This one decides which widget decides. On every timesheet duration, the unit_amount float on account analytic lines, Odoo places timesheet_uom, and at render time the component asks the timesheet_uom service which real widget to use.

The mapping, verified in the source, imports three candidates: FloatTimeField for companies encoding in hours (the familiar 08:30), FloatToggleField for companies encoding in days (click through 0 / 0.5 / 1), and FloatFactorField for units needing a conversion factor. The service picks one based on the company's configured encoding unit and hands it the field's props.

That indirection is why one settings change re-skins every timesheet screen consistently, and why this widget needs no per-view configuration anywhere.

What this means for your team

Hours versus days is a business-model choice, not a display preference. Agencies and support teams bill precise hours; consulting and audit firms sell day rates. Odoo respects that with one setting, and this widget is the mechanism that makes the setting take effect everywhere at once: grids, task forms, invoicing previews.

The trap we see in implementations is fighting the dispatcher instead of setting the unit. Teams that want day-based entry sometimes hand-swap widgets on individual timesheet views; the result breaks the first time an updated module ships its own view. Set Encoding Unit to days and every view follows, including ones added by future modules.

The setting is also a data-entry contract: whatever users see, storage remains hours underneath, so utilization reports and sale-order billing stay consistent regardless of the display unit.

Supported options in Odoo 19

Verified against timesheet_uom.js in the Odoo 19.0 hr_timesheet module: the descriptor is { component } and nothing else, no supportedOptions exist. Configuration lives in one place, the company setting below, and the delegated widget brings its own behavior.

OptionTypeWhat it does
(none)n/aThe descriptor declares no supportedOptions; it is a pure dispatcher. Rendering is controlled by Settings > Timesheets > Encoding Unit, and the delegated widget's own behavior applies.

The one control that matters is not an option but a setting: Settings, Timesheets, Encoding Unit (per company). Hours renders hh:mm through float_time, Days renders the 0 / 0.5 / 1 toggle. Because the dispatcher passes standard field props through, the delegated widget's own quirks apply, including float_time's seconds-option key mismatch documented on its page.

Working examples

How core views use it

<field name="unit_amount" widget="timesheet_uom"/>

That is the entire integration: no options, no variants. What renders depends on the company at runtime.

Switching a company to day-based entry

Settings > Timesheets > Time Encoding > Encoding Unit = Days

Every timesheet duration switches from hh:mm inputs to the day toggle, with no view changes anywhere.

Using it on a custom model's hours field

<field name="hours_spent" widget="timesheet_uom"/>

Legal on any float, and your field inherits company-consistent duration rendering. Do this only when the value genuinely follows the timesheet encoding; otherwise use float_time directly and keep the meaning fixed.

One service, three widgets

The dispatch happens per render through the timesheet_uom service, and two consequences follow directly from that design, both verified in the component.

It is company-aware, not view-aware. The service resolves the encoding unit of the active company. In multi-company databases with different encoding units, the same shared view renders hh:mm for one company's users and the day toggle for another's, which is correct behavior and occasionally mistaken for a bug report.

The wrapped widget receives standard props untouched. The dispatcher forwards the field props to whichever component it picked. It adds nothing and filters nothing, so behavior questions are always answered on the delegated widget's page, float_time for hours encoding, the toggle for days. If hh:mm parsing behaves oddly on a timesheet, debug it as a float_time issue.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentNot released. Dispatcher unchanged in the development branch; the underlying float_time changes. See below.
Odoo 19.0VerifiedVerified against the shipped source and tested on a clean database.
Odoo 18.0VerifiedSame behavior. No XML changes needed.
Odoo 17.0VerifiedSame behavior. No XML changes needed.
Odoo 16.0VerifiedSame behavior. No XML changes needed.

Upgrade note. The dispatcher pattern is stable across Odoo 16 to 19, but its file moved within hr_timesheet over the versions, so JavaScript patches importing it by path need re-checking. XML usage is untouched, and the company setting migrates as data.

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 dispatcher itself is unchanged: same service, same three delegated widgets, still no options. What changes is underneath: float_time, which renders the hours case, gains renamed and new options and a typing preview in Odoo 20 (detailed on the float_time page). Hour-encoding companies will therefore see the new time-entry behavior on timesheets without any change to this widget. We re-verify once Odoo 20 ships.

Common problems and fixes

SymptomCause and fix
Timesheets show decimals where hh:mm is expectedThe company's encoding unit is not Hours, or the field lost the widget in a customized view. Check Settings > Timesheets > Encoding Unit, then confirm widget="timesheet_uom" survived the view customization.
Two users see different duration controls on the same viewMulti-company: each user's active company has a different encoding unit. Expected behavior; align the companies' encoding units if consistency is wanted.
Day toggle only offers 0, 0.5 and 1That is the day-encoding toggle's designed value cycle. Users can type other values directly; or switch encoding to Hours for free-form entry.
Changing the encoding unit did not change old recordsIt never does: storage stays hours; only the entry and display presentation changes. Nothing to fix; totals and billing remain consistent.
Custom timesheet view renders plain floatsThe custom view used widget="float" or omitted the widget on unit_amount. Restore widget="timesheet_uom" instead of hand-picking a widget.

Timesheet_uom widget vs the alternatives

WidgetBest forKey difference
timesheet_uomTimesheet durations that must follow company policyDispatches to float_time, a day toggle, or a factor widget based on the company encoding unit
float_timeDurations that must always render hh:mmFixed formatting, ignores the company encoding setting
float_toggleClick-through preset values like half daysThe widget the dispatcher picks for day encoding; usable directly too
floatPlain decimal quantitiesNo duration semantics at all

The practical test: on real timesheet lines, keep timesheet_uom and control display through the company setting. Reach for float_time directly only when a duration must always render as hh:mm regardless of company policy, such as machine run times.

Frequently asked questions

Why does my Odoo timesheet show 0.5 instead of hours and minutes?+
Your company's timesheet Encoding Unit is set to Days, so the widget renders the day toggle. Switch Settings > Timesheets > Encoding Unit to Hours and every timesheet shows hh:mm entry instead.
How do I make timesheets entry day-based in Odoo?+
One setting: Settings > Timesheets > Encoding Unit = Days. The timesheet_uom widget re-renders every duration as the 0 / 0.5 / 1 day toggle, with no view changes needed.
Does changing the encoding unit convert my stored timesheet data?+
No. Storage stays in hours; the setting only changes how values are entered and displayed. Reports, utilization and billing keep using the same underlying numbers.
Can I use timesheet_uom on my own custom field?+
Yes, it works on any float and gives you company-consistent duration rendering. Only do it when the field should genuinely follow the timesheet encoding policy; otherwise apply float_time directly.
Does the timesheet_uom widget have options?+
None, verified in the Odoo 19 source: its descriptor registers just the component. All configuration is the company encoding setting, and the delegated widget's behavior applies underneath.
Why do the two companies in my database enter time differently?+
The encoding unit is a per-company setting, and the widget resolves it for the user's active company. Different units per company means different controls on the same screens, by design.

Billing in days but tracking in chaos?

Timesheet encoding, approval flows and sale-order billing have to agree with each other before invoices go out. We configure and extend Odoo Timesheets end to end, from encoding policy to invoiced hours, on Odoo 16 through 19.

Book a free consultation

How this page was produced

The dispatcher behavior was read from the Odoo 19.0 hr_timesheet module source (timesheet_uom.js): the three imported candidate widgets, the timesheet_uom service calls, and the optionless descriptor. The encoding-unit switch was exercised on a clean Odoo 19 database, where the screenshot was captured. The Odoo 20 statement comes from the same file on the public development branch, where it is unchanged. Spotted an error? Tell us and we will correct the page.