-
Notifications
You must be signed in to change notification settings - Fork 153
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to use Temporal instances as Map keys or Set values? #1840
Comments
Set and Map in JS use object identity - it seems like:
is the problem here? Not all objects are serializable to a "hash". |
I'm no expert here but I would think that Temporal objects will work really well as keys since they're immutable. const myMap = new Map()
const d = Temporal.ZonedDateTime.from({timeZone: "UTC", year: 2021, month: 1, day: 2})
myMap.set(d, 'foo')
myMap.get(d) |
Mutability has no effect on their use as keys; the way they'd be most useful as keys is if two calls to |
It seems like the outcome of this issue should be a cookbook recipe showing what the recommended way to do this would be. (And if it turns out to be incredibly cumbersome, we should take that seriously as ecosystem feedback; this seems like a reasonably common use case.) I agree that calling valueOf indiscriminately on objects is probably not something that InternMap/InternSet can rely on to get a hashable value, so that is probably something that should be brought to that library's attention 😄 |
Hi, that’s me. 👋 What I’m looking for is a generic recommendation on how to use timestamps (referring generically here to Date and Temporal instances… or perhaps just Temporal instants since those do have an obvious primitive representation of epoch nanoseconds) as keys in Maps or values in Sets. I could of course do instanceof checks and only support specific classes, but especially given that Temporal isn’t available natively yet and needs to be polyfilled, that would be rather limiting. I’d love some hints on how best to support this use case universally in D3 and similar libraries that work with temporal data. |
@mbostock as far as I'm aware, there is no generic way to do what you want, and explicitly supporting each thing individually is the only robust approach. |
Hello Temporal proposal authors! I have a question about how to use the Temporal API with Map and Set.
As context, I am the author of D3.js, an open-source library for data visualization. Visualization often involves time-series data, so dates and times are an important part of D3: see e.g. d3-time and d3-time-format. Common tasks with time-series data including grouping and querying data by date, say to join two tables using a date key.
For example, say you have a tabular dataset of customer purchases via a JSON API, something like:
You might convert this into a more convenient JavaScript representation using Date like so:
Now say you want to group purchases by date. Here I’ll use UTC midnight to define the start and end of each day interval. Using d3.group and d3.utcDay, you can say:
Now to get the purchases on January 2, 2021, UTC:
Similarly, using d3.rollup, you can say:
This works because d3.group and d3.rollup use InternMap under the hood, which coerces keys to a primitive value via valueOf. (I could have passed 1609545600000 instead of the Date instance to get above.)
However, Temporal instances eschew valueOf (previously #74 #517 #1462), and hence trying to use a Temporal.Instant as a key in an InternMap (or a value in an InternSet) will throw an error. I could put some special magic in InternMap or InternSet to handle objects whose valueOf methods throw an Error, and, say, fallback to toJSON as the key. Or even special-case Temporal instances (similar to how JavaScript special-cases [[defaultValue]] for Date). But is this what you recommend?
Converting to a primitive value and back again so that dates can be used as keys with Map is somewhat cumbersome. For example, with the current Temporal.Instant, I’d say:
Then to lookup a value, I’d either need to hard-code the string format:
Or use toJSON:
And similarly when iterating over the Map, if I want a nice representation of the key as a Temporal.ZonedDateTime, I’d need to say:
Arguably this is mostly a limitation of the Map and Set collections in JavaScript, which don’t allow keys and values to define equality (or hashCode, as Java does). But it’s still a common use case, so I’d love any perspective you may have on how to do this elegantly with the proposed Temporal API. Thanks for your time!
The text was updated successfully, but these errors were encountered: