Tested fix ·

Canada's November 1 time change in MongoDB, Elasticsearch, OpenSearch, Trino and DuckDB: checks and tested fixes

On 1 November 2026 Alberta, the Northwest Territories and Manitoba stop falling back, and British Columbia stops on the same day. From 02:00 local time that morning, software with the old time-zone rules puts Vancouver, Calgary, Edmonton, Inuvik and Winnipeg one hour behind. Morocco changed on 20 September, so old rules are already wrong there. Our runtimes guide covers Java, Go, PHP, Kubernetes CronJobs and MySQL.

These five data platforms each keep their own copy of the time-zone rules and ignore the operating system's copy. Their newest releases still carry old rules, so updating to the latest version before 1 November doesn't fix them:

  • MongoDB 9.0, 8.0 and 7.0: wrong now for Morocco, and from 1 November for British Columbia, Alberta, Inuvik and Manitoba.
  • Elasticsearch 9.5 and 8.19, and OpenSearch 3.9 and 2.19: wrong now for Morocco, and from 1 November for Alberta, Inuvik and Manitoba.
  • Trino 483: wrong now for Morocco, and from 1 November for Vancouver, Edmonton, Inuvik and Winnipeg. Its two copies of the rules already disagree about Vancouver, so date_trunc starts Vancouver's day at 23:00 the evening before. The next release is likely to do the same for Edmonton, Inuvik and Winnipeg.
  • DuckDB 1.5.6 is wrong for Manitoba. 1.4.5 is wrong for all four, and for Morocco now.

What breaks is anything grouped by local day or hour: daily rollups, date_histogram buckets, $dateToString, date_trunc. In Winnipeg, an event between midnight and 01:00 lands on the previous day.

Each platform has a check below and a fix we tested on its current releases. None needs a vendor update. We ran every check and fix on 14 October 2026 on Linux x86-64, using the official container images. ClickHouse's supported releases already carry the new rules (see the table).

Which releases are still wrong

The correct offsets from 1 November 2026 are Vancouver UTC−07, Edmonton and Inuvik UTC−06, and Winnipeg UTC−05. In Morocco (Africa/Casablanca) it has been UTC+00 since 20 September.

Platform, newest releases on 14 OctWhere its rules come fromWrong nowWrong from 1 NovFixed releaseTested fix
MongoDB 9.0.2, 8.0.34, 7.0.45built into the serverMoroccoVancouver, Edmonton, Inuvik, Winnipegnone announced--timeZoneInfo with 2026e zoneinfo
Elasticsearch 9.5.5, 8.19.23the bundled JDK's tzdb.dat (2026b)MoroccoEdmonton, Inuvik, Winnipegnone announcedreplace tzdb.dat
OpenSearch 3.9.0 / 2.19.6the bundled JDK's tzdb.dat (2026b / 2026a)MoroccoEdmonton, Inuvik, Winnipeg (2.19.6 also Vancouver)none announcedsame as Elasticsearch
Trino 483Joda-Time 2.14.2 (2026b) and the bundled JDK (2026a)MoroccoVancouver, Edmonton, Inuvik, Winnipeg484 is not out; see the Trino sectionreplace both copies
DuckDB 1.5.6ICU built into the library (2026d)—Winnipeg2.0.0, planned for 21 October (2026e); no 1.5.x fixICU_TIMEZONE_FILES_DIR
DuckDB 1.4.5 (long-term support)ICU built into the libraryMoroccoVancouver, Edmonton, Inuvik, Winnipegnone (the backport was declined)same as 1.5.6
ClickHouse 26.9.18.11, 26.3.50.11built into the server—nonealready fixednone needed

ClickHouse 25.8, which is out of support, has old rules and ignores the operating system's copy. Moving to a supported release fixes it.

Check and fix: MongoDB

Aggregation operators that take a timezone, such as $dateToString, $dateTrunc and $hour, use the server's rules; we tested $dateToString. Unless mongod is started with --timeZoneInfo, those rules are compiled into the server, and the official images don't set it.

Check. In mongosh:

