Skip to content

Polyfill: fix Chinese/Dangi calendar at extreme date ranges#3277

Merged
ptomato merged 4 commits intotc39:mainfrom
jessealama:fix/chinese-dangi-extreme-dates
Feb 19, 2026
Merged

Polyfill: fix Chinese/Dangi calendar at extreme date ranges#3277
ptomato merged 4 commits intotc39:mainfrom
jessealama:fix/chinese-dangi-extreme-dates

Conversation

@jessealama
Copy link
Collaborator

@jessealama jessealama commented Feb 18, 2026

Attempt to fix #3081 by using the 19-year Metonic cycle to shift extreme ISO years into ICU4C's safe range before calling Intl.DateTimeFormat, then adjusting the calendar year back. This produces approximate but non-throwing results for dates outside ICU4C's supported range, which should be sufficient for the test262 extreme-dates tests that only check that no error is thrown. Happy to adjust the approach if there's a better way to handle this.

@jessealama jessealama requested a review from ptomato February 18, 2026 10:11
@jessealama jessealama force-pushed the fix/chinese-dangi-extreme-dates branch 2 times, most recently from cc6c51f to 803508f Compare February 18, 2026 10:14
Use Metonic cycle (19-year) offset to shift extreme ISO years into
ICU4C's safe range before calling Intl.DateTimeFormat, then adjust
the calendar year back. Fixes tc39#3081.
@jessealama jessealama force-pushed the fix/chinese-dangi-extreme-dates branch from 803508f to c9d13f2 Compare February 18, 2026 10:17
@codecov
Copy link

codecov bot commented Feb 18, 2026

Codecov Report

❌ Patch coverage is 97.95918% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 98.09%. Comparing base (86a7b46) to head (f9ef3df).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
polyfill/lib/calendar.mjs 97.91% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3277      +/-   ##
==========================================
- Coverage   98.09%   98.09%   -0.01%     
==========================================
  Files          22       22              
  Lines       10457    10504      +47     
  Branches     1808     1813       +5     
==========================================
+ Hits        10258    10304      +46     
- Misses        182      184       +2     
+ Partials       17       16       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Collaborator

@ptomato ptomato left a comment

Choose a reason for hiding this comment

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

Cool, thanks!

This fix means you can probably also add "chinese" and "dangi" to the list of calendars in test/thorough/calendardaymath.js and remove the comment explaining why they need to be skipped.

I like the solution of shifting the year into range. I had a half-started branch for this issue where I did something similar only instead of shifting the year, I made a fake Metonic cycle going into the past and future. I like your solution better.

One thing from my branch that might be helpful to have here, I added a method to helperChinese:

// https://unicode-org.atlassian.net/browse/ICU-23286
isVulnerableTo70000Bug() {
  if (this.vulnerableTo70000Bug === undefined) {
    const formatter = this.getFormatter();
    try {
      Call(IntlDateTimeFormatPrototypeFormatToParts, formatter, [2146851043199999 + 1]);
    } catch {
      this.vulnerableTo70000Bug = true;
    }
    this.vulnerableTo70000Bug = false;
  }
  return this.vulnerableTo70000Bug;
},

(And only do the shifting if this flag is true.) This way, if a runtime ships a fix to the bug, we won't override their data.

@jessealama
Copy link
Collaborator Author

Cool, thanks!

This fix means you can probably also add "chinese" and "dangi" to the list of calendars in test/thorough/calendardaymath.js and remove the comment explaining why they need to be skipped.

I like the solution of shifting the year into range. I had a half-started branch for this issue where I did something similar only instead of shifting the year, I made a fake Metonic cycle going into the past and future. I like your solution better.

One thing from my branch that might be helpful to have here, I added a method to helperChinese:

// https://unicode-org.atlassian.net/browse/ICU-23286
isVulnerableTo70000Bug() {
  if (this.vulnerableTo70000Bug === undefined) {
    const formatter = this.getFormatter();
    try {
      Call(IntlDateTimeFormatPrototypeFormatToParts, formatter, [2146851043199999 + 1]);
    } catch {
      this.vulnerableTo70000Bug = true;
    }
    this.vulnerableTo70000Bug = false;
  }
  return this.vulnerableTo70000Bug;
},

(And only do the shifting if this flag is true.) This way, if a runtime ships a fix to the bug, we won't override their data.

I've incorporated this helper; thanks! I've also ungated the Chinese and Dangi calendars, so they won't be skipped now.

@jessealama jessealama requested a review from ptomato February 19, 2026 10:41
Move the standalone chineseMetonicOffset function into helperChinese as
a metonicOffset method, using `this` instead of the `helper` parameter.
helperDangi inherits it via ObjectAssign spread.

Thanks to ptomato for the suggestion.
Copy link
Collaborator

@ptomato ptomato left a comment

Choose a reason for hiding this comment

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

Thanks!

@ptomato ptomato merged commit 36c370c into tc39:main Feb 19, 2026
10 checks passed
@jessealama jessealama deleted the fix/chinese-dangi-extreme-dates branch February 19, 2026 21:42
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.

Coverage gap: Incorrect behaviour at end of range for Chinese calendar

2 participants