-
Notifications
You must be signed in to change notification settings - Fork 172
Description
Presently, Temporal getters for calendar fields like era, year, monthCode, day, etc. will call into a custom calendar each time the getter is executed. This is inefficient.
An alternative approach is to avoid calling into Calendar during the getter and instead only call the Calendar in the constructor, using a single Calendar.prototype.calculate() function. This function would return an ordinary object with calculated values for getters. In addition to enabling other optimizations and reducing user calls, this would remove the need for 14 functions:
- Temporal.Calendar.prototype.dayOfWeek ( temporalDateLike )
- Temporal.Calendar.prototype.dayOfYear ( temporalDateLike )
- Temporal.Calendar.prototype.daysInMonth ( temporalDateLike )
- Temporal.Calendar.prototype.daysInWeek ( temporalDateLike )
- Temporal.Calendar.prototype.daysInYear ( temporalDateLike )
- Temporal.Calendar.prototype.day ( temporalDateLike )
- Temporal.Calendar.prototype.era ( temporalDateLike )
- Temporal.Calendar.prototype.eraYear ( temporalDateLike )
- Temporal.Calendar.prototype.inLeapYear ( temporalDateLike )
- Temporal.Calendar.prototype.monthCode ( temporalDateLike )
- Temporal.Calendar.prototype.monthsInYear ( temporalDateLike )
- Temporal.Calendar.prototype.month ( temporalDateLike )
- Temporal.Calendar.prototype.weekOfYear ( temporalDateLike )
- Temporal.Calendar.prototype.yearOfWeek ( temporalDateLike )
- Temporal.Calendar.prototype.year ( temporalDateLike )
This issue is adapted from suggestions made by @FrankYFTang to help reduce the size of Temporal to address concerns from implementers (especially Android and Apple Watch) that Temporal's install size and/or in-memory size is too large.
From an initial quick chat with a few of the Temporal champions, we think this is an interesting suggestion!
I've got a few question about this solution. @FrankYFTang, feel free to chime in with answers if you have them:
- Where would the object returned by
calculatebe stored? In a new internal slot on Plain* types and ZDT? - Would that slot be empty for built-in calendars? How much would it increase RAM requirements for the vast majority of objects with built-in calendars?
- Would this new solution support calendar-specific fields? (I'm not sure the current solution supports calendar-specific fields either, but I know that this case is something that @sffc has talked a lot about!)
- Would Temporal shallow-clone the object returned by
calculate, so we're not holding onto an object that could be mutated later? - Would there still be a need for
getISOFields()methods with this approach? - Would implementations really need to store a JS object with all the fields? Or could they optimize storage to leverage the fact that most fields don't require 8-byte numbers? For example, calendars could be constrained to U8 for day, month, monthCode, etc.
To set expectations, a change of this magnitude, especially if there is consensus that this is a better way to implement custom calendars than the current design, is probably beyond what we can accommodate in Temporal V1. It's just too large and would probably push out our implementation timeline by over a year. So the best course of action, if we feel that this is the right custom-calendar solution, may be to ship Temporal V1 with built-in calendars only (see #2826) so we're not locked into a sub-optimal design, and then carefully design this new custom-calendar solution for a follow-up proposal.
This is analogous to the plan for custom time zones after #2826, which is that they'd be better implemented declaratively (ideally based on an existing standard like JSCalendar) in a follow-up proposal after Temporal V1, rather than a sub-optimal, user-code-required design in V1.