4 ms·
From the article: const now = new Date(); The Temporal equivalent is: const now = Temporal.Now.zonedDateTimeISO(); Dear god, that's so much uglier!
by hungryhobbit 7mo ago
From the article:
const now = new Date();
The Temporal equivalent is:
const now = Temporal.Now.zonedDateTimeISO();
Dear god, that's so much uglier!
I mean, I guess it's two steps forward and one step back ... but couldn't they have come up with something that was just two steps forward, and none back ... instead of making us write this nightmare all over the place?
Why not?
const now = DateTime();
- sourcegrift 7mo agoIf you give me your background I'll explain in longer terms but in short it's about making the intent clear and anyone who understands s modicum of PL theory understands why what's a constant is so and what's a function is so.
- themafia 7mo agoI'm a programmer. I'm a human. Perhaps we should also allow for some "human theory" inside our understanding.
- Bratmon 7mo agoI'm excited for this conversation. If you see someone respond to a developer ergonomics complaint with "If you give me your background I'll explain in longer terms... anyone who understands s modicum of PL theory" you're about to see some legendary bullshit. It's like witnessing a meteor shower!
- evolve2k 7mo agoFirstly, I really want this also and am supportive of an opinionated decision to put something at say Temporal.DateTime() that would be logical for developers to use ‘most of the time’. However my guess is that the spec designers saw this lack of specivity as part of the problem. A key issue of dates and times is that we use them culturally in day to day use in very imprecise ways and much is inferred from the context of use. The concepts of zoned time and “wall clock” time are irreducable and it’s likely much code will be improved by forcing the developer to be explicit with the form of time they want to use and need for their particular use case. I think this is why it’s so explicitly specified right now. But I agree; I’ve often struggled with how verbose js can be. Maybe with time (pun intended), more syntactic sugar and shorter conventions can be added to expand what has been an incredible effort to fix deep rooted issues.
- sheept 7mo agoI think that it's nice it's explicit that the method returns the current instant, rather than some other zero value. There's also other methods that return other types, like const now = Temporal.Now.instant() which isn't as bad. One could argue that the ugliness of the API intentionally reveals the ugliness of datetime. It forces you to really think about what you mean when you want "the current date time," which I think is one of the goals of the API.
- Bratmon 7mo agoWhat would have been wrong with Temporal.now() returning a sensible value?
- ejplatzer 7mo agoWhat counts as a sensible value? The whole point of the library is to be explicitly about what kind of date/time data you're working with, because different kinds of data have to be handled in very different ways.
- Bratmon 7mo agoIf they at least had a Temporal.nowlocal() and a Temporal.nowUTC() that returned a ZonedDateTime set to the local and UTC timezones respectively, that would be 95% of what developers need in practice.
- tmpfile 7mo agoOr const now = new Temporal();
- tshaddox 7mo agoThat’s uglier because, if you were previously doing new Date(), you almost certainly don’t want a zonedDateTime. You almost certainly want an Instant.
- rmunn 7mo agoI'd argue that `new Date()` returning the current time is a design mistake, and it should at least have been something like `DateTime.now()`. (Especially because it's called a date but it actually returns a timestamp: the footgun potential is large). C#'s date API isn't the best design (otherwise [NodaTime](https://www.nodatime.org/ https://www.nodatime.org/) wouldn't have been necessary) but it at least got some things right: you don't get the current time by doing `new DateTime()`, you get it by referencing `DateTime.UtcNow` for UTC (almost always what you want), or `DateTime.Now` for local time (which is sometimes what you want, but you should always stop and think about whether you really want UTC). And even with C#'s date API, I've seen errors. For example, a library that formatted datetime strings by merely writing them out and adding a "Z" to the end, assuming that they would always be receiving UTC datetimes — and elsewhere in the code, someone passing `DateTime.Now` to that library. (I'm guessing the dev who wrote that was in the UK and wrote it during winter time, otherwise he would have noticed that the timestamps were coming out wrong. If he was in the US they'd be 4-7 or 5-8 hours wrong depending on whether DST was in effect. But in the UK during winter, local time equals UTC and you might not notice that mistake). This is another reason why Temporal's API making clear distinctions between the different types, and requiring you to call conversion functions to switch between them, is a good idea. That C# mistake would have been harder (not impossible, people can always misunderstand an API, but harder) if the library had been using Nodatime. And Temporal is based on the same design principles (not identical APIs, just simmilar principles) as Nodatime.
- greatgib 7mo agoI also find it super more complicated and messy than what you can find in another language without proper justification. Like the Temporal.Instant with the only difference that is now but in nanosecond. Would have been better to be Now with a suffix to indicate that it is more precise. Or even better, it is just the function you use or parameter that give the precision. And why Now as the name space? I would expect the opposite, like python, you have something like Temporal.Date, and from there you get a date of now or a specific time, with or without timezone info, ...
- justingrantjg 7mo agoI'm one of the volunteer open-source folks (called "proposal champions" in TC39 parlance) who designed the Temporal API. Sorry for the late reply, as you can imagine it's been a busy week for us. You raise a very important question: why is `Temporal.Now.zonedDateTimeISO()` so verbose? After 10 years of work on Temporal, you can assume that every API design and naming decision has been argued about, often many times. I'll try to summarize the reasoning and history below to explain how we got there. There's really five questions here. There's no perfect order to answer them because the answers overlap somewhat, so you may want to read to the end until disagreeing. :-) I will have to split this response up into two posts because it's long. 1. Why do we need `Temporal.Now.`? Why not just `Temporal.`? The TC39 members working on security required us to have a forward-compatible way to override and/or prevent access to information about the local machine. With the current design, a hosting environment can monkey-patch or remove `Temporal.Now`, and regardless of what Temporal changes in the future that local-machine info will still be blocked or overridden. But if we'd spread methods across each Temporal type (e.g. `Temporal.PlainDate.today()`, `Temporal.Instant.now()`) then a new Temporal type added in the future could allow jailbreaking to get local machine info. This isn't just a security concern. Environments like jest may want to control the local time that tests see. Hosters of JS code like https://convex.dev/ https://convex.dev/ might want to override the local time so that transactions can be re-run deterministically on another node. And so on. 2. Why a `Temporal.*` namespace? Why not just `ZonedDateTime`, `PlainTime`, etc. in the global namespace? If `Date` didn't exist, we'd probably have done exactly this, and argued harder about (1) above, and we maybe could have won that argument! But we were worried about the confusion between `Date` and another type named `PlainDate` (or whatever we could have called the date-only type). By putting all Temporal types in a namespace, it was much harder to be confused. A secondary benefit of a namespace was to expose developers (via autocomplete in editors and browser dev tools) to the full set of types available, so that developers would pick the right type for their use case. But the `Date` conflict was the main reason. We could have made the types TemporalDate, TemporalTime, etc. but that shaves only one character and violates (1) so there was no chance that would move forward. So we went with a namespace. 3. Why is it `Temporal.Now.zonedDateTimeISO()` not `Temporal.now()`? As @rmunn and others discuss below, one of the core tenets of Temporal (following in the footsteps of Java, Noda time, Rust, and many others) was that developers must figure out up-front what kind of date/time data they want, and then pick the appropriate Temporal type for that data. For a canonical example of why this is needed, just think of the thousands (millions?) of times that JS developers or end users have ended up with off-by-one-day errors because `new Date()` reports a different date depending on which time zone you're in, even if all you care about is displaying a date where the time zone is not relevant. It's a reasonable argument that because `Temporal.ZonedDateTime` represents the superset of all Temporal types, it should occupy a privileged position and should be the default Temporal type for something like `Temporal.now()`. Given that I proposed the initial design of the ZonedDateTime type (https://github.com/tc39/proposal-temporal/pull/700 https://github.com/tc39/proposal-temporal/pull/700) I'm understandably sympathetic to that point of view! But there are performance concerns. Accessing the system time zone and calendar not free, nor is the extra 2+ bytes to store them in a `Temporal.ZonedDateTime` implementation compared to a cheaper type like `Temporal.Instant`. This also would have popularized a pattern of calling `Temporal.now().toPlainTime()` which creates two objects vs. just creating the desired type in one call via `Temporal.Now.plainTime()`. (cont'd in next post)