1 of 29

Time Zone Canonicalization

(for Stage 3)

Justin Grant

Invited Expert / volunteer time zone nerd

proposal-canonical-tz repo

Currently Stage 2

Champions

  • Justin Grant @justingrant
  • Richard Gibson @gibson042

Stage 3 Reviewers

  • Daniel Minor @dminor
  • Jordan Harband @ljharb
  • Philip Chimento @ptomato

2 of 29

Agenda

  • Proposal Summary (recap from Stage 2)
  • What happened during Stage 2?
  • Spec text recap
  • Stage 3?

Other info (if needed)

3 of 29

Context & Terms

  • IANA Time Zone Database (TZDB)
    • Industry-wide repository of time zone info
  • CLDR
    • Localization data (incl. time zones) used by ECMAScript, Java, …
    • Based on TZDB, but some variation (e.g. canonical IDs are never updated)
  • Identifier
    • e.g. Europe/Paris, Pacific/Auckland, or UTC
    • Primary identifier: "Zone" in TZDB, e.g. Asia/Kolkata
    • Non-primary identifier: "Link" in TZDB, e.g. Asia/Calcutta
  • Case-normalization
    • Match user-provided IDs to case in IANA TZDB
    • e.g. america/los_angelesAmerica/Los_Angeles
  • Canonicalization
    • Get the Zone, following Links if needed
    • e.g. Europe/KievEurope/Kyiv
    • This proposal is *only* about canonicalization. Identifiers are always case-normalized.

4 of 29

User complaints

5 of 29

Problems to solve

  • Problems caused by IANA TZDB canonicalization changes
    • Implementation divergence����
    • ECMAScript unexpectedly changes programmer input, e.g. Europe/KyivEurope/Kiev
    • Developers are upset by obsolete names, e.g. Calcutta, Kiev, Saigon
    • === is unreliable for comparing IDs across engines, platforms, or time
  • Temporal intensifies these problems by making IDs more discoverable
    • e.g. Temporal.ZonedDateTime shows ID in console, debugger, logs, JSON, etc.

Temporal.TimeZone.from('Asia/Kolkata');

// => Asia/Kolkata (Firefox uses IANA canonicalization)

// => Asia/Calcutta (Chrome/Safari/Node use CLDR)

6 of 29

What we did during Stage 2

  • Landed editorial PRs
  • Finished Test262 tests (and built polyfill to run them)
  • Implementer discussions in GH issues
  • 2x TG2 reviews
    • Don't expand spec changes beyond Stage 2 text
    • Further changes didn't have TG2 consensus
  • No normative spec changes since Stage 1

7 of 29

Proposed solutions (from Stage 2 advancement)

  • Reduce observable impact of canonicalization changes
    • Stop returning canonical IDs when programs provide non-canonical inputs
    • Add Temporal.TimeZone.p.equals to compare IDs, replacing unreliable ===
  • Improve TZDB identifier guidelines for implementers
    • Add spec guidelines for handing future changes (esp. renames)
    • Help implementers converge on a cross-engine set of canonical IDs

8 of 29

Proposed solutions: status

  • Reduce observable impact of canonicalization changes
    • Stop returning canonical IDs when programs provide non-canonical inputs
    • Add Temporal.TimeZone.p.equals to compare IDs, replacing unreliable ===
  • Improve TZDB identifier guidelines for implementers
    • Add spec guidelines for handing future changes (esp. renames)
    • Help implementers converge on a cross-engine set of canonical IDs

Spec:�Complete, unchanged in Stage 2 except minor editorial tweaks from review feedback�

Tests:�Full coverage in tc39/test262#3837 (100% passing via polyfill)

9 of 29

