Skip to content

fix: upgrade to polyfill 0.5.1 (wip)#92

Draft
KaiVandivier wants to merge 1 commit into
mainfrom
upgrade-temporal-polyfill
Draft

fix: upgrade to polyfill 0.5.1 (wip)#92
KaiVandivier wants to merge 1 commit into
mainfrom
upgrade-temporal-polyfill

Conversation

@KaiVandivier
Copy link
Copy Markdown
Contributor

This is a big AI attempt to upgrade to @js-temporal/polyfill, and it required remaking the Nepali calendar since the Temporal.Calendar object no longer exists. All the tests and type checks pass, and it seems to be at least mostly working when dropped into the UI library/storybook, but I think there are still things to iron out for the Nepali calendar (like timeZone is undefined errors)

Haven't looked through it thoroughly yet, but it might be useful. Here's the full Claude Code output:


Upgrade: @js-temporal/polyfill 0.4.3 → 0.5.1

Validation

  • Jest: 22 suites, 407 tests passing (matches the 0.4.3 baseline; 4 pre-existing skips)
  • Cucumber: 52 scenarios, 187 steps passing
  • TypeScript: tsc --noEmit clean
  • Lint: 0 errors (4 pre-existing any warnings in convert-date.spec.ts / validate-date-string.ts)
  • Build: yarn build succeeds (package + .d.ts)

Breaking changes in 0.5.1 that drove the work

The 0.5.0 release (June 2024 TC39) cut Temporal's scope at engine-implementer request, with cascading effects here:

0.4.3 API 0.5.x replacement
Temporal.Calendar class + subclassing removed entirely — calendars are strings only
Temporal.CalendarProtocol / CalendarLike: object only string | <existing Temporal value>
Temporal.TimeZone class, Temporal.TimeZone.from gone — use string ids
.calendar, .timeZone (object getters) .calendarId, .timeZoneId (strings)
getISOFields() .withCalendar('iso8601') + individual getters
zdt.toPlainYearMonth() / toPlainMonthDay() go via .toPlainDate() first
Ethiopic era code 'era1' 'ethiopic' (and 'ethioaa' for the older era)
Temporal.YearOrEraAndEraYear / MonthOrMonthCode types not exported anymore
Islamic eraYear getter now returns undefined (we fall back to year)
Temporal.ZonedDateTime.from({...}) without timeZone now throws — timeZone is required
Mixed-calendar toLocaleString({calendar: X}) rejected — date must already be in the target calendar

How Nepali (the custom calendar) was preserved

This was the hard part — 0.5.x has no in-polyfill way to register a user calendar. The Nepali implementation in src/custom-calendars/nepaliCalendar.ts is now a pair of shadow types that live outside Temporal:

  • NepaliPlainDate and NepaliZonedDateTime mirror the Temporal.PlainDate / ZonedDateTime API surface the library uses (year/month/day/eraYear/daysInMonth/dayOfWeek/dayOfYear/monthsInYear/calendarId, plus with, add, subtract, equals, since, withCalendar, toIso/toPlainDate, toString, toLocaleString, toPlainYearMonth).
  • Each instance holds an iso8601-backed Temporal value (for the heavy lifting and timezone math) and cached Nepali fields. The _isoToNepali / _nepaliToIso conversion logic and the NEPALI_CALENDAR_DATA table are unchanged from 0.4.x.
  • A new module src/custom-calendars/calendar-routing.ts exposes polymorphic helpers — plainDateFrom, zonedDateTimeFrom, withCalendar, zonedDateTimeWithCalendar, comparePlainDates — that branch on 'nepali' and return the right type. The rest of the library (hooks, period generation, validators) consumes these instead of Temporal.PlainDate.from({calendar: ...}) or .withCalendar(...).

Public-API impact for downstream consumers

Most exports are calendar-agnostic and unchanged. Two surface-level changes affect anyone who imports types directly:

  1. NepaliCalendar class is gone. It was a Temporal.Calendar subclass that can't exist in 0.5.x. Replaced by NepaliPlainDate / NepaliZonedDateTime shadow classes (not currently re-exported from src/index.ts — they're internal). The customCalendars map no longer contains a calendar: field; only locales + defaultLocale.
  2. PickerOptionsWithResolvedCalendar.calendar is now SupportedCalendar (string) instead of Temporal.CalendarProtocol. Consumers passing this type need to update.

Likely consumer code (@dhis2/ui Calendar / CalendarInput) shouldn't be affected unless it imports NepaliCalendar directly. Worth a manual smoke-test against @dhis2/ui before publishing.

Behavioral notes worth flagging

  • convertFromIso8601 now returns eraYear: year as a fallback when the polyfill omits it (Islamic calendar in particular), preserving the existing contract.
  • useDatePicker re-projects firstZdtOfVisibleMonth to the active calendar before passing it into useNavigation / useCalendarWeekDays. This was implicit in 0.4.x (because .toLocaleString({calendar:X}) did silent reprojection) and is now explicit.
  • Temporal.ZonedDateTime.from({calendar: 'ethiopic', year, era: 'ethiopic'}) raises if both year and era/eraYear are present and inconsistent. useDatePicker now picks one form per calendar.

@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
14 New issues
14 New Code Smells (required ≤ 0)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@KaiVandivier KaiVandivier marked this pull request as draft May 13, 2026 13:54
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.

1 participant