← Back to Blog
Development by Featured

Timezones in Odoo, Part 1: What a Timezone Name Actually Is

Timezones in Odoo, Part 1: What a Timezone Name Actually Is

This first post takes apart the thing everybody assumes is simple: what a string like Asia/Saigon actually is, who owns it, and why two organisations disagree about which name is the real one.

Asia/Saigon looks like a plain, permanent name for a place. It is neither. It is a lookup key into a database maintained by volunteers, revised on no fixed schedule, and Vietnam is not alone: eighteen other zones carry the same kind of disagreement between the organisations that name them.

This series is about what that means for Odoo, in four parts, because the answer is spread across four systems that each have their own opinion.

  • Part 1 (this one) — what a timezone name is, who publishes it, and why Asia/Saigon and Asia/Ho_Chi_Minh are both correct answers to different questions.
  • Part 2 — how Python, PostgreSQL, browsers and Odoo each turn that string into an offset, and where they stop agreeing.
  • Part 3 — what Odoo changed about timezones between 2020 and today, and what landed in which branch.
  • Part 4 — what still breaks, what it looks like in a real production database, and what to do about it.

Nothing was deleted

The first thing to correct is the framing everybody starts with, me included. No timezone was removed.

The IANA time zone database, tzdb, has two kinds of entry. A Zone carries real data: offsets, transitions, abbreviations. A Link is an alias pointing at a Zone. Vietnam has had exactly one set of rules since 1975-06-13, and the database records it once:

Link	Asia/Ho_Chi_Minh	Asia/Saigon

That line lives in the backward file, in a section headed “Alternate names for the same location”1. Asia/Saigon and Asia/Ho_Chi_Minh have never been two different times. One is a name for the other.

That date is not arbitrary. Saigon fell on 30 April 1975, ending the war; the two halves of the country were still on different clocks, the south on UTC+8 — the same offset as China and the Philippines — and the north on UTC+7. About six weeks later the offset was unified. The tzdb record puts the transition at 16:00 UTC on 12 June 1975: clocks in the south went from what would have been midnight on the 13th under the old offset back to 23:00 on the 12th under the new one. Reunification was formalised the following year; the clocks had already agreed.

The backward file is optional by construction. Its own header notes that tzdb builds fine with make BACKWARD=, and that downstream users typically ship it anyway. On a machine that does ship it, the result on disk is unremarkable:

/usr/share/zoneinfo/Asia/Saigon -> Ho_Chi_Minh    (11 byte symlink)
/usr/share/zoneinfo/Asia/Ho_Chi_Minh              (351 byte TZif file)

An alias file. What went missing on Ubuntu 24.04 was that symlink, not a timezone.

A short detour into the Vietnam entry

The Zone those aliases point at is worth reading directly, because tzdb is one of the few databases that documents its own reasoning in prose. The Vietnam section of the asia file2 answers three questions people usually guess at.

Why Ho_Chi_Minh and not Ho_Chi_Minh_City. Nothing political, just a field width:

The English-language name of Vietnam’s most populous city is “Ho Chi Minh City”; use Ho_Chi_Minh below to avoid a name of more than 14 characters.

That comment is from Arthur David Olson in 2008. The 14-character budget is a compatibility constraint from older systems, and it is why half of tzdb reads like a truncated gazetteer.

Why one zone covers a country that was two countries. Because tzdb’s cutoff is 1970 and its scope is “places that have agreed since then”:

The Ho Chi Minh entry suffices for most purposes as it agrees with all of Vietnam since 1975-06-13. […] For timestamps in north Vietnam back to 1970 (the tzdb cutoff), use Asia/Bangkok; see the VN entries in the file zone1970.tab. For timestamps before 1970, see Asia/Hanoi in the file ‘backzone’.

So Asia/Hanoi does exist, in backzone, a file most distributions do not ship at all. It carries a different LMT offset (7:03:24 against Ho Chi Minh’s 7:06:30) and a 1954 transition that the southern zone does not have. If you ever wondered why the dropdown offers no Hanoi, that is the reason: for every timestamp Odoo will ever store, Hanoi and Ho Chi Minh City are the same zone.