Proposed solutions: status (cont'd)

  • Reduce observable impact of canonicalization changes
    • Stop returning canonical IDs when programs provide non-canonical inputs
    • Add Temporal.TimeZone.p.equals to compare IDs, replacing unreliable ===
  • Improve TZDB identifier guidelines for implementers
    • Add spec guidelines for handing future changes (esp. renames)
    • Help implementers converge on a cross-engine set of canonical IDs

Spec:

Editorial note with recommendations for handling renames.

Text was wordsmithed during Stage 2 but no substantive changes.�

Tests:�n/a (recommendations only; not testable)

10 of 29

Proposed solutions: status (cont'd)

  • Reduce observable impact of canonicalization changes
    • Stop returning canonical IDs when programs provide non-canonical inputs
    • Add Temporal.TimeZone.p.equals to compare IDs, replacing unreliable ===
  • Improve TZDB identifier guidelines for implementers
    • Add spec guidelines for handing future changes (esp. renames)
    • Help implementers converge on a cross-engine set of canonical IDs

No "help implementers converge" normative changes planned in this proposal

  • Best path to V8/JSC success = if CLDR & ICU expose IANA canonical IDs
  • CLDR work is in progress, but unlikely to be complete before 2024+ �(too late for this proposal)

Plan:

  • Continue supporting CLDR/ICU work, V8/JSC can adopt when available
  • Continue discussing in GitHub issues to explore ideas, find consensus
  • Later, propose normative PRs to ECMA-402 to reify implementer changes

11 of 29

Open issues we'll move to 402 or ICU/CLDR

Issue

Status

#25 What if OS reports an ID that ECMAScript doesn't recognize?

No solution has implementer consensus

#16 Windows APIs may differ from ECMAScript canonicalization

No solution has implementer consensus

#9 Intra-country merged zones like America/Montreal

Out of scope; CLDR owns solving it

(may add others)

12 of 29

Spec Text

(no changes since since Stage 2 advancement,

except editorial updates & bug fixes)

13 of 29

Don't canonicalize in Temporal.TimeZone constructor

14 of 29

Don't expect canonical ID in internal factory AO

15 of 29

Don't canonicalize when parsing into a slot value

16 of 29

Don't canonicalize in 402 ZonedDateTime.p.toLocaleString

17 of 29

Don't canonicalize in 402 InitializeDateTimeFormat

18 of 29

Add canonicalization to TimeZoneEquals

19 of 29

New public API: TimeZone.p.equals

20 of 29

Recommended waiting period after IANA renames

21 of 29

Stage 3 Status

  • 👍 Spec is complete
  • 👍 Tests are complete
  • 👍 Polyfill is available
  • Stage 3 reviewers
    • @ptomato (#33) - 👍, if no open issues can cause normative changes
    • @ljharb (#35) - 👍, if no open issues can cause normative changes
    • @dminor (#34) - 👍
  • ECMA-262 editors (#37)
    • @bakkot - 👍
    • @michaelficarra - 👍
    • @syg - 👍

22 of 29

Feedback / questions?

You're also welcome to file & comment on issues in the proposal-canonical-tz repo!

? ? ?

23 of 29

Stage 3?

24 of 29

Stage 3?

If yes: when & how to implement?�

  • Option 1: After Temporal reaches Stage 4?
  • Option 2: At the same time as Temporal, i.e. now?
    • 2a: merge this proposal into Temporal Stage 3 spec?
    • 2b: leave them separate; add a note in Temporal?
  • Option 3: Something else?

25 of 29

Thank You! 🙏

26 of 29

Backup Slides

27 of 29

Ensure offset time zone IDs are normalized

28 of 29

(Probably) not problems

The items below have been mentioned as concerns, but we think they are OK for ECMAScript.

  • IANA's unfortunate merging of unrelated countries into one Zone, e.g. Iceland + Ivory Coast
    • Current ECMAScript implementations rely on zone.tab, which ensures 1+ Zone per country
  • Zone name-change frequency
    • Name changes are relatively rare: averaging <1 per year
  • Performance (see next slide)

29 of 29

Performance notes

  • Fewer than 600 IDs, growing < 5 per year
  • IDs will be case-normalized before storing in internal slots
    • No need to store user-entered strings
    • Slots can be indexes into a table of ~600 ID strings, avg 14 chars each
  • Spec won't require storing both canonical & original ID slots in each instance
    • Can store the original ID, look up canonical ID when needed
    • If ID slots are 2-byte indexes, then ID Canonical ID mapping table would be ~2.5K�(or ~1.5K with 10-bit indexes)
    • Or can eagerly store the canonical ID, adding 10-16 bits per instance
  • No need for TZDB to be dynamically updated
    • Dynamic updates are hard; spec allows but recommends against it