db.aggregate([{$documents: [{}]}, {$project: {winnipeg: {$dateToString: {date: ISODate("2026-12-15T12:00:00Z"), format: "%H:%M %z", timezone: "America/Winnipeg"}}, casablanca: {$dateToString: {date: ISODate("2026-10-13T12:00:00Z"), format: "%H:%M %z", timezone: "Africa/Casablanca"}}}}])

Stock mongo:8.0 prints winnipeg: '06:00 -0600', casablanca: '13:00 +0100'. Correct is 07:00 -0500 and 12:00 +0000. MongoDB 9.0.2 and 7.0.45 give the same answers as 8.0.34.

Fix. Point mongod at a 2026e zoneinfo directory. Alpine's tzdata package carries 2026e. On each server, or on any machine with Docker before you copy the directory over:

sudo mkdir -p /opt/zoneinfo-2026e
docker run --rm alpine:3.22 sh -c 'apk add -q --no-cache tzdata && tar -C /usr/share/zoneinfo -c .' | sudo tar -C /opt/zoneinfo-2026e -x
sudo chmod -R a+rX /opt/zoneinfo-2026e
TZDIR=/opt/zoneinfo-2026e TZ=America/Winnipeg date -d '2026-12-15 12:00Z' +%H:%M

The last line prints 07:00 if the copy is current. Then start mongod with --timeZoneInfo /opt/zoneinfo-2026e, or set it in mongod.conf:

processManagement:
  timeZoneInfo: /opt/zoneinfo-2026e

With the official image, mount the directory and pass the option:

docker run -d --name mongo -v /opt/zoneinfo-2026e:/opt/zoneinfo-2026e:ro mongo:8.0 --timeZoneInfo /opt/zoneinfo-2026e

Restart each member of a replica set the same way. After the restart, the check gives the correct answers on 9.0.2, 8.0.34 and 7.0.45.

The directory must be readable by the user mongod runs as. If it isn't, mongod won't start, logging failed to load time zone database. Use the operating system's /usr/share/zoneinfo only if the date line above, run with TZDIR=/usr/share/zoneinfo, prints 07:00. That isn't true yet on Debian or Ubuntu: on 14 October their copies were 2026c, and with them MongoDB still showed Inuvik at −07 and Winnipeg at −06.

When to remove it. MongoDB's ticket SERVER-132098, opened on 23 July, updates the built-in rules only to 2026c and has no fix version. Keep the option until a release carries 2026e. Don't let the directory go stale when later time-zone releases come out.

Check and fix: Elasticsearch and OpenSearch

Both look up time zones in the tzdb.dat file of the JDK they ship with, not in the operating system's copy. Their time_zone options (in date_histogram, range queries and the rest) use those rules.

What we saw. In a date_histogram with calendar_interval: day and time_zone: America/Winnipeg, an event at 05:30 UTC on 15 December went into the bucket 2026-12-14T00:00:00.000-06:00. It belongs in 15 December. In Africa/Casablanca, an event at 23:30 UTC on 12 October went into 13 October today.

Check. Print the data version of the bundled JDK. In the official images:

docker exec es sh -c "head -c 16 /usr/share/elasticsearch/jdk/lib/tzdb.dat | grep -ao '20[0-9][0-9][a-z]'"

Replace es with your container's name. For OpenSearch the path is /usr/share/opensearch/jdk/lib/tzdb.dat. 2026e means fixed; Elasticsearch 9.5.5 and OpenSearch 3.9.0 print 2026b. To check behaviour instead, run a Painless script that returns the offset:

curl -s -H 'Content-Type: application/json' localhost:9200/_scripts/painless/_execute -d '{"script":{"source":"ZonedDateTime.ofInstant(Instant.parse(\"2026-12-15T12:00:00Z\"), ZoneId.of(\"America/Winnipeg\")).getOffset().toString()"}}'

{"result":"-06:00"} means old rules; -05:00 means current. On a secured cluster, use https://, your CA (--cacert) and credentials (-u elastic, or your own user).

Fix. Build a 2026e tzdb.dat with the recipe in our Java fix. It uses OpenJDK's own sources and compiler and prints a checksum you can verify: a02e3a23d67255782b11ab81070902235ab564080f0f65ffe2a989cdaa86fe89. Mount the file over the bundled one and restart each node:

