Repository navigation
[scheduler] Create plain Date objects and read them in explicit timezones - #24029
Draft
flaviendelangle wants to merge 3 commits into
Draft
flaviendelangle wants to merge 3 commits into
flaviendelangle wants to merge 3 commits into
Conversation
Deploy previewBundle size
Check out the code infra dashboard for more information about this PR. |
Contributor
|
This pull request has conflicts, please resolve those before we can evaluate the pull request. |
flaviendelangle
force-pushed
the
scheduler-plain-js-dates
branch
from
October 28, 2026 14:17
8124816 to
56969f8
Compare
Contributor
|
This pull request has conflicts, please resolve those before we can evaluate the pull request. |
flaviendelangle
force-pushed
the
scheduler-plain-js-dates
branch
from
October 29, 2026 12:34
56969f8 to
0baae09
Compare
…ones - The Scheduler creates plain `Date` objects instead of `TZDate`s tagged with the display or data timezone, and reads them in the timezone it already knows: `buildTemporalPlainDate()`, `processDate()`, `normalizeAllDayBounds()`, `moveToPlainDate()`, `addToAdapterDate()` and `getRecurringOccurrenceKey()` take it as a parameter. - `toJsDate()` and `isSameDay()` are replaced with `getTime()` and day numbers, and `setTimezone()` and `getTimezone()` are no longer called. - `applyDataTimezoneToEventUpdate()` is removed from the recurring events plugin: the changes need no re-tagging. - The plain-date helpers read the real offsets: they no longer copy the offsets `TZDate` reads between -01:00 and 00:00. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Remove `schedulerOtherSelectors.visibleDate`: it re-tagged the visible date with the display timezone, and its consumers only read its instant. - Inline `getDateKey()` into `getRecurringOccurrenceKey()`, its only caller. - Remove the unused `adapter` parameter of `getRecurrenceUntil()`. - Update the comments that still described values tagged with a timezone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
flaviendelangle
force-pushed
the
scheduler-plain-js-dates
branch
from
October 30, 2026 09:58
0baae09 to
ebba318
Compare
Contributor
|
This pull request has conflicts, please resolve those before we can evaluate the pull request. |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Scheduler stops tagging its dates with a timezone: it creates plain
Dateobjects and reads them in the timezone it already knows, the display one or the one of the event.Changes
Dateobjects.createAdapterDate()returns aDateof the instant, instead of aTZDatethatadapter.setTimezone()tagged with the display or data timezone. The processed dates, the occurrences, the navigation and the values passed to the store all use it.TZDateonly comes back if a user passes one in, and the Scheduler only reads its instant.buildTemporalPlainDate(),processDate(),normalizeAllDayBounds(),moveToPlainDate(),addToAdapterDate(),getRecurringOccurrenceKey(),getWeekDayCode(),realignWeeklyByDay()andadjustRRuleForAllMove()take the timezone they read in, instead ofadapter.getTimezone()of their value. The store passes the display timezone or the data timezone of the event, the recurring events read the data timezone, and the navigation the display one.TZDatego.toJsDate()becomesnew Date(adapter.getTime(value))for theZstrings,isSameDay()compares day numbers in the data timezone, andsetTimezone()/getTimezone()are no longer called.applyDataTimezoneToEventUpdate()only re-tagged the dates of a change with the data timezone, so it goes from the recurring events plugin, and the store passes one set of changes to the plugin and to the editing surface.TZDatereads the offsets between -01:00 and 00:00 (as positive, like the -00:44:30 of Africa/Monrovia until 1972) to match the adapter values. With noTZDateleft, they read the offset of the timezone.adapterparameter goes from the helpers that only used it to create dates:createStartOfPlainDate(),createEndOfPlainDate(),createProcessedDate(),createAdapterDateFromWallTime(),getDayListFromPlainDates(),createStartOfPreviousDay()andgetRecurrenceUntil().schedulerOtherSelectors.visibleDategoes: it re-tagged the visible date with the display timezone, and its consumers only read its instant.getDateKey()is inlined intogetRecurringOccurrenceKey(), its only caller.@date-fns/tzbefore the fake clock, as nothing builds aTZDatethere anymore.No file of the BaseTemporal copy changes.
Changelog
Breaking changes
The
valueof the processed dates of the occurrences (onEventEditingStart,getEventAriaLabel, thetimelineEventContentslot anduseEventDialogOccurrence()) and the date passed toonVisibleDateChangeno longer carry the display timezone. Treat them as instants, not as a type to rely on: read the date and the time of a processed date in the display timezone through itskey,minutesInDayandtimestamp. The instants don't change.The offsets between -01:00 and 00:00, used by a few timezones before the 1970s (Africa/Monrovia until 1972), are read as negative. They were read as positive, like
TZDatedoes, which put the events of those years about an hour off.Adapter usage
Counted like in #23943. The references go from 43 on master, since #24021, to 25.
setTimezone,getTimezone,toJsDateandisSameDayare gone, so the Scheduler uses 4 methods instead of 8:getTime,addMilliseconds,dateandisValid.setTimezonegetTimezoneaddMillisecondsdatetoJsDateisSameDaygetTimeaddMillisecondsremains for the paste and the end of an occurrence,dateandisValidfor parsing the event strings, andgetTimereads the instants of the values that come in.Bundle size
Measured from source with esbuild, minified, with third-party packages external and without the error minifier, gzip level 9.
event-calendarevent-calendar-premiumevent-timeline-premiumValidation
pnpm test:unit --project "x-scheduler*" --runandpnpm test:browser --project "x-scheduler*" --runpass. A few tests time out under the load of the full jsdom run and pass on their own.The tests that checked the timezone a value was tagged with check its instant, its processed fields or that it is a plain
Date. The tests that read the values with the adapter getters read theirkey/minutesInDay, or the value tagged by the test itself. Tests still build their inputs withadapter.date(..., timezone), which returnsTZDates, as users can.New tests: the processed dates and
createAdapterDate()return plainDateobjects, the epoch in Africa/Monrovia reads as 23:15:30 on December 31st, 1969, andgetRecurringOccurrenceKey()keys an occurrence on its day in the timezone.A
/simplify-codebasepass on the change removedschedulerOtherSelectors.visibleDate,getDateKey()and the unusedadapterparameter ofgetRecurrenceUntil(), and updated the comments that still described tagged values. It keptcreateAdapterDate(), the one place that decides what the adapter values are, andprocessDate()next tobuildProcessedDate().A review round with Codex and the base-ui-review skill approved without findings.
TypeScript, ESLint and Prettier pass;
pnpm proptypesandpnpm docs:apiwere run (thefeaturesprop of the Event Timeline no longer listsapplyDataTimezoneToEventUpdate).I have followed (at least) the PR section of the contributing guide.
🤖 Generated with Claude Code