• VanCoding 4 hours 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.

    [-]
    • TimTheTinker 55 seconds ago
      How is this any different from Date?

        serialize: date.toJSON()
        deserialize: new Date(jsonDate)
      
      in Temporal:

        serialize: instant.toJSON()
        deserialize: Temporal.Instant.from(jsonDate)
    • jayflux 2 hours ago
      This was an intentional design decision. We wanted to make sure all the temporal types could be serialize/deserializable, but as you mentioned, you couldn't implicitly go back to the object you started with as JSON.parse doesn't support that.

      Instead the onus is on the developer to re-create the correct object they need on the other side. I don't believe this is problematic because if you know you're sending a Date, DateTime, MonthDay, YearMonth type from one side, then you know what type to rebuild from the ISO string on the other. Having it be automatic could be an issue if you receive unexpected values and are now dealing with the wrong types.

      There is an example here in the docs of a reviver being used for Temporal.Instant https://tc39.es/proposal-temporal/docs/instant.html#toJSON

    • perfmode 4 hours 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.

      [-]
      • VanCoding 3 hours ago
        It's not that much about type safety. Since TypeScript uses duck typing, a DateTime could not be used as a ZonedDateTime because it'd lack the "timezone" property. The other way around, though, it would work. But I wouldn't even mind that, honestly.

        The real drawback of the functional approach is UX, because it's harder to code and you don't get nice auto-complete.

        But I'd easily pay that price.

    • causal 3 hours ago
      I'm with you on this. I worked on a big Temporal project briefly and I was really turned off by how much of the codebase was just rote mapping properties from one layer to the next.
    • qcoret 4 hours ago
      All Temporal objects are easily (de)serializable, though. `.toString` and `Temporal.from` work great.
      [-]
      • VanCoding 4 hours 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.

        [-]
        • flyingmeteor 4 hours ago
          You would need to use the `reviver` parameter of `JSON.parse()` to revive your date strings to Temporal objects. As others have said, it's a simple `Temporal.from()`

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

          [-]
          • Bratmon 2 hours ago
            Having to provide a complete schema of your json everywhere your json gets parsed negates the advantages of json.
            [-]
            • true_religion 50 minutes ago
              The main advantage of json is that it’s human readable and writable. Beyond that, it has no notion of user created data types so anyone using it has to do custom unmarshalling to get a type apart from sting, number, dict and list.
            • hueho 27 minutes ago
              Most JSON libraries in typed languages require this for data binding to complex types though.
          • cyral 3 hours ago
            I've been doing this for so long and never knew there was a reviver param, thanks - that is super useful.
        • rimunroe 3 hours ago
          > 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.

          I don't know if I'm missing something, but that's exactly how I'd expect it to compose. Does the following do what you wanted your snippet to do?

            Temporal.PlainYearMonth.from(JSON.parse(JSON.stringify(Temporal.PlainYearMonth.from({year:2026,month:1}))))
          
          JSON.stringify and JSON.parse should not be viewed as strict inverses of each other. `JSON.parse(JSON.stringify(x)) = x` is only true for a for a small category of values. That category is even smaller if parsing is happening in a different place than stringification because JSON doesn't specify runtime characteristics. This can lead to things like JSON parsing incorrect in JS because they're too large for JS to represent as a number.
        • gowld 4 hours ago
          Would a plain data object be an instance of PlainYearMonth?

          If not, that regardless of being plain data or a serialized object with functions, you'd still need to convert it to the type you want.

    • Avamander 2 hours ago
      > 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

      Which makes me wonder how it'll look like when interfacing with WASM. Better than Date?

    • chrisweekly 3 hours ago
      It should still be possible to continue using date-fns (or a similar lib) to suit your preference, right?
      [-]
      • VanCoding 3 hours ago
        yes, sure. probably there will even pop up a functional wrapper around the temporal API occasionally. But would've been nice if it was like this from the start.
  • nekevss 5 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 5 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 5 hours 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 4 hours ago
      Yep, JavaScript got the bad version from Java too!

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

  • alanning 1 hour ago
    The Temporal Cookbook on TC39's site provides examples of how using the new API looks/feels:

    https://tc39.es/proposal-temporal/docs/cookbook.html

    For example, calc days until a future date: https://tc39.es/proposal-temporal/docs/cookbook.html#how-man...

    ...or, compare meeting times across timezones: https://tc39.es/proposal-temporal/docs/cookbook.html#book-a-...

  • wpollock 3 hours ago
    > "It was a straight port by Ken Smith (the only code in "Mocha" I didn't write) of Java's Date code from Java to C."

    This is funny to me; Java's util.Date was almost certainly a port of C's time.h API!

  • zvqcMMV6Zcr 5 hours ago
    > Safari (Partial Support in Technology Preview)

    Safari confirmed as IE Spiritual successor in 2020+.

    [-]
    • WorldMaker 3 hours ago
      Slower to implement new features, but still implementing them, just makes it the new Firefox. IE's larger problem was how popular it had been before it stopped implementing new features. It was like if Google got bored with Chrome and decided to stop all funding on it. People would be stuck on Chrome for years after that investment stopped because of all the Chrome-specific things built around it (Electron, Puppeteer, Selenium, etc and so forth).

      Right now the world needs a lot more Safari and Firefox users complaining about Chrome-only sites and tools than it does people complaining about Safari "holding the web back". Safari's problems are temporary. Chrome is the new Emperor and IE wasn't bad because it stopped, it was bad because it stopped after being the Emperor for some time. People remember how bad the time was after the Empire crumbled, but it's how IE took so many other things down with it that it is easier to remember the interregnum after IE crumbled than to remember the heyday when "IE-only websites are good enough for business" sounded like a good idea and not a cautionary tale.

      [-]
      • nchmy 1 hour ago
        > Right now the world needs a lot more Safari and Firefox users complaining about Chrome-only sites and tools than it does people complaining about Safari "holding the web back".

        There wouldn't be Chrome-only sites and tools if Safari wasn't holding the web back (no "quotes" needed, as that's precisely what they're doing).

        > Safari's problems are temporary.

        What are you talking about? They've been woefully behind for like a decade. Here's an excellent article on the topic: https://infrequently.org/2023/02/safari-16-4-is-an-admission...

        And an entire series: https://infrequently.org/series/browser-choice-must-matter/

        [-]
        • WorldMaker 33 minutes ago
          > There wouldn't be Chrome-only sites and tools if Safari wasn't holding the web back (no "quotes" needed, as that's precisely what they're doing).

          It's a matter of perspective. The safer perspective is: Safari isn't holding the web back, Chrome is moving too fast. Developers making Chrome-only sites and tools are moving too fast for the safety of web standards/web platform. Where one of the safety factors is "widely available in multiple implementations, not just a single browser".

          > > Safari's problems are temporary.

          > What are you talking about?

          The point is that Safari may be moving slow, but it is still moving. It doesn't have enough users to hold the web back. It isn't "always a decade behind", it 's "a couple years to a couple months behind", depending on which caniuse or MDN Baseline approach you want to take.

          There are some things Safari doesn't want to implement, but has registered safety or privacy or coupling reasons behind such things. Firefox is doing the same.

          Safari isn't trapping website developers in "old standards forever", it is encouraging developers to use safe, private, stable choices. Chrome is "move fast and sometimes break things". Safari doesn't want to be that. That's useful for the web as a platform to have one or two browsers considering their implementations. It's a good reason to point out "Chrome-only" developers as being "too bleeding edge" (sometimes emphasis on the bleeding) and out of touch with standards and standards processes.

    • cubefox 4 hours ago
      2026 A.D., still no support for native date pickers in mobile Safari.
      [-]
      • CharlesW 4 hours ago
        Safari for iOS got native date pickers in 2012, and desktop Safari got them in 2021.
  • xp84 2 hours ago
    They travelled through time (forward, at 1X) by nine years to do this for us. I appreciate it.
  • bnb 5 hours ago
    Can't wait for it to land in the server-side runtimes, really the last thing preventing me from adopting it wholesale.
    [-]
    • WorldMaker 3 hours ago
      Deno has had it behind the `--untable-temporal` flag for quite a few Minor versions now and the latest Minor update (because of TC-39's Stage 4 acceptance and V8 itself also marking the API as Stable) removed the requirement for the flag and it is out of the box.
    • apaprocki 5 hours ago
      Node 26! Only a matter of time... :)
    • CharlesW 4 hours ago
      FWIW, I've been using it server-side via the js-temporal polyfill for some time, no issues.
      [-]
      • bnb 3 hours ago
        ooh I'd not seen that yet, will have to take a look.
  • the__alchemist 2 hours ago
    Maybe I will be able to move away from my custom/minimal DT lib, and ISO-8601 timestamp strings in UTC. JS datetime handling in both Date and Moment are disasters. Rust's Chrono is great. Python's builtin has things I don't like, but is useable. Date and Moment are traps. One of their biggest mistakes is not having dedicated Date and Time types; the accepted reason is "Dates and times don't exist on their own", which is bizarre. So, it's canon to use a datetime (e.g. JS "Date") with 00:00 time, which leads to subtle errors.

    From the link, we can see Temporal does have separate Date/Time/Datetime types. ("PlainDate" etc)

  • kemitchell 52 minutes ago
    > The first proposal I worked on was Promise.allSettled, which was fulfilling.

    Har har.

  • kemayo 3 hours ago
    > Developers would often write helper functions that accidently mutated the original Date object in place when they intended to return a new one

    It's weird that they picked example code that is extremely non-accidentally doing this.

  • julius_eth_dev 2 hours ago
    Nine years is a long time, but honestly it tracks with how deeply broken Date has been since Brendan Eich cargo-culted java.util.Date in 1995. The real win with Temporal isn't just immutability or timezone support — it's that PlainDate and ZonedDateTime finally give us types that match how humans actually think about time. I've lost count of how many bugs I've shipped because Date silently coerces everything to UTC instants when half the time what you actually have is a "wall clock" value with no timezone attached.
    [-]
    • cityofdelusion 47 minutes ago
      Assuming this isn’t an LLM bot, I don’t see how you ship that bug multiple times. The docs for JS time are pretty minimal and it’s clear it only stores UTC epoch, so why would you assume it can handle “wall clock time” with no other context?

      It doesn’t matter if it’s python or tsql or JS or perl — you read the docs on the date time impl every time.

  • johncomposed 2 hours ago
    As a side note, huge fan of Promise.allSettled. When that dropped it cleaned up so much of the code I was writing at the time.
  • tracker1 2 hours ago
    Looking at the caniuse results... f*king Safari (and Opera)...

    https://caniuse.com/temporal

    [-]
    • beezlewax 1 hour ago
      And I have to support safari while dealing with all the problems that are mentioned in this article. Maybe there is a polyfill.
    • agos 2 hours ago
      I usually am not too harsh on Safari on implementation of new features but this is a bummer, and reflects poorly on them
  • philipallstar 4 hours 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?

    [-]
    • WorldMaker 3 hours ago
      Right, browsers own it instead of websites needing to rebuild Moment.js bundles. Additionally, most browsers pass the ownership further to the user's OS as the IANA timezone database is a useful system-level service and best updated at the cadence of OS "required" updates.
    • nekevss 4 hours 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.
  • SoftTalker 3 hours ago
    It's been a while since I worked in JS but dealing with dates/times, and the lack of real integer types were always two things that frustrated me.
  • hungryhobbit 4 hours 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();
    [-]
    • evolve2k 38 minutes ago
      Firstly, 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.

    • sourcegrift 3 hours ago
      If 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.
      [-]
      • Bratmon 2 hours ago
        I'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!

      • themafia 2 hours ago
        I'm a programmer. I'm a human. Perhaps we should also allow for some "human theory" inside our understanding.
  • redbell 4 hours ago
    Oh, for a second, TeMPOraL (https://news.ycombinator.com/user?id=TeMPOraL) came to my mind!
  • samwho 5 hours ago
    Thanks for linking to my silly little quiz in the article! :)
  • darepublic 4 hours ago
    My playbook for JavaScript dates is.. store in UTC.. exchange only in UTC.. convert to locale date time only in the presentation logic. This has worked well for me enough that Im skeptical of needing anything else
    [-]
    • WorldMaker 1 hour ago
      Storing in UTC is lossy. You've lost information about the event's original UTC offset, at the very least, and probably also its original time zone. Most backends today have good ways to round-trip offset information, and still compare dates easily (as if they were normalized to UTC). Some backends can even round-trip timezone information in addition to offsets.

      It's easy not to feel that loss as a big deal, but captured offsets can be very helpful for exactly debugging things like "what time did this user think this was?" versus time zone math (and DST lookups) from UTC. It can help debug cases where the user's own machine had missed a DST jump or was briefly on a different calendar or was traveling.

      But a lot of the biggest gains in Temporal are the "Plain" family for "wall clock times"/"wall calendar dates" and breaking them apart as very separate data types. Does a UTC timestamp of "2026-02-01 00:00:00Z" mean midnight specifically and exactly or where you trying to mark "2026-02-01" without a time or timezone. Similarly I've seen data like "0001-01-01 12:10:00Z" mean "12:10" on a clock without the date or timezone being meaningful, but Temporal has a PlainTime for that. You can convert a PlainDate + a PlainTime + a Time Zone to build a ZonedDateTime, but that becomes an explicit process that directly explains what you are trying to do, versus accidentally casting a `Date` intended to be just a wall-clock time and getting a garbage wall-clock date.

    • ibejoeb 2 hours ago
      For recording instantaneous events, that's usually sufficient. It's often not enough for scheduling. You can always present UTC or any other zone relative to some other zone, but you need to know that zone. Maybe you're going to a conference in another region and you want to know the time of a talk in that zone because that's more important than your zone. You either need to couple the zone with the time itself, or you need to refer to it. There are good reasons either way. Having an atomic time+zone type is basically trading space for time. When its embedded, you can just use it, which can be better than assuming UTC and then looking up the zone based on, say, the location of the venue.
    • andrewl-hn 3 hours ago
      The only time you need local dates is for scheduling. Stuff like “Report KPIs for each shift. Shifts start at 8:00 local time.”, or “send this report every day at 10:00 local time”, or “this recurring meeting was created by user X while they were in TimeZone Z, make sure meetings follow DST”.

      Outside of scheduling UTC is the way.

      [-]
      • 1-more 8 seconds ago
        The pathological case with scheduling is: It's 2015. You live in NYC. Your pal in Santiago, Chile says "hey next time you're here let's hang out." You say "great, I have a business trip there next April. Let's have dinner at 7pm on the 15th." They agree. You enter it into your calendar. If you store it as UTC, you're going to show up to dinner at the wrong time—the DST rules changed in between when you talked and when you expected dinner to happen. If you'd stored it as a local time with tzdb name America/Santiago you'd be there at the correct local time.
      • masfuerte 2 hours ago
        > Report KPIs for each shift. Shifts start at 8:00 local time.

        To represent this you probably don't want a local date. Plain times [1] and plain date/times [2] are a better fit.

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

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

    • recursive 2 hours ago
      It does work quite well. Sometimes you need a time zone to go with it. It might not be common, but sometimes you need to know the local time in a particular zone, which is not necessarily where the user is. I work on software that works with local times in arbitrary time zones. We submit data in a schema over which we have no control, which must include such local times that may or may not be in the time zone of the server or the current client machine.
    • themafia 3 hours ago
      I have a scheduling system that allows users to specify recurring events. "Every Monday at 2pm." Which needs to be understood in the native timezone of that user and needs to be capable of being displayed in that timezone for all viewers or optionally in the native timezone of the viewing user.

      Temporal is a blessing.

    • lpa22 3 hours ago
      Same here, this is the way
    • NooneAtAll3 3 hours ago
      why UTC and not epoch then?
      [-]
      • SoftTalker 3 hours ago
        Epoch (a/k/a "unix timestamps") are OK when you just need an incrementing relative time. When you start converting them back and forth to real calendar dates, times, with time zones, DST, leap seconds, etc. the dragons start to emerge.

        A lesson I learned pretty early on is always use the date-time datatypes and libraries your language or platform gives you. Think very carefully before you roll your own with integer timestamps.

  • sharktheone 5 hours ago
    Very happy for it finally being there!
  • normie3000 5 hours ago
    No mention of JodaTime?
  • ventuss_ovo 2 hours ago
    interesting point about immutability
  • jon_kuperman 5 hours ago
    What a journey!
  • ChrisArchitect 4 hours ago
    A good article and discussion from January:

    Date is out, Temporal is in

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

  • NooneAtAll3 3 hours ago
    so Temporal is copying cpp's std::chrono?
    [-]
    • andrewl-hn 3 hours ago
      More like a copy of Java’s JSR310, which in turn took many years to get right.
  • virgil_disgr4ce 5 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!
  • ChrisArchitect 4 hours ago
    Aside: Bloomberg JS blog? ok.
    [-]
    • robpalmer 3 hours ago
      Yep. You can learn more about why we created this new blog here:

        https://bloomberg.github.io/js-blog/post/intro/
      
      I hope you like it ;-)

      And if it seems like a surprise, you can blame me for not publicising this kind of content earlier given how long we've been working in this area. Thankfully Jon Kuperman and Thomas Chetwin (plus others) found the time and energy to put this platform together.

    • deepsun 4 hours 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).
      [-]
    • wiseowise 4 hours 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

  • patchnull 5 hours ago
    [flagged]
    [-]
    • Waterluvian 4 hours 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.

      [-]
      • thayne 3 hours ago
        > 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.

        [-]
        • kibwen 2 hours ago
          > 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).

      • Aurornis 4 hours ago
        > 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.

        [-]
        • Waterluvian 4 hours ago
          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.
          [-]
          • stephbook 3 hours ago
            Just call "Object.freeze()" before "return" in your function.
            [-]
            • cdmckay 2 hours ago
              That only goes one level deep so it’s not much of a guarantee
      • vimwizard 4 hours ago
        Rust ownership model ("stacked borrows" I believe it's called) is basically this
        [-]
        • kibwen 2 hours ago
          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.
          [-]
          • ChadNauseam 1 hour ago
            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.
        • NooneAtAll3 3 hours ago
          I think it's the other way around - he's projecting rust as what he wants
        • LoganDark 3 hours ago
      • magnio 4 hours 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 4 hours 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 4 hours ago
          > convention

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

          [-]
          • goatlover 4 hours 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.

            [-]
            • idle_zealot 3 hours ago
              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 !.
              [-]
              • xp84 2 hours ago
                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.
                [-]
                • idle_zealot 18 minutes ago
                  > 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.

      • Xenoamorphous 3 hours ago
        > The worst are methods that both mutate and return values

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

        Luckily there’s Array.toSorted() now.

      • z3t4 1 hour ago
        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.
      • darick 4 hours ago
        This is possible with the asserts x is y pattern no?

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

        [-]
        • Waterluvian 4 hours ago
          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...

          [-]
          • darick 3 hours ago
            Hmm, I see, yes it's quite limited.
    • homebrewer 1 hour ago
      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.

      [-]
      • 1718627440 39 minutes ago
        I hear you, but this also affects the good discussion below it.
    • OptionOfT 4 hours 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.

      [-]
      • WorldMaker 3 hours ago
        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.)

        [-]
        • bluGill 3 hours ago
          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.
          [-]
          • Maxion 2 hours ago
            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.
    • ndr 5 hours ago
      Immutability is underrated in general. It's a sore point every time I have to handle non-clojure code.
      [-]
      • recursive 5 hours 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 5 hours 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.

          [-]
          • recursive 3 hours ago
            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.
        • kccqzy 4 hours ago
          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.
        • hrmtst93837 2 hours ago
          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.
        • hombre_fatal 2 hours ago
          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.

    • tracker1 2 hours ago
      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.

    • VorpalWay 3 hours ago
      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.

    • pjmlp 3 hours ago
      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.

    • ravenstine 4 hours ago
      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.

      [-]
      • WorldMaker 3 hours ago
        > 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...

        [-]
      • kandros 3 hours ago
        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
      • devnotes77 2 hours ago
        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.

    • deepsun 4 hours ago
      They seem to have taken it from Joda time that revolutionized time in java 10+ years ago. Sadly no mention of Joda.
      [-]
      • tadfisher 3 hours ago
        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.

    • virgil_disgr4ce 5 hours ago
      I think that actually may be the MOST appreciated design decision in Temporal ;) either way, I'm also a big fan
    • refulgentis 1 hour ago
      Flagged because account is bot operated (posted again 2h40m later with same general comment)
  • patchnull 1 hour ago
    [flagged]
    [-]
    • sharifhsn 1 hour ago
      Your bot messed up and posted twice in the same thread.
  • newzino 3 hours ago
    [dead]
  • aplomb1026 3 hours ago
    [dead]
  • ilovesamaltman 2 hours ago
    [flagged]
  • patchnull 2 hours ago
    [flagged]