Skip to content

ICU: overlay current IANA tzdata (2026c) onto the data package - #358

Open
robobun wants to merge 1 commit into
mainfrom
farm/20d9f949/icu-tzdata-refresh
Open

ICU: overlay current IANA tzdata (2026c) onto the data package#358
robobun wants to merge 1 commit into
mainfrom
farm/20d9f949/icu-tzdata-refresh

Conversation

@robobun

@robobun robobun commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

ICU 75.1 ships tzdata 2024a. IANA has published several releases since, and shipping the stale one means Bun returns wrong offsets for every zone whose rules changed:

  • America/Asuncion (Paraguay abolished DST in tzdata 2024b) is reported as UTC-4 for half the year when real Paraguay has been permanent UTC-3 since October 2024.
  • America/Coyhaique (new zone in tzdata 2025b) is rejected with RangeError: invalid time zone.
// bun 1.4.0-canary (ICU 75.1, tzdata 2024a)
new Intl.DateTimeFormat("en-US", {
  timeZone: "America/Asuncion", timeZoneName: "longOffset",
}).formatToParts(new Date("2026-07-27T15:00:00Z"))
  .find(p => p.type === "timeZoneName").value
// "GMT-04:00"   (should be "GMT-03:00")

TZ=America/Asuncion bun -e 'new Date("2026-07-27T15:00:00Z").getTimezoneOffset()'
// 240            (should be 180; node and glibc both say 180)

Fix

ICU supports hot-replacing tzdata via four resource bundles (zoneinfo64.res, metaZones.res, timezoneTypes.res, windowsZones.res) that are binary-compatible back to ICU 4.4. This is the documented update path and what Node vendors in deps/icu-small.

This PR:

  • vendors the current (2026c) little-endian builds of those four bundles in icu/tzdata/ (234 KB total, from unicode-org/icu-data@1c3d36e), with a README describing the three-step update;
  • adds a single icupkg --auto_toc_prefix -a call after the existing filter step in each ICU build (Dockerfile, .musl, .android, .freebsd, .windows, build-icu.ps1) to inject them into the data package before it is repacked into libicudata.a / sicudt.lib.

macOS is untouched: it links Apple's system libicucore, whose tzdata follows macOS updates.

Verification

Built ICU 75.1 locally, ran the exact Dockerfile icupkg -r / icupkg -a sequence, repacked with icu/compress-data.ts, and relinked the resulting libicudata.a into a debug Bun:

process.versions.tz                                 -> "2026c"
America/Asuncion @ 2025-07, 2026-03, 2026-07, 2027-01 -> GMT-03:00 (all four)
TZ=America/Asuncion getTimezoneOffset()             -> 180
new Intl.DateTimeFormat("en", {timeZone: "America/Coyhaique"}) -> ok
test/js/web/intl/intl.test.ts                       -> 31/31 pass

Item count is unchanged (3775 before and after the overlay; the four bundles replace existing entries in place). Package size delta is <4 KB.

The bun-side companion (adding process.versions.tz via ucal_getTZDataVersion, plus the regression test and WEBKIT_VERSION bump) is in oven-sh/bun#36042.

ICU 75.1 ships tzdata 2024a. IANA has published several releases since, and
shipping the stale one means Bun returns wrong offsets for every zone whose
rules changed: America/Asuncion (Paraguay abolished DST in 2024b) is reported
as UTC-4 for half the year when real Paraguay has been permanent UTC-3 since
October 2024, and America/Coyhaique (new in 2025b) is rejected outright.

ICU supports hot-replacing tzdata via four resource bundles that are
binary-compatible back to ICU 4.4. Vendor the current (2026c) little-endian
builds of those bundles in icu/tzdata/, and add a single `icupkg -a` step
after the existing filter step in each ICU build to inject them into the
data package before it is linked into libicudata.a / sicudt.lib.

macOS is untouched: it links Apple's system libicucore, whose tzdata follows
macOS updates.
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@robobun, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 10 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: a34a611a-9106-4dd6-9212-c08b51468d73

📥 Commits

Reviewing files that changed from the base of the PR and between d103ebd and b23699a.

📒 Files selected for processing (12)
  • Dockerfile
  • Dockerfile.android
  • Dockerfile.freebsd
  • Dockerfile.musl
  • Dockerfile.windows
  • build-icu.ps1
  • icu/tzdata/README.md
  • icu/tzdata/metaZones.res
  • icu/tzdata/timezoneTypes.res
  • icu/tzdata/tz.lst
  • icu/tzdata/windowsZones.res
  • icu/tzdata/zoneinfo64.res

Comment @coderabbitai help to get the list of available commands.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't find any bugs, but this vendors ~234 KB of binary .res blobs and establishes a new ongoing maintenance step for tzdata, so it's worth a human sign-off on the approach and provenance.

What was reviewed:

  • Confirmed each of the six build scripts has the tzdata directory available at the referenced path (/icu-bun/tzdata, /icu-tzdata, or $ICU_TZDATA_DIR) before the icupkg -a call.
  • The mv filtered → originalicupkg -a filtered original swap preserves the output filename that downstream make/compress-data.ts steps read.
  • All four overlaid bundles are already listed in icu/keep-raw.txt, so compress-data.ts continues to leave them uncompressed.
Extended reasoning...

Overview

The PR overlays a newer IANA tzdata (2026c) onto ICU 75.1's bundled 2024a by vendoring four little-endian .res bundles from unicode-org/icu-data into icu/tzdata/ and injecting them into the ICU data package via icupkg --auto_toc_prefix -a immediately after the existing filter step. The same one-line change is applied consistently across Dockerfile, Dockerfile.musl, Dockerfile.android, Dockerfile.freebsd, Dockerfile.windows, and build-icu.ps1. A README and a 4-line tz.lst are added.

Security risks

The main consideration is that four opaque binary resource bundles (~234 KB) are being checked into the repo. They are stated to come from unicode-org/icu-data at a pinned commit and are pure ICU resource-bundle data (not executable code), which is the same pattern Node.js uses in deps/icu-small. I cannot independently verify the binary contents match upstream, which is one reason a human should look.

Level of scrutiny

Moderate. The build-script edits themselves are mechanical and identical across all six files, and the change is fail-fast (a bad icupkg -a aborts the build). But it touches the ICU data pipeline for every shipped platform and introduces a recurring maintenance obligation (bump on each IANA release), which is a project-level decision a maintainer should acknowledge.

Other factors

  • Paths check out: Dockerfile/.musl/.windows already COPY icu/ /icu-bun/; .android/.freebsd add COPY icu/tzdata /icu-tzdata; build-icu.ps1 derives $ICU_TZDATA_DIR from the script location.
  • The four bundles were already in icu/keep-raw.txt, so the zstd repack step is unaffected.
  • Author reports end-to-end verification (process.versions.tz → 2026c, Asunción/Coyhaique correct, intl tests pass) and item count unchanged at 3775.
  • macOS is intentionally untouched (uses system libicucore).

@github-actions

Copy link
Copy Markdown

Preview Builds

Commit Release Date
b23699ab autobuild-preview-pr-358-b23699ab 2026-07-27 03:21:16 UTC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants