NHacker Next
  • new
  • past
  • show
  • ask
  • show
  • jobs
  • submit
Temporal: A nine-year journey to fix time in JavaScript (bloomberg.github.io)
patchnull 1 hours ago [-]
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.
Waterluvian 42 minutes ago [-]
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.

darick 6 minutes ago [-]
This is possible with the asserts x is y pattern no?

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

vimwizard 27 minutes ago [-]
Rust ownership model ("stacked borrows" I believe it's called) is basically this
magnio 28 minutes ago [-]
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.
ecshafer 35 minutes ago [-]
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)

wiseowise 30 minutes ago [-]
> convention

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

goatlover 5 minutes ago [-]
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.

OptionOfT 16 minutes ago [-]
> 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.

ndr 1 hours ago [-]
Immutability is underrated in general. It's a sore point every time I have to handle non-clojure code.
recursive 59 minutes ago [-]
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.
LunaSea 57 minutes ago [-]
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.

deepsun 28 minutes ago [-]
They seem to have taken it from Joda time that revolutionized time in java 10+ years ago. Sadly no mention of Joda.
virgil_disgr4ce 1 hours ago [-]
I think that actually may be the MOST appreciated design decision in Temporal ;) either way, I'm also a big fan
nekevss 1 hours ago [-]
Super happy to see Temporal accepted!

Congrats to all the champions who worked super hard on this for so long! It's been fun working on temporal_rs for the last couple years :)

plucas 1 hours ago [-]
Would have been interesting to connect back to Java's own journey to improve its time APIs, with Joda-Time leading into JSR 310, released with Java 8 in 2014. Immutable representations, instants, proper timezone support etc.

Given that the article refers to the "radical proposal" to bring these features to JavaScript came in 2018, surely Java's own solutions had some influence?

apaprocki 55 minutes ago [-]
I would characterize it more as Joda likely informed Moment.js, which better informed TC39 because it was within the JavaScript ecosystem. As we discussed in plenary today when achieving consensus, every programming language that implements or revamps its date time primitives has the benefit of all the prior art that exists at that instant. TC39 always casts a wide net to canvas what other ecosystems do, but isn't beholden to follow in their footsteps and achieves consensus on what is best for JavaScript. So my view is this more represents what the committee believes is the most complete implementation of such an API that an assembled group of JavaScript experts could design over 9 years and finalize in 2026.
mrkeen 9 minutes ago [-]
Yep, JavaScript got the bad version from Java too!

https://news.ycombinator.com/item?id=42816135

hungryhobbit 3 minutes 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 wit something that was just two steps forward, instead of making us write this nightmare all over the place?

bnb 1 hours ago [-]
Can't wait for it to land in the server-side runtimes, really the last thing preventing me from adopting it wholesale.
CharlesW 9 minutes ago [-]
FWIW, I've been using it server-side via the js-temporal polyfill for some time, no issues.
apaprocki 1 hours ago [-]
Node 26! Only a matter of time... :)
VanCoding 19 minutes ago [-]
A big step in the right direction, but I still don't like the API, here's why: Especially in JavaScript where I often share a lot of code between the client and the server and therefore also transfer data between them, I like to strictly separate data from logic. What i mean by this is that all my data is plain JSON and no class instances or objects that have function properties, so that I can serialize/deserialize it easily.

This is not the case for Temporal objects. Also, the temporal objects have functions on them, which, granted, makes it convenient to use, but a pain to pass it over the wire.

I'd clearly prefer a set of pure functions, into which I can pass data-only temporal objects, quite a bit like date-fns did it.

perfmode 40 seconds ago [-]
This is a real pain point and I run into the same tension in systems where data crosses serialization boundaries constantly. The prototype-stripping problem you're describing with JSON.parse/stringify is a specific case of a more general issue: rich domain objects don't survive wire transfer without a reconstitution step.

That said, I think the Temporal team made the right call here. Date-time logic is one of those domains where the "bag of data plus free functions" approach leads to subtle bugs because callers forget to pass the right context (calendar system, timezone) to the right function. Binding the operations to the object means the type system can enforce that a PlainDate never accidentally gets treated as a ZonedDateTime. date-fns is great but it can't give you that.

The serialization issue is solvable at the boundary. If you're using tRPC or similar, a thin transform layer that calls Temporal.Whatever.from() on the way in and .toString() on the way out is pretty minimal overhead. Same pattern people use with Decimal types or any value object that doesn't roundtrip through JSON natively. Annoying, sure, but the alternative is giving up the type safety that makes the API worth having in the first place.

qcoret 17 minutes ago [-]
All Temporal objects are easily (de)serializable, though. `.toString` and `Temporal.from` work great.
VanCoding 10 minutes ago [-]
That's not what I mean. Even though it is serializable, it's still not the same when you serialize/deserialize it.

For example `JSON.parse(JSON.stringify(Temporal.PlainYearMonth.from({year:2026,month:1}))).subtract({ years: 1})` won't work, because it misses the prototype and is no longer an instance of Temporal.PlainYearMonth.

This is problematic if you use tRPC for example.

16 minutes ago [-]
philipallstar 22 minutes ago [-]
> have to agree on what "now" means, even when governments change DST rules with very little notice.

I didn't spot how Temporal fixes this. What happens when "now" changes? Does the library get updated and pushed out rapidly via browsers?

nekevss 17 minutes ago [-]
Typically time zone data is updated in IANA's time zone database. That data would need to be updated in the implementation. In this case, the browser would need to update their time zone data.
zvqcMMV6Zcr 54 minutes ago [-]
> Safari (Partial Support in Technology Preview)

Safari confirmed as IE Spiritual successor in 2020+.

cubefox 39 minutes ago [-]
2026 A.D., still no support for native date pickers in mobile Safari.
CharlesW 6 minutes ago [-]
Safari for iOS got native date pickers in 2012, and desktop Safari got them in 2021.
redbell 39 minutes ago [-]
Oh, for a second, TeMPOraL (https://news.ycombinator.com/user?id=TeMPOraL) came to my mind!
sharktheone 1 hours ago [-]
Very happy for it finally being there!
ChrisArchitect 34 minutes ago [-]
A good article and discussion from January:

Date is out, Temporal is in

https://news.ycombinator.com/item?id=46589658

samwho 1 hours ago [-]
Thanks for linking to my silly little quiz in the article! :)
ChrisArchitect 32 minutes ago [-]
Aside: Bloomberg JS blog? ok.
deepsun 24 minutes ago [-]
Bloomberg has a pretty large software engineering department, including a lot of offshore contractors. Similar to Walmart Labs that does cool stuff as well, despite being part of a retail chain (retail industry typically sees SWEs a cost, not asset).
ChrisArchitect 16 minutes ago [-]
oh, just meant it was a new tech blog from them.
wiseowise 23 minutes ago [-]
What surprises you? Terminal UI is written in JS using Chromium. It’s not just plain Chromium, but it’s still funny that it’s pretty much same approach as universally (according to HN and Reddit) hated Electron.

https://youtu.be/uqehwCWKVVw?is=wBijGwdD2k2jIOu7

virgil_disgr4ce 1 hours ago [-]
Pretty big fan of Temporal. Been using the polyfill for a while. Very nice to use a modern, extremely well thought-through API!
jon_kuperman 2 hours ago [-]
What a journey!
normie3000 1 hours ago [-]
No mention of JodaTime?
Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact
Rendered at 17:15:07 GMT+0000 (Coordinated Universal Time) with Vercel.