News for hackers. Stuff that matters.
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by patchnull on Wednesday March 11, 2026 @12:06PM (#47337415)
The most underappreciated design decision in Temporal is making everything immutable. Half the Date bugs I have debugged over the years come from someone calling setMonth() or setHours() on a Date object that was shared across call sites. The other half come from the implicit local timezone conversion in the Date constructor. Temporal fixes both by forcing you to be explicit about timezones through ZonedDateTime vs PlainDate, and by returning new objects instead of mutating. Nine years is a long time, but given how many TC39 proposals ship half-baked and then need follow-up proposals to fix the gaps, I would rather they got this one right.
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by ndr on Wednesday March 11, 2026 @12:13PM (#47337516)
Immutability is underrated in general. It's a sore point every time I have to handle non-clojure code.
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by recursive on Wednesday March 11, 2026 @12:16PM (#47337554)
Given the ubiquity of react, I think immutability is generally rated pretty appropriately. If anything, I think mutability is under-rated. I mean, it wouldn't be applicable to the domain of Temporal, but sometimes a mutable hash map is a simpler/more performant solution than any of the immutable alternatives.
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by LunaSea on Wednesday March 11, 2026 @12:18PM (#47337578)
Props data passed to React itself isn't immutable which is probably one of the missing bricks.

React only checks references but since the objects aren't immutable they could have changed even without the reference changing.

Immutability also has a performance price which is not always great.

Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by recursive on Wednesday March 11, 2026 @01:29PM (#47338531)
Yes, you can mutate props. But no, it's probably not going to do what you want if you did it intentionally. If react added Object.freeze() (or deepFreeze) to the component render invoker, everything would be the same, except props would be formally immutable, instead of being only expected to be immutable. But this seems like a distinction without much of a difference, because if you just try to use a pattern like that without having a pretty deep understanding of react internals, it's not going to do what you wanted anyway.
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by kccqzy on Wednesday March 11, 2026 @01:20PM (#47338404)
React doesn’t really force you to make your props immutable data. Using mutable data with React is allowed and just as error prone as elsewhere. But certainly you are encouraged to use something like https://immutable-js.com together with React. At least that’s what I used before I discovered ClojureScript.
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by hrmtst93837 on Wednesday March 11, 2026 @02:37PM (#47339426)
Immutability is often promoted to work around the complexity introduced by state management patterns in modern JS. If your state is isolated and you don't need features like time travel debugging, mutable data structures can be simpler and faster. Some so-called immutable libraries use hidden mutations or copy-on-write, which can actually make things slower or harder to reason about. Unless you have a specific need for immutability, starting with mutable structures is usually more sane.
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by hombre_fatal on Wednesday March 11, 2026 @02:56PM (#47339677)
Well, mutability is the default, and React tries to address some of the problems with mutability. So React being popular as a subecosystem inside a mutable environment isn't really evidence that people are missing out on the benefits of mutability.

Though React is less about immutability and more about uni-directional flow + the idiosyncrasy where you need values that are 'stable' across renders.

Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by virgil_disgr4ce on Wednesday March 11, 2026 @12:07PM (#47337436)
I think that actually may be the MOST appreciated design decision in Temporal ;) either way, I'm also a big fan
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by Waterluvian on Wednesday March 11, 2026 @12:32PM (#47337774)
The worst are methods that both mutate and return values.

I know this gets into a complex land of computer science that I don’t understand well, but I wish I could define in TypeScript “any object passed into this function is now typed _never_. You’ve destroyed it and can’t use it after this.” Because I sometimes want to mutate something in a function and return it for convenience and performance reasons, but I want you to have to reason about the returned type and never again touch the original type, even if they are the same object.

Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by thayne on Wednesday March 11, 2026 @02:14PM (#47339137)
> any object passed into this function is now typed _never_. You’ve destroyed it and can’t use it after this.

That is basically what affine types are. Once the value is "consumed" it can't be used again.

In rust, this is expressed as passing an "owned" value to a function. Once you pass ownership, you can't use that value anymore.

And having used it in rust, I wish more languages had something like that.

Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by kibwen on Wednesday March 11, 2026 @02:47PM (#47339556)
> And having used it in rust, I wish more languages had something like that.

Same. I'm at the point where I feel like copy-by-default semantics are one of the ancient original sins of programming languages. Single-ownership is so, so useful, and it's trivial to implement and not at all difficult to understand (especially compared to something like Rust's borrow checker).

Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by Aurornis on Wednesday March 11, 2026 @01:19PM (#47338399)
> but I wish I could define in TypeScript “any object passed into this function is now typed _never_.

Having explicit language to differentiate between pass by reference and pass by value avoids this confusion. It requires a little more thought from the programmer but it’s really minimal once you internalize it.

Rust takes this a step further with an explicit ownership and borrowing model. The compiler will refuse your code if you try to write something that that violates the borrow checker. This is endlessly frustrating to beginners but after adapting your mind to ownership safety you find yourself thinking in the same way in other languages.

I always found real-world JavaScript codebases frustrating because there was so much sharing that wasn’t entirely intentionally. It only got fixed when someone recognized a bug as a result.

Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by Waterluvian on Wednesday March 11, 2026 @01:21PM (#47338426)
Yeah exactly. That's what I've loved about Rust and hated about real-world JS. I end up having to reason about an entire case that might not be real at all: does this function mutate what I'm passing it? Should I eagerly deep copy my object? UGH.
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by stephbook on Wednesday March 11, 2026 @01:44PM (#47338747)
Just call "Object.freeze()" before "return" in your function.
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by cdmckay on Wednesday March 11, 2026 @03:21PM (#47339974)
That only goes one level deep so it’s not much of a guarantee
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by vimwizard on Wednesday March 11, 2026 @12:48PM (#47337985)
Rust ownership model ("stacked borrows" I believe it's called) is basically this
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by kibwen on Wednesday March 11, 2026 @02:49PM (#47339576)
Single-ownership ("affine types") is a separate concept from a borrow checker. Your language doesn't need a borrow checker (or references at all) to benefit from single-ownership, though it may make some patterns more convenient or efficient.
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by ChadNauseam on Wednesday March 11, 2026 @03:38PM (#47340213)
rust would be pretty unusable without references. affine lambda calculus isn’t even turing complete. however, you’re right that a borrow checker is unnecessary, as uniqueness types (the technical term for types that guarantee single ownership) are implemented in clean and idris without a borrow checker. the borrow checker mainly exists because it dramatically increases the number of valid programs.
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by kibwen on Wednesday March 11, 2026 @06:13PM (#47342890)
Supporting single-ownership in a language doesn't mean you can't have opt-in copyability and/or multiple-ownership. This is how Rust already works, and is independent of the borrow checker.

If we consider a Rust-like language without the borrow checker, it's obviously still Turing-complete. For functions that take references as parameters, instead you would simply pass ownership of the value back to the caller as part of the return value. And for structs that hold references, you would instead have them hold reference-counted handles. The former case is merely less convenient, and the latter case is merely less efficient.

Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by NooneAtAll3 on Wednesday March 11, 2026 @01:36PM (#47338635)
I think it's the other way around - he's projecting rust as what he wants
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by LoganDark on Wednesday March 11, 2026 @01:31PM (#47338570)
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by magnio on Wednesday March 11, 2026 @12:46PM (#47337966)
What you are describing is linear (or affine) types in academic parlance, where a value must be used exactly (or at most) once, e.g., being passed to a function or having a method invoked, after which the old value is destroyed and not accessible. Most common examples are prolly move semantics in C++ and Rust.
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by z3t4 on Wednesday March 11, 2026 @03:44PM (#47340285)
If you want to upset people on the internet tell them that JavaScript is strongly typed, immutable, and everything is passed by value. Which is true. You can change member values though, which is the footgun.
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by ecshafer on Wednesday March 11, 2026 @12:40PM (#47337866)
ruby has the convention of ! for dangerous destructive or mutating methods. This is something that I wish would spread around a bit.

For example:

# Original array

array = [1, 2, 3]

# Using map (non-destructive)

new_array = array.map { |x| x * 2 }

# new_array is [2, 4, 6]

# array is still [1, 2, 3] (unchanged)

# Using map! (destructive)

array.map! { |x| x * 2 }

# array is now [2, 4, 6] (modified in-place)

Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by wiseowise on Wednesday March 11, 2026 @12:44PM (#47337942)
> convention

Is the keyword. Anything that should never be broken isn’t a convention. There’s no better convention than compiler error.

Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by goatlover on Wednesday March 11, 2026 @01:10PM (#47338281)
Because Ruby is a dynamic language which mutates state. That isn't considered wrong or bad in those kinds of languages, just a way to make sure the programmer knows they're doing that. Not every PL tries to live up to the ideals of Haskell.

If you don't want an object mutated in Ruby, you can freeze it.

Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by idle_zealot on Wednesday March 11, 2026 @01:44PM (#47338740)
I don't think they're saying it shouldn't be possible to mutate arguments, just that the ! convention should be enforced. The Ruby runtime could, for instance, automatically freeze all arguments to a function that doesn't end with a !. That way all code that correctly follows the mutation naming convention will continue to work, and any development who doesn't know about it will quickly learn when they try to mutate an argument and get an error. Ideally a helpful error telling them to add the !.
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by xp84 on Wednesday March 11, 2026 @02:31PM (#47339356)
That's really interesting. Although my worry is the freezing having bad effects down the line after the function returns.

  a = [1, 2]
  
  def check_this(arr)
    raise "doesn't start with 1" unless a.first == 1
  end

  check_this(a)
  
  a << 3 # Raises "FrozenError (can't modify frozen Array)" because check_this froze `a`
Now, if you could temporarily freeze, and then unfreeze only the ones you froze, that could be really cool.
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by idle_zealot on Wednesday March 11, 2026 @04:35PM (#47341214)
> Now, if you could temporarily freeze, and then unfreeze only the ones you froze, that could be really cool.

Is that a missing feature in Ruby? You can't have a frozen reference to an object while retaining unfrozen ones in another scope? That's too bad.

Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by xp84 on Wednesday March 11, 2026 @07:43PM (#47344149)
Yeah, in my testing freeze mutates the object itself to a permanent frozen state.
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by Xenoamorphous on Wednesday March 11, 2026 @02:04PM (#47338999)
> The worst are methods that both mutate and return values

Been bitten a few times by Array.sort().

Luckily there’s Array.toSorted() now.

Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by darick on Wednesday March 11, 2026 @01:09PM (#47338269)
This is possible with the asserts x is y pattern no?

https://www.typescriptlang.org/play/?#code/C4TwDgpgBAYg9nKBe...

Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by Waterluvian on Wednesday March 11, 2026 @01:16PM (#47338368)
I think the sticking points are:

1. You cannot return anything (say an immutable result that has consumed the input)

Okay, so don't return anything, just mutate the original. Except:

2. You cannot mutate the original, return nothing, but the mutated original isn't a subset of the original. For example: https://www.typescriptlang.org/play/?#code/GYVwdgxgLglg9mABB...

Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by darick on Wednesday March 11, 2026 @01:41PM (#47338694)
Hmm, I see, yes it's quite limited.
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by deepsun on Wednesday March 11, 2026 @12:46PM (#47337963)
They seem to have taken it from Joda time that revolutionized time in java 10+ years ago. Sadly no mention of Joda.
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by tadfisher on Wednesday March 11, 2026 @02:20PM (#47339193)
Also no mention of Stephen Colebourne, author of Joda and the JSR-310 spec (the basis of java.time), the one person you should always stop and listen to when he says you are doing something wrong with time.

Alas, this post is not the only time the TC39 people ignored him.

Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by OptionOfT on Wednesday March 11, 2026 @12:59PM (#47338129)
> The other half come from the implicit local timezone conversion in the Date constructor.

Outlook at that issue even in their old C++ (I think) version.

You're in London, you save your friend's birthday as March 11th.

You're now in SF. When is your friend's birthday? It's still all-day March 11th, not March 10th, starting at 5PM, and ending March 11th at 5PM.

Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by WorldMaker on Wednesday March 11, 2026 @01:42PM (#47338709)
If your friend lives in London it may be useful to have that associated timezone so that you can be sure to message them that day in their timezone. They might better appreciate a message from SF sent on March 10th at 9PM "early that morning in London" than March 11th at 9PM "a day late".

A lot of that gets back to why Temporal adds so many different types, because there are different uses for time zone information and being clear how you shift that information can make a big difference. (A birthday is a PlainDate at rest, but when it is time to send them an ecard you want the ZonedDateTime of the recipient's time zone to find the best time to send it.)

Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by bluGill on Wednesday March 11, 2026 @01:55PM (#47338888)
His birthday is always all day. The question is where he is. If he travels to Japan his birthday won't change - even if he was born late at night and thus it would be a different day if he was born in Japan.
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by Maxion on Wednesday March 11, 2026 @02:38PM (#47339440)
The other fun ones are daily recurring events for e.g. taking some medication. You take the last one at 10pm before going to bed. You go on a trip which moves you three hours east. Now your calendar helpfully reminds you to take your meds at 1 am.
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by ravenstine on Wednesday March 11, 2026 @01:21PM (#47338422)
When I write JavaScript, I make as many things immutable as I can. Sometimes it adds verbosity and leads to less efficient computational patterns, but overall I believe I run into far fewer bugs that are hard to make sense of. There are things about the design of Temporal I don't really like, but immutability was a solid move.

What I don't understand is why they had to make string formatting so rigid. Maybe it has to do with internationalization? I'd have liked if it included a sort of templating system to make the construction of rendered date-time strings much easier.

Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by WorldMaker on Wednesday March 11, 2026 @01:52PM (#47338847)
> What I don't understand is why they had to make string formatting so rigid. Maybe it has to do with internationalization? I'd have liked if it included a sort of templating system to make the construction of rendered date-time strings much easier.

I think Temporal takes the right approach: toString() is the (mostly) round-trippable ISO format (or close to it) and every other format is accessible by toLocaleString(). In Python terms, it is a bit like formally separating __repl__ and __str__ implementations, respectively. Date's toString() being locale-dependent made it a lot harder to round-trip Date in places like JSON documents if you forgot or missed toISOString().

Temporal's various toLocaleString() functions all take the same Intl.DateTimeFormat constructor parameters, especially its powerful options [1] argument, as Date's own toLocaleString() has had for a long while and has been the preferred approach to locale-aware string formatting.

[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by Dragory on Wednesday March 11, 2026 @02:38PM (#47339452)
The problem is that sometimes you want a very specific format, not a locale-based format. This currently still has to be implemented in userland [1].

[1] https://github.com/js-temporal/proposal-temporal-v2/issues/5

Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by WorldMaker on Wednesday March 11, 2026 @08:32PM (#47344637)
A lesson I've picked up from what little localization work I've done is to avoid "specific formats" as much as possible. Some user's locale is never going to fit your "specific format" and the more you try to (micro-)manage the output format of your dates the more you are likely to make that user upset or show them a very broken experience. The short/medium/long formats you can get out of Intl.DateTimeFormat/toLocaleString aren't perfect, they are compromises, but they work and users can generally trust them.

(If you are using a specific format for something other than display to a user, maybe consider the standardized ISO format instead. Machine-to-machine communications could definitely use a whole lot fewer "specific formats" and explicit Date parsing. Very few backend languages don't have out-of-the-box support or easy found library support for ISO format today.)

Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by kandros on Wednesday March 11, 2026 @01:23PM (#47338462)
I remember the first time I got in touch with Elixir and immutability as a core principle. It changed the way I wrote JavaScript since
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by devnotes77 on Wednesday March 11, 2026 @03:04PM (#47339783)
The formatting decision is intentional and documented in the proposal: toString() is meant to be the round-trippable ISO representation, not a display string. For locale-aware output, toLocaleString() accepts the full Intl.DateTimeFormat options bag, which covers most real-world display needs.

For non-locale custom formats ("YYYY-MM-DD" style), there is a gap - Temporal deliberately does not ship a strftime-style templating system. The design rationale was that custom format strings are a source of i18n bugs (hard-coded separators, month/day order assumptions, etc). The idea was to push display formatting toward Intl so locale handling is correct by default.

In practice you can cover most cases with something like:

  const d = Temporal.PlainDate.from('2026-03-11')
  const parts = d.toLocaleString('en-CA', {year:'numeric',month:'2-digit',day:'2-digit'})
for YYYY-MM-DD (Canadian locale uses that order). Fragile, but workable.

The V2 issue Dragory linked is exactly tracking this - custom format pattern support is on the backlog. For now, date-fns or luxon work fine alongside Temporal if you need templated strings.

Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by pjmlp on Wednesday March 11, 2026 @01:49PM (#47338799)
One of the first things I learnt to appreciate in C++ already during its C++ARM days was the ability to model mutability.

Naturally there are other languages that do it much better.

The problem is that it still isn't widespread enough.

Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by VorpalWay on Wednesday March 11, 2026 @02:10PM (#47339092)
It is not just in time keeping that mutable shared state is an issue, I have seen problems arising from it elsewhere as well in Python especially, but also in C and C++. Probably because Python is pass by reference implicitly, while C and C++ makes pointers/references more explicit, thus reducing the risk of such errors in the code.

There a few schools of thought about what should be done about it. One is to make (almost) everything immutable and hope it gets optimised away/is fast enough anyway. This is the approach taken by functional languages (and functional style programming in general).

Another approach is what Rust does: make state mutable xor shared. So you can either have mutable state that you own exclusively, or you can have read only state that is shared.

Both approaches are valid and helpful in my experience. As someone working with low level performance critical code, I personally prefer the Rust approach here.

Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by tracker1 on Wednesday March 11, 2026 @02:53PM (#47339640)
Yeah... I pretty early in my career firmly cemented on a couple things with date-times. It's either a date-time + zone/location detail or always seconds from unix epoc or UTC in iso-8601 style (later JSON's adopted default) across the wire. Since most systems and JS convert pretty easily between UTC and local.

Same for storage details. I started using the 8601 style mostly in file/log naming so they always sorted correctly, this kind of carried over into my code use pre-dating JSON spec.

Doing the above saves a lot of headaches... I'd also by convention use a few utility scripts for common formatting and date changes (I use date-fns now mostly), that would always start with dtm = new Date(dtm); before manipulation, returning the cloned dtm.

Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by homebrewer on Wednesday March 11, 2026 @03:32PM (#47340125)
These LLM spambots are getting so good they're at the top of many discussions now, and people are none the wiser. Sad, but it was predictable.

Please look into its comment history and flag this. Not that it will solve anything.

Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by 1718627440 on Wednesday March 11, 2026 @04:14PM (#47340815)
I hear you, but this also affects the good discussion below it.
Re:Temporal: The 9-Year Journey to Fix Time in JavaScript by refulgentis on Wednesday March 11, 2026 @03:45PM (#47340292)
Flagged because account is bot operated (posted again 2h40m later with same general comment)