Should Absolute's getter methods getEpochNanoseconds(), getEpochMicroseconds(), getEpochMilliseconds(), and getEpochSeconds() be property getters (e.g. .epochNanoseconds) instead of methods?
These methods all return primitive number or bigint values so the issues with object identity (see #724) don't apply here.
I assume there is some historical reason why Absolute's getters are methods while other types (e.g. Date.prototype.year) use property getters. But I'm new so don't know the history.
These methods will likely be the most performance-sensitive code in all of Temporal (because it'll be used for timing tasks), so any change should keep perf implications in mind.
_This topic was split out of #724._
I'm trying to catch up with the issues about Absolute and Time zones; there is much to read.
We apparently asked Google C++ developers for suggestions; and they mentioned as first point, being happy to never have exposed the epoch for (what we call now) an Absolute: https://github.com/tc39/proposal-temporal/issues/139
Could you explain why we ignore that suggestion now?
Secondly, could someone refer me to the choice for going with an Absolute, rather than a zoned-datetime (that may also be set to UTC and consequently replace the Absolute)? cc @ptomato
We apparently asked Google C++ developers for suggestions; and they mentioned as first point, being happy to never have exposed the epoch for (what we call now) an Absolute: #139
Could you explain why we ignore that suggestion now?
We don't ignore any suggestions, but neither do they always have to be adopted :smile:
My opinion is that in our case the choice of epoch is anchored by the existing, already exposed, choice of epoch for legacy Date.
There are quite a lot of closed issues discussing about Instant vs. Absolute vs. ZonedDateTime vs. ZonedAbsolute, but maybe these are a good starting point:
I prefer the use of explicit methods. To me, use of fields implies an amount of independence and composibility that does not exist in the case of scaling鈥攅.g., a Temporal.Time instance is an enhanced bag of {hour, minute, second, millisecond, microsecond, nanosecond} (which are exposed accordingly), but that is not true of a Temporal.Absolute instance.
Given the feedback about brevity being the top concern, this seems like an easy way to make common tasks briefer.
I agree with @gibson042 that methods are a little clearer to distinguish compared to data properties vs. convenience properties.
But I'm not sure this clarity benefit outweighs the brevity benefit.
Also we have many other convenience properties throughout Temporal. Like hoursInDay, daysInMonth, etc. DateTime has 8 convenience properties. LDT has those 8 plus a few more like hoursInDay, timeZoneOffsetString, etc. Why are the Absolute convenience properties different?
I had unfortunately missed adding this one to the list of design decisions to complete. It's added now.
I agree with @gibson042.
Could we discuss at the next Champions meeting? My thinking is that brevity is the top user concern and dealing with epochXXX data is one of the top use cases where those users have been complaining about brevity.
Also, still need to answer this question:
Also we have many other convenience properties throughout Temporal. Like hoursInDay, daysInMonth, etc. DateTime has 8 convenience properties. LDT has those 8 plus a few more like hoursInDay, timeZoneOffsetString, etc. Why are the Absolute convenience properties different?
Why are the Absolute convenience properties different?
Admittedly this is more of a vague feeling than a reasoned objection, but to me they feel like methods because they return a value that isn't exact. (That excludes getEpochNanoseconds, which I guess feels like it ought to be a method if the other three are methods.)
My guiding principles here are that only fields should be accessed as properties, and fields should be limited to minimal non-redundant data that fully characterizes an instance (e.g., Temporal.Date is {calendar, era?, year, month, day} and Temporal.Time is {hour, minute, second, millisecond, microsecond, nanosecond}).
There's tension between matching fields & properties and the consistent feedback we've gotten that the current API is too verbose. Furthermore, that verbosity feedback seems concentrated on msecs-since-epoch/legacy-Date-interop use cases which are the exact subject of this issue.
Given that we're using convenience properties exhaustively elsewhere in Temporal, and given the strong feedback we've gotten both for brevty in general and spefically for brevity of epoch-milliseconds, IMHO it seems reasonable to use properties in this case too.
My guiding principles here are that only fields should be accessed as properties
I like @gibson042's idea to have a specific set of guidelines or principles that determine whether something should be a property or method. I'd recommend slightly more flexible principles, though:
===) value when called again laterI like those criteria! but I don't think "inexpensive to calculate" has to matter, as long as it's memoized once computed.
Meeting 2020-10-09: We'll make these methods into property getters.
(Rationale being, that according to the above criteria there is no reason to be inconsistent with read-only properties like date.daysInMonth other than a feeling or preference that some of us have.)
Most helpful comment
I prefer the use of explicit methods. To me, use of fields implies an amount of independence and composibility that does not exist in the case of scaling鈥攅.g., a Temporal.Time instance is an enhanced bag of {hour, minute, second, millisecond, microsecond, nanosecond} (which are exposed accordingly), but that is not true of a Temporal.Absolute instance.