Skip to main content
iVentureTeam

timezone_mismatch

A timezone dropdown that checks itself against your browser and, when they disagree, prints the actual current time in the selected zone next to its name.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 27, 2026Updated September 8, 20266 min read
Technical nametimezone_mismatch
Field typesselection
Viewsform
Moduleweb, present in every Odoo database
Used in core1 occurrence, the timezone on a working schedule in resource
VersionsOdoo 20.0, Odoo 19.0, Odoo 18.0, Odoo 17.0, Odoo 16.0
No-code setupNo. Studio offers a plain selection; the comparison needs the offset option
Alternativesselection, dynamic_selection, filterable_selection

What the timezone mismatch field does

Timezones cause a specific kind of silent error in Odoo: a working schedule, a leave request or a meeting is configured by someone sitting in one zone for a record that belongs to another. Everything saves, the times look right on screen, and the offset shows up later as an appointment an hour out or a shift starting at the wrong time.

This widget makes that visible at the moment of configuration. It renders the ordinary timezone dropdown and additionally compares the record's stored offset against the browser's own offset. If they differ, the field is flagged with an explanatory title on hover.

It goes one step further than a warning. When there is a mismatch, the currently selected option's label is rewritten to include the real current time in that zone. So instead of reading a zone name you may not have a feel for, you see what the clock actually says there right now.

What this means for your team

Working schedules are the highest value place for this. A schedule defines when an employee is available, and it drives leave duration, timesheet validation and planning. Set it in the wrong zone and the errors are subtle: half day leaves that come out as a few hours off, shifts that appear to start before the working day.

The reason a plain warning is not enough is that most people cannot mentally convert a zone name into a time. Printing the current local time next to the zone turns an abstract mismatch into something anyone can check in a second: does that look like the middle of their working day or the middle of their night?

The empty case is the one worth building a habit around. A record with no timezone at all is treated as a mismatch, with a message asking for one to be set. That is deliberate: an unset timezone is more dangerous than a wrong one, because it silently falls back to something else.

Supported options in Odoo 19

Two options are declared on top of the selection widget's own, and both matter. Read from timezone_mismatch_field.js and the selection field, Odoo 19.0.

OptionTypeWhat it does
tz_offset_fieldfieldNames the char field holding the record's timezone offset, formatted as a signed four digit string such as +0530. The widget compares that string against the browser's own offset.(default: tz_offset)
mismatch_titlestringHover text shown when a mismatch is detected. Core replaces the default with advice specific to working schedules. Ignored when the field is empty, which has its own message.(default: a generic warning about the browser timezone)
placeholder_fieldfieldInherited from the selection widget. Shows another field's value as a hint when this one is empty.

The offset field is doing the real work. The widget never resolves the zone name itself; it compares the browser's offset against a formatted offset string that the server put in the companion field. That has a consequence worth knowing: two different timezones sharing the same current offset are considered matching, and a zone whose offset changes with daylight saving will match or mismatch depending on the time of year.

Working examples

The core usage

<field name="tz" widget="timezone_mismatch"
       options="{'tz_offset_field': 'tz_offset',
                  'mismatch_title': 'Timezone Mismatch : This timezone is different
                   from that of your browser.'}"/>

Core passes both options explicitly, even though the offset field name matches the default, and replaces the default message with schedule-specific advice.

Relying on the defaults

<field name="tz" widget="timezone_mismatch"/>

Valid on any model whose offset field is called tz_offset, which is the Odoo convention. The default warning text is used.

The companion field

# on the model
tz = fields.Selection(_tz_get, ...)
tz_offset = fields.Char(compute='_compute_tz_offset')
# produces a string like "+0530"

The offset must be formatted as a signed four digit string; the widget parses it with a regular expression.

Comparing strings, not zones

The mismatch test builds the browser's offset by hand rather than using a library. It takes the browser's offset in minutes, flips the sign, formats the hours and minutes as two padded digits each, prefixes a sign, and compares the resulting string against the value in the offset field. String equality, not arithmetic.

Two behaviors follow. Because the comparison is on the formatted offset, two zones that happen to share an offset are treated as matching, which is usually what you want: a user in one zone configuring a record in another zone at the same offset has nothing to worry about right now. And because the offset is a moment-in-time value, a zone that observes daylight saving can match in summer and mismatch in winter.

The label rewriting is the part that makes the widget useful. When a mismatch is detected, the options list is rebuilt and the currently selected entry gets the local time appended. That time is computed by parsing the stored offset into minutes, subtracting the browser's own offset, and shifting the current time by the difference. Only the selected option is rewritten; the rest of the dropdown is untouched.

The empty case is handled separately and deliberately inverted. If the field itself has no value, the mismatch getter returns true regardless of offsets, and the title getter returns a different message asking the user to set a timezone. So the visual treatment is the same whether the zone is wrong or missing, which is the right emphasis.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentNot released. Behavior identical on the development branch; only the props syntax changes.
Odoo 19.0VerifiedVerified against the shipped source. Byte-identical to Odoo 18.
Odoo 18.0VerifiedIdentical behavior and options.
Odoo 17.0VerifiedSame options. This is where the component moved to the current descriptor style.
Odoo 16.0VerifiedSame options and comparison, with the older component conventions.

Upgrade note. The two options and the behavior have been the same since Odoo 16, so views carry over unchanged. Odoo 17 was where the component moved to the current descriptor style and stopped reading the value from a props shortcut, which affects custom JavaScript patches rather than XML. Odoo 18 and Odoo 19 are byte-identical.

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. Both options, their defaults, the string comparison and the local time appended to the selected label are identical. The only difference is the migration to the new Owl props syntax, where the props are declared with the schema helpers and the selection widget's own props are inlined with a source comment noting that the base is not yet converted.

Common problems and fixes

SymptomCause and fix
The mismatch never triggersThe offset field is empty or not loaded, so the comparison has nothing to work with. Make sure the offset field is computed and present in the view, and that its name matches the option.
A mismatch is flagged for the same countryThe comparison is on the current offset, and daylight saving can put two zones out of step for part of the year. Expected. Check the appended local time to confirm whether it actually matters.
Two different zones are treated as matchingThey share the same current offset, and the widget compares offsets rather than zone names. Expected. If the exact zone matters, verify it rather than relying on the warning.
The warning appears on an empty fieldIntended. An unset timezone is treated as a mismatch, with its own message. Set a timezone on the record.
No local time appears next to the zoneThe time is appended only to the selected option, and only when a mismatch is detected. Nothing to fix; a matching timezone shows the plain label.
An error parsing the offsetThe offset field does not hold a signed four digit string. Format it as +0530 or -0400; the widget parses it with a regular expression.

Timezone mismatch field vs the alternatives

WidgetBest forKey difference
timezone_mismatchTimezone fields on records configured by somebody in another zoneCompares the record's offset with the browser's and prints the selected zone's current local time
selectionA timezone field where a mismatch is harmlessNo comparison, no warning and no local time
dynamic_selectionSelections whose values come from the serverA different way of sourcing the choices, no timezone awareness
filterable_selectionLong selections that need narrowingFilters the values rather than validating them

Use the plain selection widget for a timezone field where a mismatch does not matter, for example on a record that is only ever configured by the person it belongs to. Reach for this one wherever a record's timezone is set by somebody else, which in practice means schedules, employee records and resources.

Frequently asked questions

How does timezone_mismatch decide there is a mismatch?+
It formats the browser's own offset as a signed four digit string and compares it with the value in the offset field named by the tz_offset_field option. It compares offsets, not zone names.
Why does it show a time next to the timezone?+
Because a zone name is hard to sanity check. When a mismatch is detected the widget appends the current local time in the selected zone to that option's label, so you can see immediately whether it looks plausible.
Why is an empty timezone treated as a mismatch?+
Deliberately. An unset timezone silently falls back to something else, which is more dangerous than a wrong one, so the widget flags it with its own message.
Do I have to set the offset field option?+
Only if your model does not use the conventional name. The prop defaults to tz_offset, which is what Odoo models use.
Can two different zones be treated as the same?+
Yes, if they currently share an offset. That is a consequence of comparing offsets, and it also means daylight saving can change the result at different times of year.

Schedules and leave that go wrong by exactly one hour

Timezones, working schedules and leave calculations interact in ways that only show up in payroll. We configure Odoo HR and resource schedules for distributed teams on versions 16 through 19, and test the edge cases before they reach an employee.

Book a free consultation

How this page was produced

The mismatch test, the string comparison, the empty-value behavior and the local time appended to the selected option were read from timezone_mismatch_field.js on the Odoo 19.0 branch, with the inherited option set read from the selection field in the same branch. The usage and its options come from resource/views/resource_calendar_views.xml. Version coverage comes from comparing the file across the 16.0, 17.0 and 18.0 branches and against the public development branch. Spotted an error? Tell us and we will correct the page.