-
Notifications
You must be signed in to change notification settings - Fork 156
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
Direct Time Zone Access: Elm's use case #103
Comments
Wouldn't this time by time introduce
? As time zone data changes frequently. As an example for IANA tz data: 2018e => 2018f |
@ljqx That concern applies to dealing with browser-supplied time zones in general, and is much broader than this issue. (For example, the concern applies equally to I would suggest opening a separate issue to discuss it! |
@rtfeldman Thanks for the pointer; I didn't know about the TimeZone proposal. To be clear, you're interested in Time.Zone and not Time.TimeZone, right? This proposal (and ECMA-402) use the IANA tz strings directly, rather than a wrapper class. I'm wondering, what sort of data do you need in Elm that you can't get by passing the timezone to the right temporal API? |
Correct! |
This is a great question! Let me take a moment to outline why the current Temporal proposal doesn't address Elm's use case. First, the only API in the current Temporal proposal that accesses up-to-date TZDB information is In contrast, Elm's
There are two major problems with this approach. One is an API limitation that does not currently exist, and the other is a show-stopper that prevents First, the API limitation. Problem 1: Listing Time ZonesThe hypothetical approach I mentioned earlier rules out being able to display for the user a dropdown of available time zones to choose from. This use case is currently supported through a third-party Elm package as well as in Moment TZ. Users who need this functionality would have to download a separate bundle which would naturally get out of sync with the time zones known to Temporal. Problem 2: Purity RequirementsThis is the show-stopper that prevents All Elm functions are pure. If I write an Elm program and I pass it the same inputs, it must do the same thing every time I run it. This is a foundational guarantee that the language is built around, and all sorts of things would break if it were violated. By design, the This means if we want to instantiate a However, this means that the "create a toHour : Time.Zone -> Time.Posix -> Int This would not be implementable using the current Temporal proposal. It would have to change to something like: toHour : Time.Zone -> Time.Posix -> Task x Int Since Tasks are asynchronous, this would mean it would no longer be possible to synchronously determine the hour of a timestamp in a given time zone using This would be such an ergonomics catastrophe that I doubt anyone would use it over the status quo (where they have to download time zone bundles separately, even if the browser has all that information already), so it's more likely that what would happen is that Hopefully that clarifies, but happy to elaborate further! |
This helps a lot, thanks!
|
@rtfeldman when you say pure, do you mean pure within the life of the program? Or that forever, the same inputs would have to produce the same outputs, meaning that you need to be able to permanently snapshot timezone data? (In other words, I’d be surprised if time zone data would change during the lifetime of a realm - I’d expect the data to be constant for the life of the realm, in other words. |
I haven't looked into
It's important that if I compile an Elm Having said that, it's totally fine if an Elm program gets back a different
That would be better than not specifying when the updates happen (and I think it's worth including that in the Temporal specification regardless!) but it wouldn't be enough for us to safely use If purity gets broken, even if between runs of the same program, the symptoms are really difficult to track down to the root cause—because it's such a foundational assumption Elm programmers depend on. We made the mistake early on of thinking it would be okay to use JavaScript's built-in Making impure calls to |
Intl.DisplayNames is extremely early. I hope we can make progress on it soon, but there isn't much to read yet. Use cases like this will be very useful in its design!
I still don't quite understand. What do you mean by, "what else is going on in the browser"? Does it need to be stable across a browser version upgrade and restart? If so, it's not clear to me how the browser could even provide tz data without messing with Task, as the browser will sometimes need to update the tz database. Would evancz's time zone proposal meet your requirements of being usable without returning a Task? Date has far more impurities than ZonedInstant, e.g. it updates the local timezone based on where the UA is within the lifetime of a page. |
Sorry for my lack of clarity! I'm trying to choose my words carefully because it's not that the time zone itself needs to be stable across a browser version upgrade and restart (which would defeat the whole point), but rather that compiled Elm functions which don't return It might be helpful to give some context on how Elm tends to interact with JavaScript APIs. In general:
So the fundamental question behind "Can
However, because it takes a
Evan's proposal would do the trick, yeah. The key is that if the browser exposes a function like However, it's not possible to use
That's totally fair! The problem is that for us, it's all or nothing; more impurities are worse, but any at all means we can't use the API to address our use case. 😄 Thanks for your patience on this, by the way! I really appreciate your taking time to understand the situation thoroughly. ❤️ |
Given that time zone data is never constant over time (it changes based on legal decisions, for example), it kind of seems like inherently you’d need it to always be asynchronous in any paradigm/language, with the constraints you’ve outlined. |
I'd say it's inherently effectful for that reason. In Elm, all effects are necessarily handled asynchronously due to purity requirements (so effectful implies asynchronous), but in JS it's possible to run effects synchronously - e.g. |
@rtfeldman ok - so by those definitions and under those constraints, it would seem to me that the only way the language could provide timezone data that would meet your requirements for synchronous usage is if the engine retained all historical and future snapshots of timezone data, and if you were able to determine a fixed point in time with which to apply time zone logic. Am I understanding the situation correctly? |
@ljharb I don't think that is necessary, because it seems like the necessary escape hatch already exists. @rtfeldman is asking for a way to get the data for a time zone (e.g., a characterization of every UTC offset shift) so that the only asynchronous aspect of temporal arithmetic in Elm will be retrieval via |
Ahhh, thank you for clarifying. So the ask is to be able to somehow provide an asynchronously retrieved snapshot of timezone data, rather than a string (that could produce different data over time), to specific date/time operations? |
Precisely! 😃 |
I've already communicated to the champions that I want to be able to pass around a TimeZone object rather than a string (ie, the two would be interchangeable), although I was imagining no such guarantee as above - but I'm not sure it would harm any of my use cases to have it (ie, that timezone data was frozen at construction time of a TimeZone object). |
Nice! Were you thinking that the TimeZone object would hold enough info necessary to do the calculations? |
Not in a user-visible way, of course, but yes - my thinking was that just like the internals see a string, and know how to look up the data - they'd know how to get the data based off of a specific TimeZone object. |
Gotcha! 🤔 Is there a reason the calculation info couldn't be exposed in a user-visible way? |
No idea, but I'd assume that exposing that data directly would be a much larger API for browsers to ship and adhere to, which might preclude some optimizations and make it difficult to get consensus. |
@rtfeldman Thanks for bearing with me; your explanation in #103 (comment) makes sense about the act of getting the timezone returning a Task. I am wondering, could the core of Elm "cheat" and provide this same getTimeZone interface returning a Task x Time.Zone, but actually have Time.Zone be wrapping a String? This string would then logically own the tz info for that time zone. In the implementation, the data wouldn't be read from the TZ database until constructing a ZonedInstant later, but it's hard for me to see how the result would differ in terms of observability/purity. |
Speaking as someone who had to do timezones in Java in the years that Oracle withdrew from the standard timezone database for hardware security, I can say that the ambiguities present in Javascript's TZ implementation are easily repaired and fundamentally currently insurmountable I'll repeat what I said else-ticket. My opinion is that all we actually need is:
Those five things would allow a user-land implementation to fill any needed gaps at any level of complexity I'm aware of (short of things like (leap seconds and support for historic Russian calendars)[https://www.youtube.com/watch?v=-5wpm-gesOY]) I am enthusiastically in support of adding a handful of methods to repair this |
The W3C TAG expressed strong support for including a low-level API for access to the timezone database in w3ctag/design-reviews#311 . Could we do do this in the TC39 Temporal proposal, alongside the high-level API? |
you're the guy who closed my proposal years ago but now that the right people support it, you want one |
I see multiple people asking for the same thing as a useful signal and data point. We can push back on feature requests to a point, but eventually it's time to reconsider. Thanks for your help in getting to this point. |
tzdb data exposure seems like a fine thing to have, for sure. Adding it to this proposal, feels maybe scope-creepy? I had thought -- I could be wrong, edumacate me if necessary -- the aim of the proposal was to rectify the inadequacies of Now, maybe that's just solvable by doing everything in this proposal, then -- if the existing ideas are firmed up sooner, uplifting just them and letting the tzdb lower-level bits follow when they're ready. I don't know if our processes allow that. I'm not much of a rigid process-adherence fanatic, myself, for any of this -- I just care that stuff gets done. But if we could fork off |
Well, maybe I'm being naive, but I think we could provide the timezone data in a way that fits in well with a high-level API. The current proposal accepts strings as timezone parameters. We can keep doing this, while also making a If we decide we want a One thing that I really don't want to happen is for Temporal to be a JavaScript standard, and underlying timezone database access to be theoretically a web-only feature. That layering feels wrong. |
i also feel tzdb is a hard-to-generalize, client-specific/presentation-logic problem that's perhaps out-of-scope. most business-logic need only utc-value and timezoneOffset to do their calculations/aggregations: {
"utc": "2019-02-08T00:00:00.000Z",
"timezoneOffset": -360
} complicating it with tzdb-lookups at that stage, rather than at the [implementation-specific] input-validation/presentation stage is usually an anti-pattern. |
This is not enough information to account for daylight savings time changes, among other edge cases. There's a reason tzdb stores more information than these two data points! |
Right, I definitely wouldn't want to expose something incorrect like @kaizhu256 is describing. This proposal's schema looks reasonable to me, though we might leave describing the timezones to Intl.DisplayNames rather than this API (since both the abbreviation and long name are locale-specific (yes, there are multiple locales within a timezone)). |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
I do not understand problem 2. Your claim is that the That is true if and only iff the underlying timezone database changes (i.e. a seamless browser/os update while elm is executing). In which case exposing the nderlying timezone database directly would trigger the same problem. If the underlying database changes, then you would have the exact same problem in pure elm. In short, let instant = new Instant(1553262381001000000n);
let zoned = new ZonedInstant(instant, 'America/New_York'); will return the same result every time. Now considering that the value itself is an object, the only way to solve that is to use let map = new WeakMap();
function makeZoned(instant, zone) {
let submap = map.get(instant);
if (!submap) {
submap = new Map();
map.set(instant, submap);
}
let zoned = submap.get(zone);
if (!zoned) {
zoned = new ZonedDateTime(instant, zone);
submap.set(zone, zoned);
}
return zoned;
} Now for any given input you have As for problem 1, a listing of all timezones may well be worth while. I think it's just out of scope for this proposal and easily doable individually now. I am thinking of proposing a direct tzdata API as well. But I'd like to get temporal done first. |
@pipobscure perhaps you missed this comment clarifying the issue? #103 (comment). The way I understand it, the problem (simplified) is: Bad (impure) function:
Good (pure) function:
The problem is that (apparently) there is no current way to get the necessary timezone object, so you are forced to go with scenerio |
Given that a TimeZone object has been added, is this issue possible to close? |
@maggiepint thanks! Closing this. |
@littledan suggested I post about this here!
Elm's core
time
package works with time zones, as does Moment Timezone.In Elm, it's important for us to be able to take a time zone string like
"America/New_York"
—such as one we'd get fromIntl
—and turn it into aTime.Zone
value which holds information about that time zone.Currently the way we do this is the same way Moment Timezone does: there's an Elm package which ships IANA timezone data and provides an API for turning the time zone strings into Elm's
Time.Zone
values.This has a few problems, which this writeup explains in greater detail. (Moment Timezone faces the same issues we do.)
The key for us is being able to expose an Elm function which takes a
String
and returns aTime.Zone
value which contains up-to-date information about that time zone. It would be great if someday we could get that information directly from the browser!The text was updated successfully, but these errors were encountered: