Tested fix · Updated

Canada's November 1 time change: which runtimes will still be an hour off, and the tested fixes

On 1 November 2026 Alberta, the Northwest Territories and Manitoba stop falling back. British Columbia decided earlier this year and stops on the same day. From 02:00 that morning, software using the old time-zone rules shows Calgary, Edmonton, Inuvik and Winnipeg one hour behind; copies of the rules older than April 2026 get Vancouver wrong too. A job scheduled for 09:00 in America/Winnipeg runs at 10:00 real local time.

The fix is in the IANA time-zone database release 2026e. pytz, Ruby's tzinfo-data, the JavaScript time-zone libraries, Alpine and Red Hat already ship it. Software that reads the operating system's copy is fixed once the OS package carries 2026e; Debian and Ubuntu were still on 2026c on 13 October. Four runtimes carry their own copy of the database, and updating them before 1 November is not enough:

  • Java. Every current Eclipse Temurin LTS release ships data from April (2026b). The OpenJDK update due on 20 October carries 2026c: it fixes Alberta, but Inuvik and Winnipeg stay wrong until the January 2027 update. Morocco is already wrong on these builds today.
  • Go. No Go release carries 2026d or 2026e, and Go's development branch doesn't either. The next data update is planned for Go 1.28, due February 2027. Programs that use Go's built-in copy of the database are wrong.
  • PHP 8.2 and 8.3. Both branches get security fixes only; 8.3 stays at 2026a and 8.2 at 2024b, so they are also wrong for British Columbia and Alberta.
  • Rust chrono-tz. The latest release (0.10.4) carries 2025b.

Each has a tested fix below that doesn't wait for a vendor release. Node.js also carries its own copy: the current 22 and 24 releases are on 2026c, and you can check yours below. We ran every check and fix on 13 October 2026 on Linux x86-64.

What changes on 1 November

Each province or territory moves to permanent time and stops changing clocks twice a year. The IANA database models all four changes as taking effect on 1 November 2026 at 02:00 local time. Before that date every version of the data gives the same answer; after it, old data is one hour off.

tz releaseChangeZonesCorrect offset from 1 NovOld data shows
2026b (April)British ColumbiaAmerica/VancouverUTC−07UTC−08
2026c (July)AlbertaAmerica/Edmonton, America/YellowknifeUTC−06UTC−07
2026d (11 Sep)Northwest Territories (Inuvik)America/InuvikUTC−06UTC−07
2026e (29 Sep)ManitobaAmerica/Winnipeg, Canada/CentralUTC−05UTC−06

2026c also moved Morocco to permanent UTC+00 from 20 September 2026 (Africa/Casablanca, Africa/El_Aaiun). Data older than 2026c shows UTC+01 there now.

Which runtimes are still wrong

This covers the runtime's own copy of the data, not the operating system's. "Wrong from 1 Nov" assumes you install every release available before then.

RuntimeData in latest release (13 Oct)Still wrong from 1 Nov after updatingWhen a fixed release arrivesTested fix
Eclipse Temurin LTS 8u504, 11.0.32, 17.0.20, 21.0.12, 25.0.4; Debian's OpenJDK (also in distroless/java21)2026bInuvik, Winnipeg (Alberta and Morocco are fixed by the 20 October update, which carries 2026c)January 2027 (8u522, 11.0.34, 17.0.22, 21.0.14, 25.0.6)Replace tzdb.dat
Amazon Corretto 21.0.12, 25.0.42026dWinnipegnot announcedSame as Temurin
Red Hat UBI9 OpenJDK 17/21 images2026enonealready fixednone needed
PHP 8.4.26, 8.5.112026cInuvik, Winnipeg, unless 8.4.27/8.5.12 ship before 1 Novnext release (the 8.4 and 8.5 branches already carry 2026e)PECL timezonedb
PHP 8.3.352026aVancouver, Edmonton, Inuvik, Winnipegnever (security-only branch)PECL timezonedb
PHP 8.2.342024bVancouver, Edmonton, Inuvik, Winnipegnever (security-only branch)PECL timezonedb
Go 1.27.2, built-in data2026cInuvik, WinnipegGo 1.28 (February 2027) at the earliest; don't wait for a 1.27.xShip current zoneinfo
Go 1.26.9 / 1.25.14, built-in data2025c / 2025bVancouver, Edmonton, Inuvik, WinnipegnoneShip current zoneinfo
Rust chrono-tz 0.10.42025bVancouver, Edmonton, Inuvik, Winnipegnone (an open pull request updates to 2026c only)see Rust
Node.js 22.23.3, 24.21.02026cInuvik, Winnipeg, unless a 22.x or 24.x release with 2026e ships before 1 Nov2026e is in Node 26.11.0 and marked for the 22 and 24 linesnone tested here

Already fixed once you update: pytz 2026.5, Ruby tzinfo-data 1.2026.5, moment-timezone 0.6.5, @js-joda/timezone 3.1.0, Joda-Time 2.15.0, and Alpine and Red Hat (UBI9, UBI10) tzdata. Each of these carries 2026e.

Fixed only where the OS has no zoneinfo: Python's zoneinfo module and Rust's jiff read the operating system's copy first. Their own 2026e data (the PyPI tzdata package 2026.5, jiff-tzdb 0.1.9) is used only where the OS has none, such as Windows or an image without tzdata. Otherwise they are as current as the OS: see Base images.

Am I affected?

Java. Print the data version inside your image or on your server. The path is $JAVA_HOME/jre/lib/tzdb.dat in a Java 8 JDK and $JAVA_HOME/lib/tzdb.dat everywhere else.

head -c 16 "$JAVA_HOME/lib/tzdb.dat" | grep -ao "20[0-9][0-9][a-z]"

Anything before 2026e means affected; 2026e means fixed. On 13 October the stock eclipse-temurin:21-jre image printed 2026b.

PHP.

php -r 'echo timezone_version_get(), "\n";'

2026.5 or later means fixed. The official images print 2024.2 (8.2), 2026.1 (8.3) and 2026.3 (8.4 and 8.5). A .1 to .5 suffix maps to the letters a to e. 0.system means PHP uses the operating system's data, as Debian's and Ubuntu's own PHP packages do; see Base images. On Ubuntu 24.04 with its php8.3-cli package, PHP printed 0.system and Inuvik at −07:00.

Node.js.

node -p process.versions.tz

2026e means fixed. On 13 October the official Node 22.23.3 and 24.21.0 images printed 2026c, so Inuvik and Winnipeg are wrong from 1 November.

Go. Go reads the operating system's zoneinfo first and falls back to its own copy only when none is found. A Go binary in a scratch or distroless static image, or one built with -tags timetzdata and run where there is no zoneinfo, uses the built-in copy and is affected. A Go binary on a full OS image is exactly as current as that image's tzdata package (see Base images below).

Any language, offset check. Ask for the UTC offset on 15 December 2026. Correct answers: Edmonton −06:00, Inuvik −06:00, Winnipeg −05:00. For Java, with a JDK 11 or later on the path, run this block as it is. On Java 8, replace the last line with javac Check.java && java Check.

cat > Check.java <<'EOF'
import java.time.*;
public class Check {
  public static void main(String[] a) {
    Instant t = Instant.parse("2026-12-15T12:00:00Z");
    for (String z : new String[]{"America/Edmonton", "America/Inuvik", "America/Winnipeg", "Africa/Casablanca"})
      System.out.println(z + " " + ZoneId.of(z).getRules().getOffset(t));
  }
}
EOF
java Check.java

Stock Temurin 21 prints -07:00, -07:00, -06:00 and +01:00. After the fix it prints -06:00, -06:00, -05:00 and Z.

Fix: Java (Temurin, Debian OpenJDK, Corretto)

Java keeps all its time-zone rules in one file, tzdb.dat. You can build that file yourself from OpenJDK's own sources at the commit that brought in 2026e, using OpenJDK's own compiler for it, and drop it into your JDK. We publish the recipe and the expected checksum, not a binary, so you can verify what you install.

Why you can trust the result. We first used the same recipe on the commits that shipped 2026b: the output is byte-for-byte the tzdb.dat in Temurin 11, 17, 21 and 25. On the commit with 2026d it is byte-for-byte Corretto 21's file. Then we put the 2026e file into Temurin 8, 11, 17, 21 and 25 and compared every one of the 604 zones against the stock file: exactly the 18 zones named in the 2026c, 2026d and 2026e release notes changed, and nothing else.

You need git and Docker. Save this script as build-tzdb.sh. It follows OpenJDK's build rules for this file and runs offline in a container:

#!/bin/bash
# Build an OpenJDK update line's tzdb.dat exactly as its make rules do (GendataTZDB.gmk + CopyInterimTZDB.gmk).
# usage: build-tzdb.sh <git-repo-dir> <commit> <out.dat>   (needs docker + ${BUILD_IMAGE:-eclipse-temurin:21-jdk}; runs offline)
set -euo pipefail
repo=$1 rev=$2 out=$3
w=$(mktemp -d "${TMPDIR:-/tmp}/tzdb.XXXXXX"); mkdir -p "$w/tool" "$w/tzdata"
if git -C "$repo" cat-file -e "$rev:jdk/make/data/tzdata/VERSION" 2>/dev/null; then   # jdk8u layout: self-contained tool
  git -C "$repo" archive "$rev" jdk/make/data/tzdata | tar -x -C "$w/tzdata" --strip-components=4
  git -C "$repo" archive "$rev" jdk/make/src/classes/build/tools/tzdb | tar -x -C "$w/tool" --strip-components=7
else
  d=src/java.base/share/data/tzdata; git -C "$repo" cat-file -e "$rev:$d/VERSION" 2>/dev/null || d=make/data/tzdata
  git -C "$repo" archive "$rev" "$d" | tar -x -C "$w/tzdata" --strip-components=$(( $(tr -cd / <<<"$d" | wc -c) + 1 ))
  git -C "$repo" archive "$rev" make/jdk/src/classes/build/tools/tzdb | tar -x -C "$w/tool" --strip-components=7
  for f in ZoneRules ZoneOffsetTransition ZoneOffsetTransitionRule Ser; do
    git -C "$repo" show "$rev:src/java.base/share/classes/java/time/zone/$f.java" | sed -e "s/package java.time.zone/package build.tools.tzdb/" > "$w/tool/$f.java"
  done
fi
chmod -R a+rwX "$w"
docker run --rm --network none -u "$(id -u):$(id -g)" -v "$w:/w" -w /w ${BUILD_IMAGE:-eclipse-temurin:21-jdk} sh -c \
  'mkdir cls && javac -nowarn -encoding UTF-8 -d cls tool/*.java 2>&1 | grep -v "^Note" ; java -cp cls build.tools.tzdb.TzdbZoneRulesCompiler -srcdir tzdata -dstfile tzdb.dat africa antarctica asia australasia europe northamerica southamerica backward etcetera gmt jdk11_backward'
cp "$w/tzdb.dat" "$out"
echo "$(grep -v '^#' "$w/tzdata/VERSION" | grep -v '^\s*$') $(sha256sum < "$out" | cut -c1-64) $out"

Java 11, 17, 21 and 25 all use the same file. Build it from the jdk25u-dev commit 749c4eb, "8393337: (tz) Update Timezone Data to 2026e":

git clone --filter=blob:none --no-checkout --shallow-since=2026-10-01 https://github.com/openjdk/jdk25u-dev
bash build-tzdb.sh jdk25u-dev 749c4eb5856693ff9a9ae8d8d4fc77cb374fd36c tzdb-2026e.dat

It prints tzdata2026e a02e3a23d67255782b11ab81070902235ab564080f0f65ffe2a989cdaa86fe89 tzdb-2026e.dat. Building from the 2026e commits in jdk11u-dev, jdk17u-dev or jdk21u-dev gives the same checksum. If yours differs, don't install it.

Java 8 needs its own file, from the jdk8u-dev commit 46d5191:

git clone --filter=blob:none --no-checkout --shallow-since=2026-10-01 https://github.com/openjdk/jdk8u-dev
bash build-tzdb.sh jdk8u-dev 46d5191081489a1998575f5aa8edcef4bc76da90 tzdb-2026e-jdk8.dat

Java 8's compiler writes the zones in a different order on each run, so this file's checksum varies. Check the result with Check.java instead. To confirm the recipe for Java 8, we rebuilt the file from the jdk8u-dev commit that shipped 2026b and compared all 604 zones with Temurin 8's shipped file: they are identical.

Install it. In a container image, copy it over the original:

FROM eclipse-temurin:21-jre
COPY tzdb-2026e.dat /opt/java/openjdk/lib/tzdb.dat

On a server, back up $JAVA_HOME/lib/tzdb.dat ($JAVA_HOME/jre/lib/tzdb.dat for a Java 8 JDK), copy the new file in its place and restart the Java processes. To roll back, restore the backup.

What changes. Offsets and instants are correct for all four provinces and territories and for Morocco. Time-zone abbreviations come from a different part of the JDK, so they stay as before: Winnipeg prints -05:00 CST and Edmonton -06:00 MST. If your output depends on those abbreviations, test it. Stock Temurin already prints -07:00 PST for Vancouver.

When to remove it. Delete the override when you move to a release that carries 2026e (January 2027 for the community builds), so it doesn't hold back later data updates.

Other options. Red Hat's UBI OpenJDK images already carry 2026e through the OS tzdata-java package, so switching base image is a valid fix. OpenJDK's tracker also lists 2026e for Oracle's own out-of-band JDK updates; we didn't check those builds, Oracle's TZUpdater tool or its licence terms.

Fix: PHP 8.2, 8.3, and 8.4/8.5 until their next release

The PECL timezonedb extension replaces PHP's built-in data. Version 2026.5 carries 2026e. In the official Debian-based images:

FROM php:8.3-cli
RUN apt-get update && apt-get install -y $PHPIZE_DEPS \
 && pecl install timezonedb-2026.5 \
 && docker-php-ext-enable timezonedb

We tested this on 8.2.34, 8.3.35 and 8.4.26: afterwards timezone_version_get() prints 2026.5 and all four Canadian zones are correct. On PHP 8.4 and 8.5 you can instead update to the next release once it is out, since both branches already carry 2026e.

Fix: Go in scratch and distroless static images

Go uses the operating system's zoneinfo before its built-in copy, so give the image a current one. Alpine's tzdata package carries 2026e:

FROM alpine:3.22 AS tz
RUN apk add --no-cache tzdata

FROM scratch
COPY --from=tz /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=build /app /app
ENTRYPOINT ["/app"]

Replace the build stage and /app with your own. For a distroless static image, replace FROM scratch with it; the copy overwrites the image's own Debian zoneinfo.

We tested this with a Go 1.27.2 binary built with -tags timetzdata. In scratch, without the copy it reports Inuvik −07 and Winnipeg −06; with it, −06 and −05. With gcr.io/distroless/static-debian13 as the final stage, the image's own zoneinfo gives the same wrong −07 and −06, and the copy gives −06 and −05.

On a full Debian- or Ubuntu-based image, Go reads the OS package, which is still 2026c (next section).

We reported the 2026d and 2026e releases on Go's tracking issue for time-zone data, golang/go#22487; the Go team has moved that issue to Go 1.28.

Rust: chrono-tz

chrono-tz 0.10.4, the latest release, carries 2025b. The open pull request #233 updates it to 2026c only, and a maintainer replied there that chrono and chrono-tz are deprecated, linking the project's soft-deprecation notice. jiff reads the system zoneinfo on Unix and carries 2026e (jiff-tzdb 0.1.9) for systems without one. We did not run a chrono-tz program; the data version comes from the crate's own release notes.

Base images: Debian and Ubuntu are on 2026c

.NET, Python's zoneinfo, Rust's jiff, Ruby without tzinfo-data, PHP from Debian's or Ubuntu's own packages, glibc and Go on a full OS image read the operating system's zoneinfo. On 13 October:

Base imagetzdataWrong from 1 Nov
debian:13, debian:12 and images built on them (golang, php, ruby, .NET runtime-deps 8.0/10.0, distroless static-debian13 and java21-debian13), amazonlinux:20232026cInuvik, Winnipeg
ubuntu 22.04, 24.04, 26.04, and eclipse-temurin images (Ubuntu-based)2026cInuvik, Winnipeg
gcr.io/distroless/static-debian12, golang:1.252026bEdmonton, Inuvik, Winnipeg
alpine 3.22 with tzdata, Red Hat UBI9 and UBI10 with tzdata2026enone

On Ubuntu, 2026e is waiting in the proposed pocket. Debian has not yet published it for 12 or 13. Until then, the Alpine copy shown in the Go fix is the tested way to get 2026e into a scratch or distroless static image; we didn't test copying it over a full Debian or Ubuntu image's zoneinfo.

What we did not check

  • arm64, Windows and macOS. Java's tzdb.dat doesn't depend on the processor, so the Java fix should apply unchanged on arm64.
  • Whether Adoptium, Amazon, Microsoft or Azul will publish an out-of-band 2026e build before 1 November. As of 13 October none has announced one.
  • The exact release dates of PHP 8.4.27 and 8.5.12.
  • A running chrono-tz program.
  • Temurin 27, which is not an LTS release. OpenJDK's tracker lists 2026e for 27.0.2.
  • A fix for Node.js 22 or 24 before their next release.
  • Whether Ontario's Rainy River area changes. The IANA data assumes it follows Manitoba, and its notes say a further release may follow for northwestern Ontario.
  • PHP images based on Alpine (we tested the Debian-based ones).

Sources