JavaScript Temporal is coming
415 comments
·January 30, 2025phiresky
burntsushi
> It clearly takes inspiration from other high-quality time libraries such as chrono in Rust
You might be interested in Jiff (a crate for Rust), which is inspired by Temporal. And here is a comparison I did with other datetime crates (including `chrono`): https://docs.rs/jiff/latest/jiff/_documentation/comparison/i...
I actually don't think Temporal takes a ton of inspiration from the `chrono` crate personally. I think it's definitely more from Joda (as you mentioned) or `java.time` these days, and some of the other Javascript datetime libraries that have cropped up over the years (thinking about date-fns and Moment.js).
michaelcampbell
> Otherwise you'll get a bug twice per year due to DST
Those of us of a certain age learned long ago never to schedule cron (etc.) jobs in a production environment between 01:00 and 03:00 local time.
adriand
A few weeks before the time change that happened last fall, I had to debug an issue in our production environment related to something that got scheduled at, IIRC, 1:30 am "local time" and due to some date-handling code that didn't handle the time shift properly, I was getting "ambiguous time" errors. Anyway, I fixed the issue and in the process became intrigued by the interesting fact that there are certain times each year that happen twice.
A couple of weeks after that, on the night of the time change, I went to a party and afterwards a friend of mine and I went back to my house and started jamming and messing around with synthesizers and so on. As it neared 2:00 am, he told me he'd best be heading home, because it was getting rather late. I told him not to worry and that we were about to travel back in time...which we did. Then we spent another hour hanging out until it was almost 2:00 am again and he left.
I don't ever recall actually witnessing this happening before, in the past, I've always awakened in the morning to find I needed to change the clock on the stove. I really recommend staying up for the time change, because this is a pretty magical time of year. If you don't like the hour you experienced between 1:00 am and 2:00 am, you have just one opportunity per year where guess what — you get a do-over! Or if you really loved it, guess what - you can relive it!
wlesieutre
That won't save you everywhere, Greenland falls back at midnight (12 AM Sunday to 11 PM Saturday) in order to synchronize their DST change with Europe
jlarocco
I wonder if that will that change when America owns Greenland /s
yard2010
A long while ago my friend and I released a Safari extension that shows a few clocks in the timezones that you choose. I can't recall the details, but we had an off by 1 error on a few zones during DST.
I ended up fixing it by hand changing the time, releasing a version every 6 months for years, otherwise we would get mails about it from the few users using it.
I think I could automate this or otherwise solve the issue, but it always felt nice to move the clocks of a few hundred people.
foobarchu
Are your production servers configured in something other than UTC, or is there a factor here I'm missing? I've never really seen a good reason for a live server not to be Z'd out
makeitdouble
This is grand-parent's point IMO: running your cron on UTC is a decision to have it on that specific timezone.
So you're effectively deciding for instance to send your user newsletter at varying hours, sometimes at 1h00, sometimes at 3h00. Or accept that every scheduled event needs to be appropriately timezoned and adjusted as needed if DST change. Or to have your logs timestamp be non obvious when comparing events separated by months, or have to convert all your business timestamps to a different timezone.
Those are all sensitive decisions, and we usually accept the trade-off, but it needs to be an explicit tradeoff.
2muchcoffeeman
You might doing logistics and have to have things kicked off in the local time zone. So UTC might not work if you have Day Light savings.
null
LaGrange
This is true, but there's one fly in the ointment I noticed: a lot of people _hate_ using time zones that refer to a real life location.
They ain't gonna bother finding out whether "Europe/Paris" is like a wide slice of France or just specifically Paris, they don't want to tell you they live in Paris and will get annoyed.
When using things to like, schedule online community events or whatever, this has been a pain. People _want_ to use fixed offset, they are fine with things like "CET/CEST", and _hate_ things like "Europe/yourexactcoordinates."
And before you run into here, _I_ know time zones well enough to be chill - most of them (all?) are actually really large areas. But there's plenty of people who are both privacy-minded and not really interested in researching the differences between a "time" and a "time zone" or whatever because they aren't terminal dorks.
sesm
> chrono in Rust and Joda Time in Java
Those are from different time epochs, by the time Rust 1.0 was released, Java already had this approach implemented in standard library via java.time and didn't need any 3rd party libraries for this.
jillesvangurp
Java.time basically is based on joda time and aside from slightly different package names is largely the same thing. That happened to more parts of the Java API. The concurrent package also started out as a standalone library.
Joda time has inspired spinoffs on lots of platforms. Including js-joda for the javascript ecosystem. I'm not sure how much the new Temporal approach is based on that but it wouldn't surprise me that that was one of the starting points for the new standard.
tomtomtom777
> It even solves the serialization issue of the difference between a "fixed-offset" timestamp (e.g. 2025-01-01T00:00+02:00) and one in a specific timezone (e.g. Europe/Paris).
Could you elaborate on that? What is the issue?
amiga386
+02:00 is not political. It's an offset from UTC and will be the same offset in the past and future.
Europe/Paris is political. It defines that offsets change at certain times of the year, but that could change tomorrow, or the political boundary that the timezone applies to could split such that the person or entity needing a time in their "local" timezone finds another one needs to be picked (see various US states/counties applying/disapplying daylight savings).
It's impossible to be 100% confident what the offset from UTC will be at any time in the future. You also need to be a historian to correctly apply it to times in the past - take https://en.wikipedia.org/wiki/Time_in_the_Republic_of_Irelan... as an example!
tharkun__
Even countries that are on UTC don't save you from this. I had no idea until very recently but there is a time that simply never existed in Iceland!
Wednesday January 2st 1908 00:00 clocks were turned forward 28 minutes to 00:28. So an entire 28 minutes of time never eexisted in Iceland even thought today they are on UTC year round and one might think they are the best and easiest country to handle timezone wise.
phiresky
That but also and for me more importantly it does not tell you how to add time - If you add one month of hours to a date in October, it depends on the timezone whether you will end up one hour of local time earlier or not (due to DST), because then +02:00 might be +01:00
Cthulhu_
I wonder what happens when a timezone ceases to exist, e.g. what if Paris is renamed to New New York after the British take revenge and take over France.
burntsushi
The issue is that if you have a timestamp (e.g., `2025-06-20T17:00:00+02:00`) and a time zone (e.g., `Europe/Paris`) and you go to serialize it, are you explicitly including the time zone in that serialization? And when you deserialize it, are you checking that the offset is still valid for that time zone at that time?
Temporal fixes this by using RFC 9557[1], which includes the time zone in the serialized representation. RFC 9557 is a superset of RFC 3339. So where as previously you might just emit `2025-06-20T17:00:00+02:00`, using RFC 9557, you would emit `2025-06-20T17:00:00+02:00[Europe/Paris]`. For example, using Temporal:
>> instant = Temporal.Instant.from('2025-06-20T17:00:00+02')
>> zdt = instant.toZonedDateTimeISO("Europe/Paris")
>> zdt.toJSON()
"2025-06-20T17:00:00+02:00[Europe/Paris]"
And when you go to deserialize an RFC 9557 timestamp, Temporal will do some validation to help ensure it's still correct. For example, you might serialize a RFC 9557 timestamp that is in the future, but at some later point, that region might abolish DST. At which point, your RFC 9557 timestamp might or might not resolve to the intended time. If it was in DST, Temporal will reject it at parsing time.You can read more about this at https://tc39.es/proposal-temporal/docs/zoneddatetime.html and search for "conflict". There's an example about Brazil abolishing DST in 2019 that should lay it out for you.
Separately from even this, there are other concerns. If you forget to include the time zone in your serialization and then just deserialize it as a simple timestamp, then it makes it very easy for arithmetic on that value to be wrong because it won't be DST safe (unless you're careful to reconstitute its time zone somehow). With Temporal and RFC 9557, all of that is handled for you automatically.
vlovich123
I get that it’s more correct, but it assumes that Europe/Paris is a constant representation of how to apply the timezone-specific stuff but that’s incorrect. For example, ‘2025-06-20T17:00:00+02[Europe/Dublin]’ is a very different time if it’s created today vs if it were created in 1760 [1]. That’s a very extreme example, but timezone rules change and dates created from before the change was announced would be interpreted differently from ones created after they were announced. It’s interesting to me the standard doesn’t embed the creation time of the timestamp in UTC as well.
https://en.wikipedia.org/wiki/Time_in_the_Republic_of_Irelan...
MobiusHorizons
Places like Europe/Paris or America/Los Angeles can participate in daylight savings, and if they do, they may have different schedules, and those schedules may change at different points in history due to the passing of laws. Europe and the us already have a different schedule for daylight savings, and the whole west coast is trying to opt into permanent daylight savings for the last several years. But that would require an act of congress.
Programmatically it mostly means you have to ship metadata about how the offsets change over time, which needs to be updated periodically. Browsers already ship that metadata, so it is really nice to finally have a way to access it from JavaScript without shipping the extra few tens of kilobytes.
SonOfLilit
Europe/Paris might change between now and the referenced time.
Piskvorrr
In other words, 2025-01-01T00:00+02:00 was NOT Europe/Paris (as it was CET at that time, GMT+1), 2024-08-01T00:00+02:00 could have been Europe/Paris (CEST, GMT+2), 2030-08-01T00:00+02:00 may be Europe/Paris (CEST, GMT+2), or perhaps not (CET, GMT+1). Or it may be a completely different TZ that incidentally shares the same offset at that time.
stewx
One represents a time in a specific place, and one represents merely a shift from UTC. A specific time zone can have different offsets depending on the time of year, for example with Daylight Savings Time.
jillesvangurp
Sounds great. I've been working with kotlinx-date time for a few projects on both the JVM and in browsers using kotlin-js. Because this is a multiplaform library that needs to work on multiple platforms it sort of is stuck with the lowest common denominator; which on kotlin-js was the old Date API.
The way this kotlin library works is that it implements a modern API that uses the underlying platform rather than re-implementing a bunch of things. This is mostly not a bad decision but it does have its limitations. One of the limitations is that not all platforms exposes a sane way to e.g. resolve timezones by their name and localize times while taking into account e.g. day light saving. Fixing that basically requires dealing with the time zone database and not all platforms expose that.
I ran into this recently. I managed to work around it as this is something you can dig out of existing browser APIs but it was annoying having to deal with that. Unfortunately there are probably a few more obstacles on other Kotlin platforms.
klysm
I’m also using it in production and it’s so much better than any of the existing alternatives
DanielHB
> time _is_ complex
If only humans could read int64 epoch values
AndrewStephens
And lived on a flat planet.
moi2388
That’s not a valid argument. There is no reason why people in Japan couldn’t start their workday at 03:00, or people in France at 22:00
nekevss
if only it was as simply a reading int64 epoch values :')
lttlrck
Just add "What Three Words" for time.
WorldMaker
"Eastern Daylight Time"
"America/Michigan/Detroit"
We built that already. We call it time zones.
pavon
And time since epoch was defined sanely.
qwertox
Man, that took some time to find in the docs:
Temporal.ZonedDateTime.prototype.withTimeZone() [0], which allows to convert from one timezone to another
const meetingTime = Temporal.ZonedDateTime.from(
"2021-08-01T12:00[America/New_York]",
);
const meetingTimeInParis = meetingTime.withTimeZone("Europe/Paris");
console.log(meetingTimeInParis.toString()); // 2021-08-01T18:00:00+02:00[Europe/Paris]
To me, timezone translations as well as durations are such an essential thing which libraries must handle, and it's nice to see that Temporal handles both. But it looks like Temporal.Duration doesn't offer a custom `format` function, for example `duration.format('H\hmm\m')` or something like that to format a duration into 1h03m.[0] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
desmondwillow
The DurationFormatter proposal allows you control over which units you want formatted and at what brevity: eg. 1 yr, 3 hours, and 3m. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
I partially implemented it in the icu4x library.
nekevss
Agreed this sounds like they are looking for Intl.DurationFormatter.
Temporal.Duration.prototype.toLocaleString will end up using Intl.DurationFormatter though, so that will ultimately be what he wants (probably going to depend on that ICU4X implementation being complete though).
styfle
DurationFormat looks cool but it didn’t behave as I expected.
https://github.com/tc39/proposal-intl-duration-format/issues...
burntsushi
As the comment mentions there, the idea is that you can do those sorts of transformations on the duration and then emit them:
>> d = Temporal.Duration.from({milliseconds: 60000})
>> d.seconds
0
>> d.milliseconds
60000
>> d = d.round({largestUnit: 'second'})
>> d.seconds
60
>> d.milliseconds
0
nobleach
There are quite a few things marinating in the TC39 pot right now. This is one that I wish would ship sooner, rather than later. I do recognize that it takes dev effort (on the part of v8, JSC, and SpiderMonkey engineers) to get the major browsers to support any of these new features. So I truly appreciate all that folks are doing to move the ball forward. The impatient person in me is cheering, "now get Records and Tuples going too! You can skip that silly Pipe-syntax war if you want!"
rimunroe
Records and tuples are unlikely to ever ship, or at least are extremely unlikely to ship with the semantics around equality people want. My understanding is that browser vendors already have pretty strong opposition to introducing new primitives at this point. Reading this thread[1] will give some explanation as to the hiccups with how equality would behave. It sucks, because while I wouldn't have expected BigInt to have gotten much adoption in the first place, I constantly run into cases where I'd want collections with structural equality.
Additionally, my understanding is that the opposition to adding new primitives also affects pattern matching, though I'm not sure why. I'm much less up to date on that proposal.
[1] https://github.com/tc39/proposal-record-tuple/issues/387
pspeter3
That's a bummer. I wish there was a way to use non primitive objects in Maps & Sets more effectively then. Perhaps a well known Symbol for hashCode or something.
theplatman
BigInt shipped because financial organizations needed it for certain applications.
rimunroe
I know why people needed it. It’s obviously useful. However, it’s still a relatively niche use case and rarely encounter people using it, especially compared to how many people I encounter asking about dealing with compound keys in maps or how to deeply compare two static blobs of JSON-style data. I understand why the implementers felt burned by its lack of adoption given its burden of implementation, but I’m also a bit surprised they expected more use.
int_19h
To be honest, this reads kind of insane, and reminds me of how wasm was at least partially designed around V8 idiosyncrasies and limitations.
rimunroe
> To be honest, this reads kind of insane
Could you clarify which part you’re referring to? I’m disappointed at them feeling trepidation after BigInt, but the thread I linked (and some other discussions I’ve seen) make me understand why they’d choose to focus effort elsewhere.
It would be a monumental change and it’s not entirely clear how much of the community outside the React and similar ecosystems would adopt it. It might have significant performance issues for the desired use cases and choices about value semantics would affect usability.
inbx0
It's great that Temporal is coming, and I'm sure there are bunch of other nice things coming up too, but unfortunately I don't share your optimism with the specific proposals that you mention (even though those would be very nice).
Pipelines, pattern matching and records+tuples have all been in the works for 4+ years, and are all still in stages 1-2. I don't think any of them has seen any significant progress in the past year, except maybe pattern matching. According to an issue in the records and tuples repo, there's been pushback on the value semantics of it (i.e. whether === can be made to work). Dropping value semantics would significantly reduce the whole proposal's usefulness.
I think all of them are at least a year or two away from reaching stage 3, if they ever do. But hey at least we now have array grouping functions.
null
dkdbejwi383
The one I want is pattern matching (https://tc39.es/proposal-pattern-matching/), which is still at stage 1 so many years away, sadly.
halfmatthalfcat
Pattern matching (and expression based assignment, of which idk if there’s a proposal for or not) are two things that would really drive a ton of value.
CharlieDigital
It's going to end up looking a lot like C# [0][1]; these two/three (JS/TS, C#) languages have been converging for a while now. Now just waiting for C# to get official first party discriminated unions!
[0] https://learn.microsoft.com/en-us/dotnet/csharp/language-ref...
[1] https://timdeschryver.dev/blog/pattern-matching-examples-in-...
recursive
Assignment is already an expression, no?
console.log(x = "hello");
hajile
I also REALLY want records and tuples.
DanielHB
Unfortunately that proposal seems to be kinda dead.
React is a fundamentally flawed framework because of the lack of this feature. It inverts the responsibility of any non-primitive prop by putting the burden on the parent element instead of the child to decide when to rerender things. So elements are no longer self-contained if they receive any non-primitive values (besides react elements).
The React compiler auto-memoization that facebook is pushing also addresses this issue through build-time magic. I not fond of this approach.
noduerme
Records.. Wasn't Dictionary an ECMA5 proposal or was that just a novel touch in AS3?
[edit: For those who don't know, Dictionary was a type in AS3 that let you use any object reference or string or number as a unique key, with any type of value attached. Garbage collection worked around this so it wasn't a weak reference as long as the dictionary object itself was alive. Think of a Javascript Set except with strongly typed keys of any kind you specified. Errors thrown at compile time. God..I miss that language.]
jitl
We’ve had Map with those semantics since 2014, came out in Chrome a few months before Set.
Record/Tuple objects are immutable primitives with structural equality, not object reference equality. So little relation to AS3 Dictionary/ES6 Map, besides being possible keys for Map/Set.
klabb3
> Record/Tuple objects are immutable primitives with structural equality
TIL and also god that would be amazing, almost to the point of making JS/TS actually nice if done right (what’s next, pattern matching?). The number one footgun in JS imo is the combination of mutability and reference copying. Immutable or at least easy-to-copy plain old data is fantastic when it is well supported in the language.
z3t4
It's not just the major browser makers. I was working on a JavaScript inference engine around when ES6 started to roll out, I had decent ES5 support but when all the syntatic updates came I had to give up. They basically killed the JavaScript ecosystem with all the updates. We only have complile to JS languages now. Those that still writes in vanilla JS are like those who still build apps in assembly langauge.
fiala__
> We only have complile to JS languages now. Those that still writes in vanilla JS are like those who still build apps in assembly langauge.
I strongly disagree, it's never been easier and more pleasant to write modern JS without transpilers. I've only rarely had to reach for a framework or transpiler in the last few years.
andrewmcwatters
Come now, this is silly. There are plenty of us that are explicitly avoiding build phases because, for us, what needs to be built adds very little benefit.
Working with assembly is comparatively expert work that few professionals are good at. JavaScript can be written by kids.
stevage
The main reason people don't write much vanilla JS is because they're writing TypeScript instead.
bolognafairy
> Those that still writes in vanilla JS are like those who still build apps in assembly langauge.
…Huh? Are you referring to transpilation?
k__
I had the impression the implementation happens first, then the ratification later when things worked out well.
culi
Even when it does ship it'll probably be another year before enough browsers have updated to safely use it in production. So you'll need a polyfill. Which you can start using today anyways!
agos
are there polyfills for those proposals?
null
ggregoire
Anyone knows how the data about each timezone stays updated within Temporal? Does the TC39 update the data somewhere, then each browser copies that data internally and releases a new version of the browser? If a user visits my website and this user has not updated their browser with the new data, will they see incorrect hours?
For example Mexico removed DST in 2022 [1]. When using third party libraries like pytz or moment-timezone, you just update the library on your side with the updated data for Mexico. Or bump the language if it's handled in the standard library. What about Temporal and my visitors' browser?
haburka
Reading the proposal page “ Time Zones and Resolving Ambiguity”[1], it only mentions that it uses the IANA time zone database[2] not when it updates it. However I imagine the users computer has access to this database as well and probably handles it being updated. I’m not sure about this. It’s also entirely possible for the browser to download this database and maintain it too, separately from updates. I’m sure it depends on the implementation.
thayne
Yes, the user's operating system probably already has an IANA database somewhere, or the browser could bundle its own IANA database.
And the browser probably already has some way to access that database anyway.
infogulch
Since it's built into the browser it's probably updated when the browser is updated. Browser vendors did a lot of work to update quickly, browsers are probably the most up-to-date software on your average person's computer.
baq
Please don't forget about us node users (and deno and bun I guess, too).
infogulch
If you're running years old js runtimes in a bigcorp that doesn't feel like updating for the next decade, I'll pray for you. (Because there's nothing else to do.)
rough-sea
deno added this about a year ago https://docs.deno.com/api/web/~/Temporal https://deno.com/blog/v1.40#temporal-api
sureIy
Browsers already have to stay up to date with locales due to the Intl helpers so researching that would likely lead to the same answer.
burntsushi
On Unix systems (including Linux distros, macOS and Android), there is a system copy of the IANA Time Zone Database. I actually don't know if browsers use that or if they ship their own copy. But Temporal definitely uses the IANA tzdb.
> If a user visits my website and this user has not updated their browser with the new data, will they see incorrect hours?
Yeah I think this is generally correct. But I don't think that's a departure from current norms? I think this is also just true in general. If the user doesn't update to their system to account for new time zone transition rules then that's just kinda how the cookie crumbles.
The alternative is that every application ships their own tzdb. And to be clear, some do that and sometimes it is warranted. But in general this would be wasteful and likely lead overall to inconsistency between applications and likely a slower cadence of updates. (Because now every application has to be updated and shipped out again.)
WorldMaker
Windows has its own complex in different ways system-wide Time Zone Database, but these days also has a full IANA Time Zone Database compatibility layer.
nekevss
It's going to depend on the implementation and the system. The implementation will probably end up needing to define a time zone provider, which will ultimately be provided by host/system hooks provided to Temporal from the engine implementation.
TheAceOfHearts
They should add an event to detect when someone changes timezones. That could be another entry in the "falsehoods that programmers believe about time": programmers believe that your timezone is fixed during usage. But in reality there are millions of people moving between timezones every day.
small_scombrus
> They should add an event to detect when someone changes timezones.
That sounds like it would be used as yet another data point with which to fingerprint and locate people ._.
TheAceOfHearts
I don't believe adding this event would represent a new data point for fingerprinting because it's already possible to detect timezone changes by polling `Intl.DateTimeFormat().resolvedOptions().timeZone` and `new Date().getTimezoneOffset()`.
lblume
Where would you expect this event to be used? I don't think most web applications somewhat dependent on time should directly have to listen and respond to these events for the amount of people affected by it just doesn't justify the extra effort, I would assume. Libraries could benefit, of course.
scarface_74
First JavaScript is unfortunately not just for web apps. It’s also for desktop apps.
Say my normal work day is from 8-5 and I work in the Eastern time zone. I set my Slack DND to outside those hours.
I hop on a plane and go somewhere on the west coast. The perfect case, Slack would notify me of the change and let me decide whether I wanted to adjust the DND to local time or keep it.
There are two possible scenarios for me. I could have flown to Seattle for a business meeting and I want to change my DND to local time to be in sync with the rest of the team onsite.
The other scenario is that I’m flying to Los Angeles to hang out. But I’m working during the day and I still need to work east code time.
chippiewill
You couldn't just rely on a timezone change event for that though. You'd need to track it at the application level because it might not be open when the timezone changes.
null
klabb3
> First JavaScript is unfortunately not just for web apps. It’s also for desktop apps.
A bit of a tangent but I’d say server is bigger than desktop. Like it or not JS (or TS) is the only cross platform development language that’s feasible today if you want to use a single language stack. As much as I despise the JS ecosystem practices and haphazard tooling there is no point trying to put the genie back in the bottle.
TheAceOfHearts
To my understanding, it shouldn't require that much effort since browsers should already be keeping track of timezone changes, see Chromium's time_zone_monitor [0]. Browsers could emit a "timezonechange" event on the window.
A quick search of gecko-dev shows entries for both WM_TIMECHANGE and NSSystemTimeZoneDidChangeNotification, although they haven't separated it into its own service. I imagine they also track timezone changes for other platforms.
[0] https://source.chromium.org/chromium/chromium/src/+/main:ser...
noduerme
The client's timezone should only matter to the client. There's no condition where their clock matters except to translate a timestamp into their local time (for their convenience). Who cares if they change time zones?
ninkendo
So that you can update the UI to show the new time zone? Or change the time format to indicate that it’s no longer in the same time zone as the user is in? That’s just off the top of my head, I’m sure there’s more.
fkyoureadthedoc
I agree that it would be a nice feature, but I'd really have to be scraping the bottom of the feature barrel before I got to this. Unless my product heavily featured scheduling, or was a clock.
BoppreH
Sending emails at specific user times, billing (be careful with this one!), scheduling events in the future, reporting it to other users (Microsoft Teams' "it's 20:39 in this user's Timezone").
crowcroft
Since this requires state to track should be up to the developer to define how they want to track and respond to changes in timezone? I'm not sure I would want Temporal to have an opinion on how to handle that?
TheAceOfHearts
I would expect a timezonechange event to get emitted on the window and that the developer would be responsible for handling it accordingly. This wouldn't require any changes to Temporal.
crowcroft
Right, like the browser/app environment would be responsible for it, and then devs can hook into that if they want to handle it or not?
nejsjsjsbsb
If you are on a plane or ISS you could even be timezoneless.
jofzar
Iss uses Coordinated Universal Time which is just GMT.
esafak
Wouldn't you be in the time zone you are traveling over, the same as with other modes of transportation?
nejsjsjsbsb
You might but that isn't useful. Basically a web app will show you a time affected by your tailwind and weird geopolitics. (The weird politics are not so bad if you stay in the same time zone just changes 2 times a year)
aetherspawn
Suggestion, design your app to not be time zone dependant if at all possible.
For example, store dates in UTC and render instantaneously in current time zone.
wim
That only works for past events, not future ones. Converting to UTC is lossy so rendering timestamps correctly in the future becomes problematic with DST/TZ rule changes.
sureIy
> Converting to UTC is lossy
How so? UTC is a constant point in time. The difficulty lies in representing the value correctly, but the point in time is unchanged.
Unlike what sibling comment mentioned, if an appointment is scheduled at 1739287704987, the value will be the same regardless of where and when it's accessed from.
lxgr
Really depends on what you want to do. If it's something like "set the date at which new system behavior x becomes effective", UTC is perfectly fine; for scheduling a meeting, not so much.
mschuster91
> and render instantaneously in current time zone
And for that you need to have a timezone-change event, if you don't want to poll the current system timezone.
iforgot22
For timestamps, which are considered fixed points in time, yeah. Dates and times are different. If you block off 12-1pm for lunch in your calendar every day, the actual timestamp of that event might change if you fly elsewhere and set it to use the local timezone automatically. Same with holidays and birthdays.
Cthulhu_
How would the runtime know that though? If you're in a plane with no internet, or if you're privacy conscious and you have location services turned off, there's no way for the JS engine to know you're in a different timezone.
I mean your argument has some merit but I'd argue that "you get the new timezone if you create a new date after your system updates its local timezone" is good enough.
Furthermore, most applications will just use UTC; local timezone is more used to adjust the displayed time, and even then it's opt in (e.g. someone reading a log will want server time or UTC, someone using a calendar will want to see their local time OR the time at the location of an event, etc).
TheAceOfHearts
The operating system is responsible for tracking timezone changes. If you turn off automatic timezone switching or you're in an airplane without internet then the timezone change just won't be detected, which is perfectly fine. That isn't an argument against supporting a timezonechange event.
Every major operating system has had a way to keep track of timezone changes going back over 25 years. This was during the era where most people were on desktops, but now most people are on mobile devices so it's more relevant than ever. Chromium already has a time_zone_monitor service in place, which I linked in a different reply.
Currently, if you want to detect that the timezone has changed you have to poll `Intl.DateTimeFormat().resolvedOptions().timeZone` and `new Date().getTimezoneOffset()`. An event would just let you get notified without requiring polling.
Updating the displayed time on the client is precisely one of the reasons that this feature can be desirable.
lxgr
> someone reading a log will want server time or UTC
I personally prefer local times when reading logs, but I'll absolutely take UTC over a wrong local time.
agos
a timezone change event might be a nice idea, but there's no reason it should be inside Temporal
OptionOfT
Very sad that .Now is not a function call. It shouldn't be a property.
Evaluating .Now multiple times in a loop will yield different values, which is unexpected.
C# did the same and it shouldn't have been:
https://ericlippert.com/2014/05/19/when-should-i-write-a-pro...
yuchi
I think you got it wrong. Now is a namespace for functions that retrieve the actual values, such as Now.instant()
nikeee
I really like the temporal proposal, except for one thing: they rely on reference equality in comparisons. On other words:
Temporal.Instant.from('2020-01-01') != Temporal.Instant.from('2020-01-01')
This isnt inherently bad, but it effectively removes the ability to use these objects as Map keys or collecting them in a Set. I know why that decision was made, I'm just sad that this wont be possible. Maybe there will be some version that relies on records and tuples, if these ever make it.brundolf
Is there any non-primitive JS type that has non-referential equality for ==?
tubthumper8
Yeah, that's one of the core problems, there's no overloading of equals in JS and no other cases of objects using non-reference equality. Adding that in itself would be a big deal (ex. see the Records and Tuples proposal which has been going on for years and may never complete)
8n4vidtmkvmk
There's exactly one IIRC. document.all
syncsynchalt
It looks like `.epochMilliseconds` should work as a Map/Set key/member in some situations, though you'll need to preserve the instant in the value in the Map case if you want to preserve the zonedata / do further operations on the Instant.
For the Set case you could use a Map{v.epochMilliseconds:v} and preserve the Instant.
Not great, but I think we all blame JS for this rather than Temporal. This could be made to work by the runtime but then polyfills would fail.
nikeee
Passing Dates to a React component caused re-rendering issues in some of my applications due to Date being an object.
I had to resort to numbers (Unix time) to not have to add memoization everywhere. Seems like this will continue with Temporal. Or React-Compiler will solve this.
zeroimpl
Even if that worked, using these in a map/set would be a lot like using floating point numbers in a map/set - which is generally a bad idea.
ivanjermakov
Because it is impossible in JS? Except some crazy hacks, similar to how Java's constant string pool works, where every used object is a reference to a value in a pool of all objects.
nikeee
There is the record and tuple proposal. If we'd have methods on records (currently not part of the spec) this would be trivial.
jdkoeck
I wouldn’t call this a particularly crazy hack, it’s also called string interning and I reckon that’s what every language runtime does when strings are immutable (which includes javascript runtimes, also this isn’t required by the language specification).
sureIy
Why not just use 'String()' or '2020-01-01'?
justingrantjg
Temporal includes `equals` methods on every type. String comparison sometimes works, but there are enough cases where it doesn't (especially when comparing strings that refer to the same data but were generated by different libraries so formatting is different for things like trailing zeroes of decimals, time zone aliases, etc.) that it's usually best to use a library function for comparison instead of just using string comparison.
8n4vidtmkvmk
Comparison functions are unlikely to work across libraries too?
mstade
Providing comparison functions that work with existing APIs is solid design, should be required reading for any new types added really. Kudos to the designers!
const durations = [
Temporal.Duration.from({ hours: 1 }),
Temporal.Duration.from({ hours: 2 }),
Temporal.Duration.from({ hours: 1, minutes: 30 }),
Temporal.Duration.from({ hours: 1, minutes: 45 }),
];
durations.sort(Temporal.Duration.compare);
console.log(durations.map((d) => d.toString()));
// [ 'PT1H', 'PT1H30M', 'PT1H45M', 'PT2H' ]
juancroldan
I get that the naming Temporal is used for avoiding conflicts with typical time objects like Moment, Datetime, etc. But isn't it a terrible name? At first glance I thought it was some kind of garbage collection control
Thorrez
temporal
> 1. of or relating to time as opposed to eternity
> 2. of or relating to grammatical tense or a distinction of time
> 3. of or relating to time as distinguished from space
https://www.merriam-webster.com/dictionary/temporal
Sounds like a good name to me.
WorldMaker
There are only 2 hard problems in software engineering: naming things, cache invalidation, and off by one errors.
shawabawa3
I thought it was Temporal the workflow engine in the browser
russellbeattie
We're definitely bike-shedding a decision that has already been made, but I agree that it's a horrible name.
First, "Temporal" is an adjective, not a noun. It might be related to time, but it doesn't make intuitive sense.
But more importantly, choosing an odd name because it has a lower probability of conflicting with old code will just make the language increasingly obscure over time.
When they added Promise and Generator, there were plenty of libraries that used those object names. It didn't matter, because unlike reserved keywords, you can override built-in Objects.
In my opinion the standards committee needs to have backbone and do the right thing for the long-term health of the language and use "Time".
But again, I'm sure this argument has come and gone and the decision has been made and agreed upon by all the browser makers and JS engine implementations.
8n4vidtmkvmk
I don't think you create Temporals though. It's essentially a namespace for things like Instant, so it need not be a noun.
Time has the opposite problem. I expect it to be a class, not a namespace. Time.Time creates more confusion, not less.
agos
Boolean is also a built in named after an adjective, and we deal with it just fine :)
Temporal is not "odd", it's just a bit less common in english that many people are used to
imdsm
I also think it's a terrible name. I'd even take DateV2 over this. I get they need backwards compatibility but Temporal sounds terrible. DateTime isn't by standard part of JS so why not use that? Until then const DateTime = Temporal
reddalo
I agree, the naming is unfortunate. DateTime would have been way better.
cosiiine
There's even the concept of "Temporal Dead Zone" in Javascript already which describes the period of time where variables aren't accessible.
LordDragonfang
While I love that javascript has been taking features from popular libraries (read: jquery) and integrating them into vanilla, I do despair a little that every time it does so with a much more verbose and annoying invocation.
dang
Related. Others?
JavaScript Temporal Is Coming - https://news.ycombinator.com/item?id=42809834 - Jan 2025 (18 comments)
Mozilla: Temporal (Limited Availability) - https://news.ycombinator.com/item?id=42776548 - Jan 2025 (1 comment)
Is It Time for the JavaScript Temporal API? - https://news.ycombinator.com/item?id=29712118 - Dec 2021 (100 comments)
Temporal: Getting started with JavaScript's new date time API - https://news.ycombinator.com/item?id=27661667 - June 2021 (194 comments)
JavaScript Temporal - https://news.ycombinator.com/item?id=27395236 - June 2021 (1 comment)
JavaScript Proposal Temporal for Dates is now stage 3 - https://news.ycombinator.com/item?id=26432346 - March 2021 (1 comment)
Uninen
I appreciate how truly awesome the Web APIs are nowadays but I still feel sad that the first submission for this was almost 4 years ago in March 2021.
Talk about slow turning ships!
andyjohnson0
From TFA:
> When JavaScript was created in 1995, the Date object was copied from Java's early, flawed java.util.Date implementation. Java replaced this implementation in 1997, but JavaScript is stuck with the same API for almost 30 years, despite known problems.
I'm not a JavaScript or web developer, and I was surprised by the above. Can anyone comment on why the language was stuck with an inadequate api for so long? What are the forces at work here?
DanielHB
Well browser standards were pretty much gimped by microsoft during the IE5/IE6 era, so from 1998 until around 2010 there was no progress on standards and Microsoft was actively trying to prevent web applications from becoming a thing in order to not damage Windows market share.
From 2010 until about 2020 I would say the standard committee took hold and they have been quite busy with other things. Since JS is a language defined by committee it can take quite some time for people to agree on APIs which is a subjective topic. The last thing the standards body want is to introduce an API and then deprecate it in favor of another API slightly later.
WorldMaker
> during the IE5/IE6 era
During that era was a peak of browser innovation. IE5 and IE6 contributed a lot of things to web standards. They contributed a bunch of things that web standards eventually rejected too, but that was the risk of innovation at the time.
It was the period between IE6's last feature update and IE7's first release where Microsoft declared the browser wars "finished" and disbanded the IE team entirely that was the Darkest Age. So about 2001-2006 were the darkest few years.
It certainly had repercussions until around 2010, but the worst "sabotages" were done and gone by then. "Legacy" problems.
phire
I would say the darkest era was after IE7 was released: 2006-2010.
You could see all the new features, you could use them, you could design your site around them. But so many people refused to upgrade, so as a web developer you were forced to do stupid things to make IE6 work.
And it's not like IE7 was that much better. You needed to put effort into making that work too. At least Chrome and Firefox would usually both do the same thing.
harrall
Microsoft was MASSIVELY trying to make web applications a thing. They introduced HTML Applications[1] in 1999 (e.g. Electron). In 2001, they added the JavaScript features that let us have Gmail and Google Maps (XMLHttpRequest). They let you rebuild your Windows desktop or any folder as a HTML in Windows 2000/ME. They created a ton of APIs from web components[2] to CSS effects[3] in 1998.
However, when Netscape died, Microsoft did a 180 and went from the leader in promoting the web to the absolute worst obstruction. It seemed like they completely de-funded their IE development team.
[1] https://en.wikipedia.org/wiki/HTML_Application
[2] https://en.wikipedia.org/wiki/HTML_Components
[3] https://learn.microsoft.com/en-us/previous-versions/ms530752... (previously was just filter:)
boplicity
> Microsoft was actively trying to prevent web applications from becoming a thing in order to not damage Windows market share.
Boy, it's a different company doing this now, but this is definitely still something that is happening, especially in mobile.
DanielHB
Not to the same level as back then, the closest thing would be Apple refusing to implement good PWA integration and Web Push Notifications (forcing people to use Apple Push Notifications which only works in Safari). PWAs are still (mostly) supported in Safari, they just don't integrate at the OS level in iOS.
Apple is still actively developing Safari and JSC and implementing standards, Microsoft basically COMPLETELY FROZE browser improvements for 10+ years. Worse even, they pushed proprietary Microsoft-only solutions to try to lock-in people.
eviks
Is Java not designed by committee?
Secretmapper
Javascript, for the longest time, was a _slow_ moving target - web browsers themselves had cross browser issues where API X might work on browser A but not on browser B.
There were so many bigger issues like that I think that made this not a high priority in the grand scheme of things.
I think a good example of this is jQuery - while jQuery is a good tool, a huge part of its usage was the quirks between browsers. Selectors and the class of problems jQuery solved had more immediate impact to web applications, so fixing and taking from it became a more immediate concern.
JS API -> moment/date-fn/luxon -> Temporal has the same kind of trajectory. Not that those libraries will now be immediately 'bad' mind you - just that the base API is more sane.
phire
And for the longest time, nobody even considered javascript to be a serious tool; It was rare for anyone to write more than a hundred lines of javascript.
I remember when google introduced gmail in 2004. Suddenly google had done full single-page application in javascript, proving that not only was it possible, but that the resulting user-experience was awesome.
At the time, there were no javascript frameworks. Jquery (if you can even call it a framework) wasn't created until 2006. I don't think there were even helper libraries.
I mostly remember javascript from dynamicdrive.com, where you would go to find quick snippets of "Dynamic HTML" to copy/paste into your html. Sometimes there were useful things like roll-over menus, but I remember many of them being silly toys, like sparkles that would follow your mouse around the screen, or snow which would slowly cover the page.
agos
excellent point. it took 6 years (!) for Backbone.js, arguably the first Javascript framework, to come out... and the same year AngularJS.
mrkeen
> Java replaced this implementation in 1997
If that date's correct, they replaced it with another flawed implementation. The 'good' one came much later: https://jcp.org/en/jsr/detail?id=310
> What are the forces at work here?
I feel like I'm always simultaneously engaged in about 5 HN threads at a time, advocating for some combination of immutability, type-safety, and/or no-nulls. It's basically all I do.
By and large, people simply aren't into it. "Because the world is shared and mutable" is a pretty common rebuttal:
4 hours ago: https://news.ycombinator.com/item?id=42876487
2 days ago: https://news.ycombinator.com/item?id=42850569
papercrane
1997 would be JDK 1.1, which introduced the java.util.Calendar/GregorianCalendar classes. The Calendar API was an improvement in some use cases over Date, but it's biggest flaw was mutability. The current API is based on JodaTime and is very similar to Temporal.
agos
and yet on threads about Elixir there seems a lot of people who care – rightly so, immutability it's great and Elixir makes the best out of it. Don't give up the good fight!
mrbluecoat
I've been a JavaScript developer since the nineties and I too have been puzzled about this very thing. Everyone has known Date has been broken for a very long time and a plethora of pollyfills and datetime libraries have sprung up to band-aid the situation but nothing ever got close to being resolved as major ECMAscript versions were released over the years. I guess if it takes 270 pages for MDN to explain it, it's a rocket science problem that's well over my head.
baq
First rule of being a platform: Do Not Break Existing Code.
spiffyk
Well, Java did not break existing code, they added the new code alongside the old one. Just like JavaScript seems to be doing years later.
Cthulhu_
That's fair, but they didn't need to - just make a new Date library and deprecate the old one.
stevoski
Going back even further in time, Java.util.Date was was heavily inspired by a C library.
That’s the origin of getMonth() in Java (and therefore in JS) returning a value from 0-11 and not 1-12 as many coders initially expect.
What was the origin for this peculiarity in C? That I don’t know, but I’m curious to find out if anyone knows.
andyjohnson0
C uses zero-based array indexing. A C array variable is a pointer to its first element, and an element index is just an offset from that. Element 0 is at start + 0, element 1 is at start + (1 * element size) etc.
Which why the fields of the 'tm' structure [1] (used to represent dates and times) are zero based§. Makes it easy to index into eg an array of day names using tm_wday. I guess at one time Java.util.Date was a leaky abstraction layer on-top of such an api.
§ Except for the tm_mday element, which curiously is 1-based. I've always assumed that this is because it is unlikely to be used as an array index. A long time ago I'm ashamed to admit that I used tm_mday == 0 as a quick check for an invalid tm value.
wanderingstan
Just spitballing, but in C it was always the convention to use zero-based indexing. Probably because you were often adding these indexes to pointers (literal memory addresses) to index into an array, so you needed a zero to index into the first slot of the array.
8n4vidtmkvmk
What I don't get is why the day of the month doesn't also start at 0?
ARandumGuy
My work does a lot of stuff with time and scheduling, and let me tell you having timezone-unaware date/time objects distinct from specific points in time will be so damn useful. The old Date class made it really easy to accidentally screw that up. Third party libraries help, but something as important and fundamental as time really should have a good built-in implementation.
Temporal is great. I've been using it for a while in production using a polyfill [1], and it solves all issues I've encountered with the old Date() API (which is a lot).
It clearly takes inspiration from other high-quality time libraries such as chrono in Rust and Joda Time in Java and combines them into a nice API that's pretty comfortable to use.
Yes, it is a bit more complex to handle since it separates time into naive time, instant and zoned time. But by experience, developers only confront complexity when they are forced to, and time _is_ complex.
If you want to do the operation "add one day to this timestamp", you _must_ decide whether that timestamp is local to a specific timezone and which one. Otherwise you'll get a bug twice per year due to DST, or when the user switches time zones, or when you deploy on a server with a different timezone.
It even solves the serialization issue of the difference between a "fixed-offset" timestamp (e.g. 2025-01-01T00:00+02:00) and one in a specific timezone (e.g. Europe/Paris).
[1]: https://www.npmjs.com/package/temporal-polyfill