Where the data comes from. The transition list is sourced to Trần Tiến Bình’s Lịch Việt Nam: thế kỷ XX-XXI, cross-checked against the original decrees — Võ Nguyên Giáp’s 1945 gazette entry moving Vietnam back two hours, Ordinance No. 46 of 1955, Decree No. 362-TTP of 1959 — each with a scan URL in the file. Eight offset changes between 1906 and 1975, every one of them cited.

None of that changes the offset your users see. It does explain the shape of the whole problem. A tzdb identifier is an editorial decision, taken by a small group of volunteers, constrained by things like a 14-character field width and a 1970 cutoff, and revised whenever better evidence turns up — the Vietnam data was last corrected in 2024, from a book someone pointed at on the mailing list. Nothing in tzdb’s own documentation advertises these strings as stable keys.

If that sounds like an odd foundation to build a database column on, John Feminella’s !!Con talk “tzdata: Back to the Future!” is ten minutes on how the database is maintained and how often it moves4. It is the clearest short explanation of why timezone identifiers change at all, which is the assumption every layer in this series turns out to be making.

Was the rename political

The short answer is in the commit, and it is duller than the question. Asia/Saigon was the Zone name until 6bf3a2a08, on 18 March 2008, whose entire message is Saigon -> Ho_Chi_Minh. The diff replaces this line:

-# Saigon's official name is Thanh-Pho Ho Chi Minh, but it's too long.
+# we use Ho_Chi_Minh below to avoid a name of more than 14 characters.

So the file had acknowledged the rename for years and kept Saigon anyway, because the official name did not fit. What changed in 2008 was not the position, it was the willingness to truncate.

And it was not a decision about Vietnam. Olson committed Calcutta -> Kolkata the same day. Same rule, several cities, one afternoon — the tzdb guideline is “use mainstream English spelling” of the current name, and these were the entries that had fallen behind it. Asia/RangoonAsia/Yangon, America/GodthabAmerica/Nuuk and Europe/KievEurope/Kyiv followed later under the same rule.

Where tzdb does design around politics, it says so, and the scope is narrower than people expect7:

Be robust in the presence of political changes. For example, names are typically not tied to countries, to avoid incompatibilities when countries change their name […] or when locations change countries.

Identifiers avoid countries, so that a rename or a change of sovereignty cannot break them. Cities are a different matter: there tzdb follows the current name. Which is worth holding on to for the rest of this series, because nothing here erased anything. The city was renamed in 197610, tzdb caught up in 2008, and Asia/Saigon still resolves today as a Link. What eventually broke production was a Debian packaging decision in 2023 and a CLDR key-stability decision — both technical, both decades downstream of the history.

Why Debian moved the aliases out

Upstream still ships backward. So who stopped shipping it?

Debian did, deliberately, and said so in advance.

The trigger came from tzdb itself. Release 2021b carried the line “Move some backward-compatibility links to ‘backward’"3, part of a longer effort to consolidate zones whose timestamps have agreed since 1970. That reorganisation gave distributions a clean boundary to package against.

Debian took it. As of tzdata 2023c-8, in August 2023, the main tzdata package ships only timezones that follow the current naming rule of geographical region plus city. Everything in backward, every legacy alias including the whole US/* family, moved into a new package called tzdata-legacy5. Debian 12 and Ubuntu 23.10 are where most people first met the change.

The changelog is worth reading, though not for the reason I first assumed. From NEWS.Debian:

This might be needed in case the system provides timezone-aware data over the network (e. g. SQL databases).

That line did not arrive with the split. The split shipped in 2023c-8 in August 2023; the NEWS entry appeared in 2023d-1 in January 2024, after people had already run into it. The bug report asking for this to reach the release notes says so plainly: “People ran into this at the time (#1051973, #1056908), and the response was to add a NEWS.Debian entry.”

So the warning is not a prediction. It is a description written after the fact, which has then sat in a changelog for almost three years — long enough that by the time it would have helped you, nobody was reading it any more.

One aside, because it explains a confusing detail. tzdata-legacy also carries the right/ tree, the leap-second variants of every zone, which is why the package description reads “time zone data for TAI minus ten seconds” even though most people install it for US/Eastern. Two unrelated things in one package, 735 files in total6.

The second organisation

If the story stopped at packaging, it would be an operations problem: old databases meet a new image. It does not stop there, because tzdb is not the only body that publishes timezone identifiers.

Unicode CLDR publishes its own, and browser engines do not agree on whether to use them: Chrome does, Firefox follows IANA instead. Part 2 measures that; what matters here is that a second list exists at all. CLDR keeps them in common/bcp47/timezone.xml9. Vietnam’s entry:

<type name="vnsgn" description="Ho Chi Minh City, Vietnam"
      alias="Asia/Saigon Asia/Ho_Chi_Minh" iana="Asia/Ho_Chi_Minh"/>

The whole mechanism is in those two attributes. The first name in alias is CLDR’s canonical identifier, and it is Asia/Saigon. The separate iana attribute records that IANA disagrees and names Asia/Ho_Chi_Minh as the primary.

CLDR knows about the rename. It is choosing not to follow it, because canonical identifiers are keys and stable keys are the point: CLDR was already using Asia/Saigon when it started, and changing it later would break everything stored under the old name. IANA made the opposite call, on the grounds that current names should stay accurate. Two organisations, two definitions of “canonical”, the same seven-hour offset.

That iana attribute appears only when the two disagree, which makes the file self-documenting. Exactly 19 of its 469 entries carry it, and those 19 are where a CLDR-following browser and current IANA data disagree about what to call the same place:

CLDR canonical IANA primary Location
Asia/Saigon Asia/Ho_Chi_Minh Vietnam
Asia/Calcutta Asia/Kolkata India
Europe/Kiev Europe/Kyiv Ukraine
Asia/Rangoon Asia/Yangon Myanmar
Asia/Katmandu Asia/Kathmandu Nepal
America/Buenos_Aires America/Argentina/Buenos_Aires Argentina
America/Cordoba America/Argentina/Cordoba Argentina
America/Catamarca America/Argentina/Catamarca Argentina
America/Jujuy America/Argentina/Jujuy Argentina
America/Mendoza America/Argentina/Mendoza Argentina
America/Indianapolis America/Indiana/Indianapolis United States
America/Louisville America/Kentucky/Louisville United States
America/Coral_Harbour America/Atikokan Canada
America/Godthab America/Nuuk Greenland
Atlantic/Faeroe Atlantic/Faroe Faroe Islands
Africa/Asmera Africa/Asmara Eritrea
Pacific/Enderbury Pacific/Kanton Kiribati
Pacific/Ponape Pacific/Pohnpei Micronesia
Pacific/Truk Pacific/Chuuk Micronesia

Dhaka is the control case. Its entry reads alias="Asia/Dhaka Asia/Dacca" with no iana attribute, because CLDR’s canonical already matches IANA’s — and sure enough, no browser will hand you Asia/Dacca.

Thirteen countries, and the shape of the list says something. Seven of the nineteen are reorganisations rather than renames: tzdb moved five Argentine cities under America/Argentina/, two US cities under their states, and CLDR kept pointing at the old flat names. Only a handful — Saigon, Calcutta, Kiev, Rangoon — are the political renames people assume this is about. Two of them are in the United States, which tends to surprise people who have filed this under “a problem for other people’s timezones”.

Everywhere else, the two organisations agree and none of this ever surfaces.

What Part 1 establishes

Four facts to carry forward:

  1. Asia/Saigon is an alias, not a zone. Nothing was deleted; an 11-byte symlink stopped being installed.
  2. Which aliases exist on a given machine is a packaging decision, and Debian changed it in August 2023 — with a changelog naming timezone-aware SQL databases as an example of what might need the legacy package back.
  3. CLDR and IANA currently disagree about which of two names is canonical, for 19 zones, and neither list shows any sign of moving toward the other.
  4. IANA’s timezone identifiers are editorial and revisable, and nothing in tzdb’s documentation promises they will stay stable keys. CLDR’s canonical identifiers read as the opposite bet — favouring the old name once it is in use as a key — which is my best explanation for why the two lists diverge, not a policy either project states city by city.

Put together, those four say something uncomfortable: a timezone name is not a value, it is a lookup against a database, and there is more than one database. A string that resolves on one machine is not guaranteed to resolve on the next one, and nothing about the string tells you which.

Nothing has failed yet. It fails in Part 2, where one value passes through four systems that each do that lookup against a different copy.

Ready to get the most out of Odoo?

Whether you are starting a new implementation, upgrading from an older version, or optimizing your current setup — our Odoo-first team is here to help.