docker run -d --name es -v "$PWD/tzdb-2026e.dat:/usr/share/elasticsearch/jdk/lib/tzdb.dat:ro" docker.elastic.co/elasticsearch/elasticsearch:9.5.5

Add your usual settings. For OpenSearch, mount it at /usr/share/opensearch/jdk/lib/tzdb.dat. With the file in place, the date_histogram buckets above were correct on Elasticsearch 9.5.5 and 8.19.23 and on OpenSearch 3.9.0 and 2.19.6. The Painless check printed -05:00 on 9.5.5, 3.9.0 and 2.19.6. The file built for Java 11 to 25 also worked in the JDK 27 that Elasticsearch 9.5.5 and 8.19.23 bundle.

If you run Elasticsearch or OpenSearch with your own JDK (ES_JAVA_HOME or OPENSEARCH_JAVA_HOME), fix that JDK instead. The image or package replaces the bundled file on every upgrade, so keep the mount until a release prints 2026e. The OpenJDK update due on 20 October carries only 2026c, which fixes Alberta and Morocco but not Inuvik or Winnipeg.

Check and fix: Trino

Trino has two copies of the rules: Joda-Time's and the JDK's tzdb.dat. Functions such as hour() and format_datetime() follow Joda-Time's copy, casting to varchar follows the JDK's, and date_trunc depends on both. In 483 Joda-Time's copy is 2026b and the JDK's is 2026a. Neither has the Alberta, Northwest Territories or Manitoba change, so hour(at_timezone(…, 'America/Winnipeg')) for 12:00 UTC on 15 December returns 6 instead of 7. Only Joda-Time's copy has British Columbia's change, so for Vancouver hour() is already right while a cast to varchar shows the old offset.

Both copies must match. We updated only Joda-Time's copy, which is what Trino's development branch has done: it moved to Joda-Time 2.15.0 (2026e) but still builds its image with Temurin 25.0.4, whose data is from April. In that state hour() is right, but date_trunc('day', …) returns 2026-12-14 23:00:00 America/Winnipeg for a time on 15 December. The day starts at 23:00 the previous day. Updating only the JDK's copy moves it to 01:00. If 484 ships as the development branch stands on 14 October, it will behave like the first case for Edmonton, Inuvik and Winnipeg.

Check:

SELECT hour(at_timezone(TIMESTAMP '2026-12-15 12:00:00 UTC', 'America/Winnipeg')), date_trunc('day', at_timezone(TIMESTAMP '2026-12-15 06:30:00 UTC', 'America/Winnipeg'));

Correct is 7 and 2026-12-15 00:00:00 America/Winnipeg. Stock 483 gives 6 and a midnight that prints correctly but is an hour late (06:00 UTC, not 05:00); hour() is the part that shows the error. With only Joda-Time updated, it gives 7 and 2026-12-14 23:00:00.

Vancouver already has the split in stock 483:

SELECT date_trunc('day', at_timezone(TIMESTAMP '2026-12-15 07:30:00 UTC', 'America/Vancouver'));

Correct is 2026-12-15 00:00:00 America/Vancouver. Stock 483 gives 2026-12-14 23:00:00 America/Vancouver.

Fix: replace both. You need the 2026e tzdb.dat from our Java fix and Joda-Time 2.15.0's compiled zones:

curl -fLO https://repo1.maven.org/maven2/joda-time/joda-time/2.15.0/joda-time-2.15.0.jar
unzip -q joda-time-2.15.0.jar 'org/joda/time/tz/data/*' -d joda-2.15.0
docker run --rm --entrypoint cat trinodb/trino:483 /etc/trino/jvm.config > jvm.config
echo '-Dorg.joda.time.DateTimeZone.Folder=/etc/trino/joda-tz' >> jvm.config
docker run --rm --entrypoint sh trinodb/trino:483 -c 'echo $JAVA_HOME'

The jar's SHA-256 is 6bbe1302e5bec0f03eb7e7442334b475bb225361a5498369d6a0a9a472630c33. If you already have your own jvm.config, add the -D line to it instead. The last command prints the bundled JDK's path, /usr/lib/jvm/jdk-25.0.3+9 in 483. Then mount all three on the coordinator and every worker:

docker run -d --name trino \
  -v "$PWD/tzdb-2026e.dat:/usr/lib/jvm/jdk-25.0.3+9/lib/tzdb.dat:ro" \
  -v "$PWD/joda-2.15.0/org/joda/time/tz/data:/etc/trino/joda-tz:ro" \
  -v "$PWD/jvm.config:/etc/trino/jvm.config:ro" \
  trinodb/trino:483

The check then gives 7 and 2026-12-15 00:00:00 America/Winnipeg, the Vancouver query gives 2026-12-15 00:00:00 America/Vancouver, and Morocco is right. On a tarball install, the JDK is whatever you run Trino with: apply the Java fix to it and add the -D line to etc/jvm.config. On 484 or later, the Joda-Time half may already be built in, but the tzdb.dat half is still needed until Trino's JDK carries 2026e.

Check and fix: DuckDB

DuckDB handles time zones (TIMESTAMPTZ, SET TimeZone, timezone()) with the ICU library built into it. It doesn't read the operating system's copy: mounting 2026e zoneinfo changed nothing.

Check. In the DuckDB CLI or any client:

SELECT strftime(timezone('America/Winnipeg', TIMESTAMPTZ '2026-12-15 12:00:00+00'), '%H:%M') AS winnipeg, strftime(timezone('Africa/Casablanca', TIMESTAMPTZ '2026-10-13 12:00:00+00'), '%H:%M') AS casablanca;

Correct is 07:00 and 12:00. DuckDB 1.5.6 gives 06:00 and 12:00; 1.4.5 gives 06:00 and 13:00.

Fix. ICU loads newer time-zone data from a directory named in ICU_TIMEZONE_FILES_DIR. Download ICU's 2026e files from the Unicode Consortium's icu-data repository:

mkdir -p icu-tz-2026e
for f in zoneinfo64 timezoneTypes metaZones windowsZones; do curl -fsSL -o icu-tz-2026e/$f.res https://raw.githubusercontent.com/unicode-org/icu-data/main/tzdata/icunew/2026e/44/le/$f.res; done
sha256sum icu-tz-2026e/*.res

Expected checksums:

5b484c7f02c99d5164208ce84e18fba67c6314d77cf60503e2b19f708b66c6da  icu-tz-2026e/metaZones.res
5e77ce5afb7374a36cbe3be197d0a6deaa919e6f672c2a372f7a9d91b7f8534f  icu-tz-2026e/timezoneTypes.res
b8c3a7adb94fd659f8203ee4af4dc72a4e6b14566baac1855c493096f337184b  icu-tz-2026e/windowsZones.res
5a168fb78cccfc872f9a50e91facf0bf8b7204a6c4f92fe5c64a8165e9e62448  icu-tz-2026e/zoneinfo64.res

Set the variable in the environment that starts the process, with an absolute path:

export ICU_TIMEZONE_FILES_DIR=/path/to/icu-tz-2026e

With it, the check gives 07:00 and 12:00 on 1.5.6 and 1.4.5 in Python, and in the 1.5.6 CLI. Setting os.environ inside Python after import duckdb has no effect, even before the first time-zone query. To check that the files change nothing else, we compared all 638 zones at five instants with and without them. Only the zones named in the time-zone release notes changed.

Or upgrade. DuckDB 2.0.0, planned for 21 October, carries 2026e. It is a major release, and we haven't tested it. The maintainers decided not to put 2026e in another 1.4 or 1.5 release.

When to remove it. Once you run a release that carries 2026e or later, unset the variable so these files don't hold back later updates.

What we did not check

  • Managed services: MongoDB Atlas, Elastic Cloud, Amazon OpenSearch Service, Starburst Galaxy, MotherDuck and ClickHouse Cloud run their own builds.
  • arm64, and installs from deb or rpm packages. These should use the same built-in data as the images, but we didn't run them.
  • Trino 484, which isn't out. We predicted its behaviour from its development branch and reproduced that state on 483.
  • DuckDB 2.0.0, and DuckDB's Node.js, R and JDBC clients, which use the same library.
  • Whether an Elasticsearch or OpenSearch release built with the 20 October JDK appears before 1 November. That JDK would fix Alberta and Morocco, but not Inuvik or Winnipeg.
  • Kibana and OpenSearch Dashboards, which send their own time-zone setting with each query.

Sources