Temporal: The 9-year journey to fix time in JavaScript

(bloomberg.github.io)

766 points | by robpalmer 1 day ago

58 comments

  • wesselbindt 1 day ago
    I'm very happy about this. The fact that Temporal forces you to actually deal with the inherent complexities of time management (primarily the distinction between an instant and a calendar datetime) makes it incredibly difficult to make the mistakes that Date almost seems designed to cause. It's a bit more verbose, but I'll take writing a handful of extra characters over being called at 3AM to fix a DST related bug any day of the week.
    • anowell 1 day ago
      Agreed. We've almost eradicated our usage of JS Date - fixing plenty of bugs along the way, and then I extracted thousands of lines of conversions and formatting from our production app (scheduling focused) into a temporal-fun package to make it Temporal more ergonomic for lots of common cases.

      npmjs.com/package/temporal-fun

      • lightwords 19 hours ago
        Word of warning Temporal relies on the Intl API for formatting, and support in Chrome is very limited due to their binary size constraints. As a result, you'll need to polyfill unsupported languages using format.js
        • TimTheTinker 14 hours ago
          Format.js polyfills a lot of stuff that's already supported in modern browsers, and seems to prefer its own polyfills to the native APIs.

          Is there any way to force it to only use (and bundle) the polyfills that are needed assuming 2025+ era browsers?

        • rafram 18 hours ago

            $ du -sh '/Applications/Google Chrome.app'
             1.3G    /Applications/Google Chrome.app
      • 698969 19 hours ago
        That looks neat although your package is missing a link to the source repository.
        • anowell 17 hours ago
          Good catch. Will get that added today.

          github.com/howie-code/temporal-fun

    • throwaway_12629 1 day ago
      Technically, you're not likely to to have to fix a DST bug at 3AM any day but Sunday.
      • dskloet 1 day ago
        That's a great example of the kind of wrong assumption that makes dealing with dates and times so challenging.

        Some countries start on a Friday or Saturday and until 2022 Iran could start any day of the week although never at 3AM.

      • usefulcat 1 day ago

            // call foo() one day from now:
            sleep(86400); foo();
        • hdjrudni 1 day ago
          Sorry, sleep returned a Promise and you didn't await it. You called foo() immediately.
        • koakuma-chan 23 hours ago
          What you want there is to stop saying "day" and instead say "24 hours." This way the code is correct and you don't need to deal with time weirdness.
          • danbruc 20 hours ago
            No, because if I want something to happen everyday at 12 o'clock, I have to wait for one day, if I wait for 24 hours, I will be off by an hour for half of the year.
            • koakuma-chan 15 hours ago
              Why do you want something to happen everyday at 12 o'clock specifically? If this is truly what you want, sure.
              • danbruc 8 hours ago
                Lunch break reminder popup?
            • loloquwowndueo 18 hours ago
              Only if you live in one of the brain dead countries that observe the dst anachronism.
              • eureka7 16 hours ago
                ok, but they still observe it and you still have to deal with it in your code.

                our personal convictions don't change that fact.

          • mklepaczewski 19 hours ago
            You seem to assume that a day always has 24 hours. Common (but not only) non-24h day lengths are: - 23 hours - 25 hours - 24 hours 1 second - 23 hours 59 minutes 59 seconds

            You could assume that a day isn't exactly 24 hours, but it's close-ish to 24 hours. Nope, not even close.

            And that assumes that we can treat an hour as a precise measure of time (we can't). On some systems, even a second is not a precise measure of time (second smearing).

            To make things worse, those are "simple" edge cases.

            Time is hard. I'm not sure if I can make any statement about time that is true.

            • koakuma-chan 15 hours ago
              I am saying that you shouldn't use day as a unit of time. You should use second, minute, hour, etc, because these have a constant duration. sleep(86400) should reliably make your thread sleep for at least 24 hours.
              • mklepaczewski 13 hours ago
                It depends on the context and the system you’re working with. In some systems, an hour may last 3599, 3600 or 3601 seconds (due to the leap second), a minute may be 59,60 or 61 seconds. Even a second is not always a „true” second.

                There’s no single time unit that works for all situations.

      • manarth 16 hours ago
        Some countries alter their observance of DST in line with their observance of Ramadan, which means that the time-offset changes aligned with Ramadan.

        Ramadan is observed from one visual sighting of a crescent moon to the next.

        Cloud conditions may prevent sighting and thereby alter the official start of Ramadan for an individual location, and from time-to-time, the start of a country's change in timezone.

        • troad 5 hours ago
          > Some countries alter their observance of DST in line with their observance of Ramadan, which means that the time-offset changes aligned with Ramadan.

          Only Morocco does this, I believe, and it's not even clear that that's actually official time at this point. In 2018, Morocco abolished DST, but it seems unclear what that means in practice.

          I'd love it if someone from Morocco could weigh in on what the actual situation is on the ground. Do people still change their clocks for Ramadan? Would they be annoyed if a website kept Moroccan users on standard time during Ramadan?

        • jacquesm 16 hours ago
          Cue a longish article titled 'Falsehoods Programmers Believe About Time'
    • SOLAR_FIELDS 1 day ago
      In this day and age when a natural language query can produce the most AbstractBeanFactoryFactoryBeanFactory boilerplate at the same rate as a much more concise equivalent, does verbosity matter as much?
      • zelphirkalt 13 hours ago
        If you want to understand what is going on at all, then yes, good abstraction layers do matter, and a lot at that. Hashtag cognitive debt.
  • Vinnl 1 day ago
    > Whilst Firefox was able to implement Temporal as it was being specced - thanks to the great work of André Bargull (known online as Anba)

    It's worth highlighting that André is actually a volunteer contributor who managed to implement the whole thing by themselves.

    • sfink 1 day ago
      Considering how prolific anba is, the only way we know he isn't an LLM is because he'd have to be several generations more advanced than the current SOTA. (It is possible that he might be an LLM from a few decades in the future, considering the connection to Temporal.)

      anba implemented all of Temporal single-handedly, plus fixed up numerous places in the spec, plus migrated the implementation over some massive changes after other implementers discovered what a monster it all is. The original version of the spec kind of forced two separate internal implementation paths for everything, one for custom calendars and one for the built-in stuff, just to make the built-in one reasonably performant. That was a lot of work to implement, and a lot of work to remove. (I think ptomato shepherded the spec side of that?)

      Fortunately, anba knows how to take a break, relaxing occasionally with minor tasks like rewriting large swathes of the JIT code generator to optimize the support on various platforms. He also gets plenty of nutrition, by ingesting entire specs and mind-melding with them.

      • apaprocki 16 hours ago
        I feel like those not involved in this space might not realize so much stuff that benefits the entire web/world comes from volunteers like anba and companies outside the usual browser vendors. Whether you’re an individual contributor or you want to push your employer to contribute or let you contribute, the best time to get involved is always now. We owe anba a big one. Thank you!!
  • Animats 1 day ago
    I went through a similar decade-long fire drill around ISO8601 date parsing in Python.[1] Issue started in 2012, and after about a decade a solution was in the standard library.

    [1] https://groups.google.com/g/comp.lang.python/c/Q2w4R89Nq1w

    • baliex 1 day ago
      Thank you thank you thank you.

      Parsing dates with anything other than fromisoformat feels totally backwards in comparison. We were using ciso8601 until fromisoformat was in the standard library. And now things are incredibly simple and reliable.

  • VanCoding 1 day 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.

    • jayflux 1 day 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

      • frde_me 1 day ago
        So it's intentional to make people pass down raw strings versus making the communication safe(er) by default?
        • Hasnep 1 day ago
          There are no date, time or datetime types in JSON, so you'll have to serialise it to a string or an int anyway, and then when deserialising you'll need to identify explicitly which values should be parsed as dates.
          • zelphirkalt 13 hours ago
            Well, you could still have a compound object in JSON, that is output by the Temporal API, and which given as input is guaranteed to result in an equal object it was created/serialized from. This compound object must contain all required infos about timezones and such stuff.
        • Manishearth 1 day ago
          .... we're talking about serialization here. "convert to a raw string" is sort of the name of the game.

          It's a string in a well specified string format. That's typically what you want for serialization.

          Temporal is typed; but its serialization helpers aren't, because there's no single way to talk about types across serialization. That's functionality a serialization library may choose to provide, but can't really be designed into the language.

        • hdjrudni 1 day ago
          You realize that JSON isn't just for JavaScript to JavaScript communication, right? Even if you had a magical format (which doesn't make sense and is a bad idea to attempt to auto-deserialize), it wouldn't work across languages.

          If you really want that, it's not very hard to design a pair of functions `mySerialize()`, `myDeserialize()` that's a thin wrapper over `JSON.parse`.

        • jitl 1 day ago
          its gotta become bytes somehow
    • perfmode 1 day 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.

      • downsplat 16 hours ago
        For most situations, I deal with this by keeping dates as strings throughout the app, not objects. They get read from the db as strings, passed around as strings. If I need datetime calculations, I use the language's datetime objects to do it and convert right back to string. Display formatting for users happens at the last moment, in the template.

        No-one seems to like this style, but I find it much simpler than converting on db read/write and passing datetime objects around.

      • TimTheTinker 1 day ago
        Sounds like we need an extended JSON with the express intent of conveying common extended values and rich objects: DateTime instants (with calendar system & timezone), Decimal, BigInt, etc.
        • sheept 1 day ago
          I disagree: this is not unlike including the schema in the JSON itself. This should be handled by the apps themselves, since they would have to know what the keys mean regardless.

          If you do want the interchange format to be the one deserializing into specific runtime data structures, use YAML. YAML's tag syntax allows you to run arbitrary code inside YAML, which can be used for what you want.

          • TimTheTinker 1 day ago
            I'm not talking about something arbitrarily extensible or compound values like vectors or lat/lon. Just a few more common data types -- primitive-like values that frequently need to be passed around.

            This would probably best exist as a well-known wrapper around JSON itself.

            • jitl 1 day ago
              there are a zillion of these "json pro" kind of things: superjson, devalue, capnweb, all with slightly different ideas about how to lower high-level semantics to json's available types. it's so easy to do this kind of thing, its a real https://xkcd.com/927/ situation.

              CBOR (Concise Binary Object Representation) has JSON-like semantics with type extension support; with built in type extensions its much easier to get some agreement about registering certain magic type IDs to mean certain things. for example from a random google search for "cbor datetime" https://j-richter.github.io/CBOR/date.html; there's an IANA registry of type IDs: https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml

              however, it is binary.

            • akdev1l 1 day ago
              Amazon ION is kind of this?

              Few people seem to use it outside of Amazon tho

        • mrighele 19 hours ago
          I think a more practical and compatible approach is to keep json as it is, and use a side channel (e.g. an openapi spec) to convey metadata. Then it is up to the client to decide that a date returned as a string is a date or string, or to create a specific class instead of a generic object
      • VanCoding 1 day 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.

    • TimTheTinker 1 day ago
      Updating JSON.parse() to automatically create Temporal objects (from what shape of JSON value?) without a custom reviver would be a step too far, in my opinion.

      This is effectively no different from Date:

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

        serialize: instant.toJSON()
        deserialize: Temporal.Instant.from(jsonDate)
    • tshaddox 1 day ago
      Don’t JavaScript Date instances have the same problem? Date implements toJSON, but when parsing JSON you’ll have to manually identify which string values represent Dates and convert them back to Date instances. The exact same is true of Temporal (e.g. Instant).

      And as far as I know, date-fns deals with native Date instances, not “data-only objects.”

    • nulltrace 1 day ago
      The serialization thing is real but I don't think OOP vs functional is the actual issue here. JSON has no date type, period. You JSON.stringify a Date, get an ISO string, and hope whoever's parsing remembers to reconstruct it. Temporal doesn't fix that part, but at least when you do reconstruct you're saying "this is a ZonedDateTime" vs "this is an Instant" instead of everything being one ambiguous Date object.
    • qcoret 1 day ago
      All Temporal objects are easily (de)serializable, though. `.toString` and `Temporal.from` work great.
      • VanCoding 1 day 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 1 day 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...

          • foresterre 1 day ago
            Depending on your needs (i.e. how you would otherwise use your output jspn), using the reviver can have a significant impact on performance. JSON.parse itself is hyper-optimized. At the company I work we used the reviver for almost exactly this, but profiling showed that using the reviver had enormous impact on performance. We cut it out, and won in the seconds of performance for some large json's.
          • cyral 1 day ago
            I've been doing this for so long and never knew there was a reviver param, thanks - that is super useful.
          • Bratmon 1 day ago
            Having to provide a complete schema of your json everywhere your json gets parsed negates the advantages of json.
            • true_religion 1 day 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.
            • hdjrudni 1 day ago
              Even if you don't explicitly provide a schema, you implicitly still have one. The recipient needs to know what you're sending them. Unless maybe you want to start parsing JSON payloads with an LLM.
            • hueho 1 day ago
              Most JSON libraries in typed languages require this for data binding to complex types though.
              • Bratmon 1 day ago
                Which is why many developers only use JavaScript Object Notation for JavaScript objects, and only JavaScript objects that can losslessly be written as JSON. Which this proposal explicitly does not support.
            • afiori 1 day ago
              {"$temporal_type":"PlainYearMonth","$data":"........"}
        • rimunroe 1 day 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.
        • aubergene 1 day ago
          This seems more to do with how JSON works than Temporal. There are libraries such as Devalue which will handle this for you

          `devalue.parse(devalue.stringify(Temporal.PlainYearMonth.from({year:2026,month:1}))).subtract({ years: 1})`

          https://www.npmjs.com/package/devalue

        • tshaddox 1 day ago
          This is also true of JavaScript Date instances, so I’m curious what solution you had that did work with raw JSON stringify and parse.
        • cyberrock 1 day ago
          Then you're talking about changing JSON.parse to start parsing some schema as a type instead of object, which would break compatibility.
        • jonathrg 1 day ago
          The JSON types are string, number, boolean, null, object and array. So how could the suggested code possibly work? Do you want JSON.parse to do arbitrary code execution like Python's pickle?
        • gowld 1 day 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.

    • causal 1 day 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.
    • Avamander 1 day 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 1 day ago
      It should still be possible to continue using date-fns (or a similar lib) to suit your preference, right?
      • VanCoding 1 day 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.
  • plucas 1 day 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 1 day 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.
      • MBCook 1 day ago
        Well said. As a Java programmer who hasn’t touched Temporal yet in JS it is extremely similar to the new Java types like… ZonedDateTime.

        It’s not identical. The names of the “Plain” objects make a bit more sense to me than the “Local” names Java chose.

        But overall easy to use and a fantastic improvement. I can’t wait to get to use it.

    • mrkeen 1 day ago
      Yep, JavaScript got the bad version from Java too!

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

    • mexicocitinluez 17 hours ago
      I'm in the C# world and can attribute most of my understanding about dates and times to Noda (the .NET version of Joda). Shout out to Jon Skeet for maintaining it.
  • nekevss 1 day 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 :)

  • zvqcMMV6Zcr 1 day ago
    > Safari (Partial Support in Technology Preview)

    Safari confirmed as IE Spiritual successor in 2020+.

    • WorldMaker 1 day 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.

      • supernes 21 hours ago
        The biggest problem with IE from a developer standpoint wasn't the slow feature release cadence, it was that the features it did have worked differently from standards-based browsers. That's very much the position of Safari/WebKit today - code that works across all other engines throws errors in WebKit and often requires substantial changes to resolve.

        Safari is also pretty popular on iPhones, in fact it has a full 100% market share. With browser updates tied to the OS, that means millions of devices have those "temporary" problems baked in forever.

      • nchmy 1 day 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 1 day 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.

          • nchmy 16 hours ago
            As the links I shared showed in tremendous detail, everything you've said is complete nonsense.
            • WorldMaker 14 hours ago
              The only well supported and consistent argument I see in those links is that Safari is bad at PWAs. I agree with that. But (timely rant incoming) I also think everyone is currently bad at PWAs. The current ServiceWorker-based approach is brittle and hard to use because it is too low level and too tightly coupled to what seem to be Chrome-specific concerns. The previous manifest.json approach should have never been disabled in Chrome, it should have at least lived side-by-side and let developers vote by their feet, at least until a reasonably equivalent high-level manifest replacement was built.

              I was just thinking about this this week because I have a webpage I built with offline capabilities and an excuse coming up where many of the webpage's users will be offline for a week but might have use for the webpage, but I can't easily turn it into a PWA because it was built as an MPA and there's no great high level tools for writing an MPA's ServiceWorker because most of the high level libraries are so (overly) focused on SPAs. I wish I could just put a manifest.json or some sort of zip archive users could download and have it share Local Storage.

              I do pin a lot of this on Google engineers. The side effect is Safari is having a hard time implementing these "standards", but the real cause is the "standards" are over-complicated trash that are also hard to develop for. Everyone including the links you sent can see how Apple's App Store moat gives them an incentive to drag their feet on implementing these "standards" and yet no one is giving Google enough gruff for the conflict of interest with Google Play's moats and making over-complicated standards that are hard for anyone to use and harder for anyone else to implement is just another way to drag your feet and keep the whole web platform behind, without looking like you are dragging your feet.

              It would feel different, too, if the fully declarative manifest.json approach hadn't briefly worked (well) in Edge (Spartan) and Firefox before Google derailed that standards train with "Chrome-first" ServiceWorker complications. Always seemed like one of the reasons that Microsoft just gave up on the web platform because they couldn't keep up with Google's machinations (and conflicts of interest) in Chrome.

              • nchmy 13 hours ago
                It is bizarre that you're "pinning" this on the Chromium engineers - who are essentially the only ones moving the web forward.

                The safari feet dragging/obstruction goes far beyond PWAs. The chart on this page is one of many examples showing how consistently far behind Safari is - they've been enormously behind chrome and firefox in coverage of tests for 7+ years. https://wpt.fyi/. And here's an extremely comprehensive article on the topic https://webventures.rejh.nl/blog/2024/history-of-safari-show...

                As for standards, here's another detailed series to learn from https://infrequently.org/series/effective-standards-work/. Once again, you have it all backwards. Saying "no one is giving Google enough gruff for the conflict of interest with Google Play's moats and making over-complicated standards" is not only laughable, but just dumb - Google doesn't and, in fact, can't "make standards". Standards are something that comes about through the painful diplomatic process described in those links.

                Moreover, it is quite clearly an institutional decision to hold back the web, or else they would allow for other browser engines to run on iOS rather than focing them all to be skins on webkit. Again, this is all documented in extreme detail in the articles on that site. If you find it to be still somehow lacking, the author is very open to discussion on bluesky or mastodon (I'd prepare far better though, because what you've said thus far would get eviscerated).

                Also bizarre that you are saying that Google Play is somehow at the root of this supposed scheme to make web standards impossible for others to implement. Android is similarly against the web flourishing, but evidently not nearly as powerful in the greater Google enterprise as iphone/app store is in Apple.

                As for MPA PWAs, there's nothing at all stopping you from serving pages from a service worker. There's plenty of valid and accessible ways to precache all the pages that a user might need while offline. Workbox (from Google!) makes it easy, but its also easy to hand-roll.

                And, Microsoft most definitely has not given up on the web platform - they literally adopted and make contributions to chromium. The author of that site literally works at Microsoft now, coaching both internal and external teams on improving their use of the web, as well as contributing to standards.

                I dont see any point in continuing this discussion, as you haven't shown even the slightest interest in considering how you're living in some bizarro world.

                If you are actually attempting to communicate in good faith, i can't recommend strongly enough that you read that entire site. And, likewise, read and support the work of Open Web Advocacy. https://open-web-advocacy.org/

                • WorldMaker 12 hours ago
                  > It is bizarre that you're "pinning" this on the Chromium engineers - who are essentially the only ones moving the web forward.

                  I'm saying this is exactly the problem. If the perception is that only one browser is "moving forward" and the rest are just chasing that moving target, that's not healthy and it is not a standards process. WHATWG has always been at risk of "regulatory capture" by Google or at least Chromium interests. More so than ever there are standards that seems like WHATWG rubber stamped whatever Chrome decided to do without larger consensus work with Safari and Firefox. That's really dangerous for the web platform. (And W3C lost to WHATWG and seems increasingly irrelevant as a standards body for HTML.)

                  I think we are all very lucky that ECMA hasn't so far shown the same risk and TC-39 (JS) continues to look overall diverse and healthy.

                  > Google doesn't and, in fact, can't "make standards". Standards are something that comes about through the painful diplomatic process described in those links.

                  This is why I put standards in quotes in most of that comment. I do think WHATWG has already signed off on Chrome-first things as "standards" that aren't in the sense of multiple robust implementations and a diverse enough number of stakeholders that aren't just using Chromium-derived codebases. I worry WHATWG is at risk of getting worse in this.

                  > As for MPA PWAs, there's nothing at all stopping you from serving pages from a service worker. There's plenty of valid and accessible ways to precache all the pages that a user might need while offline. Workbox (from Google!) makes it easy, but its also easy to hand-roll.

                  As very personal experience from building PWAs (and failing to build many more of them): Workbox is bloated and awful to work with and is bad enough at SPAs that trying to feed it an MPA makes me want to scream just thinking about it. Hand-rolling a Service Worker remains a nightmare because the API is awful to work with by hand, which is the whole reason Workbox exists. There's something very wrong with the APIs that right now the only answer seems to be "just use Workbox". That's not healthy for the web platform to be so dependent on a single vendor's tool to get over the hump of using a web API. (Even if that tool is open source. CVEs affect open source like everything else.)

                  The last time I was serious about PWA development I broke down in tears and switched to Ionic's Capacitor and Electron because browser wrappers are still too much easier than writing a PWA.

                  I know that isn't just me also anecdotally by the number of Electron apps running on my machine even right now (a bunch) and the number of PWA apps running on my machine (none).

                  Statistically Service Workers and Workbox are massive failures, and it isn't Apple's fault and it is weird to me claiming that it is entirely Apple's fault. If you don't want to blame Google or at least Chromium engineers, that's fine, we don't have to agree on that. But show me the app with a working PWA ServiceWorker that has a good reliable caching strategy, good offline-first support, and people use that offline-first capability regularly and I'll show you a unicorn. The APIs are terrible, the standards should be better. If we don't want to point fingers at why the current APIs and standards are so awful, can we at least find someone to point a finger at who is actively working to make them better? It doesn't seem to be "Just Use Workbox" Chromium. Who is actually trying to move the offline-first web forward towards pragmatic reality and not just "we support it in theory, with this one JS library, but very few are using it in practice and almost none successfully"?

                  > And, Microsoft most definitely has not given up on the web platform - they literally adopted and make contributions to chromium. The author of that site literally works at Microsoft now, coaching both internal and external teams on improving their use of the web, as well as contributing to standards.

                  When Microsoft switched to Chromium they soft laid off a lot of their web platform staff. Chromium Edge's outward development focus seems to be AI and First-Party Coupon Cutting Extensions.

                  Spartan Edge had ideals and seemed to really believe in the PWA as a first class application platform. For a time, I had a bunch of PWAs as daily use applications in Windows 8 and early 10 (not all of which I built myself, either). That era is certainly gone now. WebView2 is making some inroads in reduce the reliance on Electron by certain types of apps, but WebView2 isn't a PWA platform, it is another end run around it/away from it.

                  > I dont see any point in continuing this discussion, as you haven't shown even the slightest interest in considering how you're living in some bizarro world.

                  > If you are actually attempting to communicate in good faith

                  You've strayed close enough to the realm of ad hominem attacks that I'm going to stop here. It doesn't sound like we are going to ever agree, but certainly not because I'm not debating in "good faith" or living in some "bizarro world". It seems rude to me to imply such accusations. Just because I have a different perspective doesn't make me a bad actor nor prove I have some sort of mental health issues. I may have experienced a different world than you have in my career, but there was nothing "bizarro" or worse about it. Different perspectives should be a joy to engage with, not an affront to ridicule. I'm sorry I couldn't find help you find common ground.

                  • nchmy 9 hours ago
                    it would, indeed, be great if there were others contributing to the web. Mozilla should be, but they seem to be run by incompetent grifters. Apple could be, but that would be completely against their interests. So we're left with chromium moving the web forward - that's not their fault and its ludicrous that you keep saying it is.

                    as for service worker, I literally said you dont need workbox. I have done lots of hand-rolled MPA caching. Its dead-simple, so i dont know what complexity you're referring to.

                    As for the fact that there arent many good pwas out there - people dont bother because iphone is a mess. Your arguments would hold water if apple allowed other browser engines and then pwas still languished.

                    Even still, there's all sorts of efforts towards offline/local-first. Its a hard problem to solve. But, again, simple MPA caching is not hard. If its a dynamic backend, then that would be much more difficult

        • tacticus 1 day ago
          > There wouldn't be Chrome-only sites and tools if Safari wasn't holding the web back

          Given the number of chrome-only sites that block firefox and not safari i think there are other issues in front end land

          • WorldMaker 15 hours ago
            I agree. It's also interesting how much that overlaps with "Firefox is an ad blocker" CAPTCHAs/paywalls/ad network complaints.
    • cubefox 1 day ago
      2026 A.D., still no support for native date pickers in mobile Safari.
      • CharlesW 1 day ago
        Safari for iOS got native date pickers in 2012, and desktop Safari got them in 2021.
  • QGQBGdeZREunxLe 1 day ago
    Noticed that converting between certain calendars is not supported. Was that choice intentional?

        const today = Temporal.PlainDate.from("2569-03-11[u-ca=buddhist]"); 
        today.toLocaleString("en", { calendar: "hebrew" });
        > Uncaught RangeError: calendars "buddhist" and "hebrew" aren't compatible
    • rmunn 1 day ago
      Converting between solar-based and lunar-based calendars is fraught with potential for ambiguity. The Buddhist calendar is a solar calendar, while the Hebrew calendar is lunar-based. So converting between dates in the Buddhist calendar and the international-standard (ISO 8601) calendar is typically easy (give or take some subtleties I won't go into for reasons of length). But converting between the Hebrew calendar and the ISO 8601 calendar, or the Buddhist calendar, involves figuring out when the new moon will be — and since the lunar cycle is 29 or 30 days, 12 lunar months add up to 354 days. So the lunar calendars, including the Hebrew calendar, typically add a "leap month" every two or three years in order to track the sidereal year.

      All of which means there are many potential ambiguities in converting between calendars, and the combinatorial explosion possible means they probably only want you to convert between non-ISO8601 calendars and ISO8601. It would be too easy to get corner cases wrong otherwise and not notice, I'm sure. So to convert a date from Buddhist calender to Hebrew calender, you'd probably have to do Buddhist -> ISO8601, then ISO8601 -> Hebrew. (I haven't had time to test that for myself yet, I'll post a correction if that turns out to be wrong).

    • fabon 22 hours ago
      I think this is intentional design. Anyway we can convert `Temporal.PlainDate` to other calendars explicitly (I believe explicitness is good here).

        today.withCalendar('hebrew').toLocaleString("en", { calendar: "hebrew" });
        // "22 Adar 6329"
    • paradox460 1 day ago
      Certainly surprising

      One of my favorite interview questions is asking a candidate to, piece meal, build a calendar. They start with Julian, and then write converters to and from other calendars. Any calendar can be converted to any other, by going through Julian

      I got the idea from the book "calendrical calculations"

  • wpollock 1 day 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!

  • bnb 1 day ago
    Can't wait for it to land in the server-side runtimes, really the last thing preventing me from adopting it wholesale.
    • WorldMaker 1 day 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 1 day ago
      Node 26! Only a matter of time... :)
    • CharlesW 1 day ago
      FWIW, I've been using it server-side via the js-temporal polyfill for some time, no issues.
      • bnb 1 day ago
        ooh I'd not seen that yet, will have to take a look.
  • avandecreme 22 hours ago
    I didn't know about https://docs.rs/temporal_rs/latest/temporal_rs/

    I wonder if it has a chance to replace chrono and jiff in the rust ecosystem.

    • nekevss 12 hours ago
      Yep, temporal_rs is designed with native Rust use in mind, so you should be able to use temporal_rs directly wherever you'd use jiff or chrono.

      That being said, the library is designed to be specification conformant and with EcmaScript implementations in mind. There are some specific API choices made specifically for those clients.

      That being said, we are always looking for feedback regarding the native Rust API. So feel free to try temporal_rs out and provide whatever feedback you'd like :)

  • xp84 1 day ago
    They travelled through time (forward, at 1X) by nine years to do this for us. I appreciate it.
  • matheus-rr 15 hours ago
    The Java parallel is apt. Joda-Time dominated the ecosystem for about 8 years before JSR 310 landed in Java 8 (2014). One thing that helped there was a clear, single release target.

    What I keep thinking about with Temporal is the adoption timeline question isn't really 'is it specced?' anymore, it's 'what minimum runtime version do I need?' Node.js, Deno, Bun all need to ship it stably, and then the practical floor for usage is wherever most prod environments are. The polyfill situation (@js-temporal/polyfill and others) doesn't really collapse until that happens.

    So the speccing is done but I think we're still a couple of LTS cycles away from it being genuinely boring to reach for Temporal.

  • alanning 1 day 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-...

  • the__alchemist 1 day 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)

    • jitl 1 day ago
      I wouldn't be surprised to see the Rust ecosystem eventually move to Temporal's api, given v8 (Chrome) adopted Boa's rust implementation temporal_rs (https://docs.rs/temporal_rs/latest/temporal_rs/), see burntsushi's arguments for the need of a better datetime handling library in Rust (https://github.com/BurntSushi/jiff/blob/master/DESIGN.md#why...). I'm not sure his jiff create will be the one, i think temporal_rs has become the authoritative implementation.
    • apaprocki 1 day ago
      Yes, please try! One of the main motivations for doing all this work is to slim down both the amount of code that has to be delivered and executed by providing everything that's needed by the platform. In addition, you're slimming the potential bug/attack surface as well, which is always nice.
  • tmpfile 1 day ago
    I’d like to have interval types for example

       const D = new Temporal()
       const t = new Interval({minutes:5})
       const v = D.add(t)
  • corentin88 21 hours ago
    Temporal is a good idea, but the API is too complicated for broad adoption:

    - new Date() equivalent in Temporal is `const now = Temporal.Now.zonedDateTimeISO();`.

    - Date.now() equivalent is `Temporal.Now.instant().epochMilliseconds`

    - It’s PascalCase, where JS is mostly snakeCase.

    - nanoseconds per default. who needs that except Bloomberg? It should have been an option

    It’s definitely great all the efforts put in place, but it’s not going to be a replacement to Date which such a complicated design.

    • gjm11 8 hours ago
      Most of that complication is there because times and dates are actually complicated. You can have a nice simple API that doesn't expose the complication only if you're happy for it to encourage false assumptions and wrong behaviour.

      But, still, let's look at your first couple of complaints.

      To make #1 more explicit: If you want the equivalent of "new Date()", then as you observe you need to say something that's longer because it's more specific about what it's giving you. Why can't it just do the obvious simple thing, like Date does?

      To make #2 more explicit: If you want the equivalent of "Date.now()", then as you observe you again need to say something that's longer because it's more specific about what it's giving you. Why can't it just do the obvious simple thing, like Date does?

      Well, because as those two examples show there isn't actually an obvious simple thing. Two operations both of which one might expect to do the obvious simple thing do different things, and if there's some obvious way for someone who doesn't already happen to have the specs of Date memorized to know which one is "new Date()" and which one is "Date.now()", I don't know what it is.

      So, to me, those first two examples look like pretty convincing evidence that Temporal is a better design and one that's less likely to lead non-experts to make serious mistakes.

      ... And then your other two complaints aren't actually about the API being "too complicated" at all! PascalCase isn't more complicated than snakeCase. Nanoseconds aren't more complicated than milliseconds.

      (Also: "zonedDateTimeISO" and "epochMilliseconds" are in fact both snakeCase, and a quick look at the Temporal documentation suggests that this is the norm. Method names are snakeCase, class names are PascalCase. I am not a Javascript expert but isn't that pretty normal?)

      • corentin88 6 hours ago
        Thanks for sharing your thoughts too. I still have the feeling that broad adoption comes from simple things that just work. And the complicated stuff is more optional.
  • KolmogorovComp 16 hours ago
    Doesn't the implementation being in rust for many browser (`temporal_rs`) make it possibly slower than it could be in pure JS? Calendar is not very intensive process, so I would not be surprised if the slowness of boundary passing make it slower.
    • fabon 13 hours ago
      Actually most APIs of JavaScript are implemented in C++ in modern browsers, not in JS. I guess adopting Rust isn't an obstacle for performance.
  • pbowyer 21 hours ago
    If you were creating a new programming language in 2026, which DateTime/Temporal library would you copy and why?
  • kemayo 1 day 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.

    • Griffinsauce 22 hours ago
      An example that is hard to follow defeats the point. It's just showing what pattern is possible and you can imagine the abstraction layers and indirection that would make it happen accidentally.
  • parampathonmon2 18 hours ago
    Nice to see Temporal finally landing after such a long standardization process. The duration and timezone handling should simplify a lot of date math that libraries like moment and date-fns have been covering.
  • redbell 1 day ago
    Oh, for a second, TeMPOraL (https://news.ycombinator.com/user?id=TeMPOraL) came to my mind!
  • SoftTalker 1 day 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.
  • klysm 1 day ago
    Bravo to the designers of this library. It’s well implemented and I’ve been using the poly fill for years now
  • ramon156 19 hours ago
    TIL temporal_rs was a thing. Not to be biased, but I think it's awesome how much Rust is used in the JS ecosystem. I saw Vite using oxc in some parts. Love it!
  • johncomposed 1 day 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.
  • thinkindie 20 hours ago
    coming from PHP, it's incredible how many times I've been bitten by glitches with managing time with JS clientside.
  • philipallstar 1 day 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 1 day 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 12 hours ago
        I believe V8 / chrome bundles IANA time zones into the zoneinfo64 resource bundle. I'm not actually sure they hit the system tzdb at all.
    • nekevss 1 day 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.
    • Anonyneko 15 hours ago
      This is why I'm sticking with moment.js for now. I don't like that it's not immutable, but I value bundling timezone data into the app too much. Our customers are likely to use outdated browsers at their workplaces (we even had to maintain IE11 compatibility a bit too long for our liking).
    • apaprocki 1 day ago
      Depending on the situation, the data lives either within the browser or within the OS. Chrome releases ship versions of tzdata that correspond to the version of tzdata shipped with the ICU it uses, and they do backport updates to prior Chrome releases within a certain window. Apple has a sideband way of deploying tzdata to all devices that doesn't appear via the normal Software Update mechanism. So it all depends on which particular OS/browser combo you're interested in and the decisions those owners made.
  • Banou 1 day ago
    Temporal is nice but I've tried using it and had terrible performances. Hope the implementations get better in the future.
  • gangnamdotori 15 hours ago
    Temporal API is fascinating. Time handling has always been painful in programming languages. Curious how widely this will get adopted in production systems.
  • tracker1 1 day ago
    Looking at the caniuse results... f*king Safari (and Opera)...

    https://caniuse.com/temporal

  • normie3000 1 day ago
    No mention of JodaTime?
  • samwho 1 day ago
    Thanks for linking to my silly little quiz in the article! :)
  • stevefan1999 1 day ago
    I thought this Temporal is about the durable execution Temporal, well it is about time...
  • kemitchell 1 day ago
    > The first proposal I worked on was Promise.allSettled, which was fulfilling.

    Har har.

  • sharktheone 1 day ago
    Very happy for it finally being there!
  • darepublic 1 day 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
    • ibejoeb 1 day 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.
    • WorldMaker 1 day 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.

    • tshaddox 1 day ago
      That generally works for timestamps (Temporal Instant). But it doesn’t work for representing calendar dates with no time information (Temporal PlainDate) unless you add an additional strict convention like “calendar dates are always represented as midnight UTC”).
    • andrewl-hn 1 day 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 1 day 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 1 day 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 1 day 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 1 day 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.

    • KingMob 22 hours ago
      "Just use UTC" is another, albeit more subtle, falsehood programmers believe about date/time.

      It's fine for distributed logging and computer-only usage, but fails in obscure ways once humans, time zones, travel, laws, and/or daylight saving time get involved.

      If you're scheduling events for humans, and can't immediately list the reasons your app is an exception to the above, store the time zone to be safe. You probably don't have big data, and nobody will notice the minuscule overhead.

    • NooneAtAll3 1 day ago
      why UTC and not epoch then?
      • SoftTalker 1 day 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.

    • lpa22 1 day ago
      Same here, this is the way
  • bpiroman 1 day ago
    I wish JavaScript held onto the name Mocha :)
  • FireBeyond 1 day ago
    > Higher-precision timestamps (nanoseconds, at a minimum)

    I get HFT, but I have a hard time comprehending a need for a Bloomberg Terminal to be talking in picoseconds, as in fractions of a billionth of a second.

  • jon_kuperman 1 day ago
    What a journey!
  • ChrisArchitect 1 day ago
    Aside: Bloomberg JS blog? ok.
    • robpalmer 1 day 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 1 day 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 1 day 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

  • hungryhobbit 1 day 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();
    • tshaddox 1 day ago
      That’s uglier because, if you were previously doing new Date(), you almost certainly don’t want a zonedDateTime. You almost certainly want an Instant.
    • rmunn 1 day ago
      I'd argue that `new Date()` returning the current time is a design mistake, and it should at least have been something like `DateTime.now()`. (Especially because it's called a date but it actually returns a timestamp: the footgun potential is large). C#'s date API isn't the best design (otherwise [NodaTime](https://www.nodatime.org/) wouldn't have been necessary) but it at least got some things right: you don't get the current time by doing `new DateTime()`, you get it by referencing `DateTime.UtcNow` for UTC (almost always what you want), or `DateTime.Now` for local time (which is sometimes what you want, but you should always stop and think about whether you really want UTC).

      And even with C#'s date API, I've seen errors. For example, a library that formatted datetime strings by merely writing them out and adding a "Z" to the end, assuming that they would always be receiving UTC datetimes — and elsewhere in the code, someone passing `DateTime.Now` to that library. (I'm guessing the dev who wrote that was in the UK and wrote it during winter time, otherwise he would have noticed that the timestamps were coming out wrong. If he was in the US they'd be 4-7 or 5-8 hours wrong depending on whether DST was in effect. But in the UK during winter, local time equals UTC and you might not notice that mistake).

      This is another reason why Temporal's API making clear distinctions between the different types, and requiring you to call conversion functions to switch between them, is a good idea. That C# mistake would have been harder (not impossible, people can always misunderstand an API, but harder) if the library had been using Nodatime. And Temporal is based on the same design principles (not identical APIs, just simmilar principles) as Nodatime.

    • evolve2k 1 day 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.

    • sheept 1 day ago
      I think that it's nice it's explicit that the method returns the current instant, rather than some other zero value.

      There's also other methods that return other types, like

          const now = Temporal.Now.instant()
      
      which isn't as bad.

      One could argue that the ugliness of the API intentionally reveals the ugliness of datetime. It forces you to really think about what you mean when you want "the current date time," which I think is one of the goals of the API.

      • Bratmon 1 day ago
        What would have been wrong with Temporal.now() returning a sensible value?
        • ejplatzer 1 day ago
          What counts as a sensible value? The whole point of the library is to be explicitly about what kind of date/time data you're working with, because different kinds of data have to be handled in very different ways.
          • Bratmon 12 hours ago
            If they at least had a Temporal.nowlocal() and a Temporal.nowUTC() that returned a ZonedDateTime set to the local and UTC timezones respectively, that would be 95% of what developers need in practice.
    • tmpfile 1 day ago
      Or const now = new Temporal();
    • greatgib 20 hours ago
      I also find it super more complicated and messy than what you can find in another language without proper justification.

      Like the Temporal.Instant with the only difference that is now but in nanosecond. Would have been better to be Now with a suffix to indicate that it is more precise. Or even better, it is just the function you use or parameter that give the precision.

      And why Now as the name space? I would expect the opposite, like python, you have something like Temporal.Date, and from there you get a date of now or a specific time, with or without timezone info, ...

    • sourcegrift 1 day 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.
      • themafia 1 day ago
        I'm a programmer. I'm a human. Perhaps we should also allow for some "human theory" inside our understanding.
      • Bratmon 1 day 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!

  • virgil_disgr4ce 1 day ago
    Pretty big fan of Temporal. Been using the polyfill for a while. Very nice to use a modern, extremely well thought-through API!
  • NooneAtAll3 1 day ago
    so Temporal is copying cpp's std::chrono?
    • andrewl-hn 1 day ago
      More like a copy of Java’s JSR310, which in turn took many years to get right.
  • ventuss_ovo 1 day ago
    interesting point about immutability
  • ChrisArchitect 1 day ago
    A good article and discussion from January:

    Date is out, Temporal is in

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

  • nehalem 21 hours ago
    And yet another modernisation of the web platform sabotaged by Apple and their misguided (malicious?) refusal to update their devices continually.

    https://caniuse.com/temporal

    It will take years until this can be widely used as intended.

    • halapro 18 hours ago
      The spec hasn't even reached stage 4 yet. Chrome only added support 58 days ago. Safari already added support in their alphas.
      • nehalem 9 hours ago
        Sure and that’s nice going forward. Yet unlike with Chrome, older devices won’t be updated making this a nice add-on at best.
      • nekevss 12 hours ago
        The specification reached stage 4 just yesterday. That was the motive behind the blog post :)
  • patchnull 1 day ago
    [flagged]
    • Waterluvian 1 day 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 1 day 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 1 day 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 1 day 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 1 day 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 1 day ago
            Just call "Object.freeze()" before "return" in your function.
            • cdmckay 1 day ago
              That only goes one level deep so it’s not much of a guarantee
      • vimwizard 1 day ago
        Rust ownership model ("stacked borrows" I believe it's called) is basically this
        • kibwen 1 day 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 day 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.
            • kibwen 1 day ago
              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.

        • NooneAtAll3 1 day ago
          I think it's the other way around - he's projecting rust as what he wants
        • LoganDark 1 day ago
      • magnio 1 day 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 1 day 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 1 day ago
          > convention

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

          • goatlover 1 day 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 1 day 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 1 day 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 1 day 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.

                  • xp84 1 day ago
                    Yeah, in my testing freeze mutates the object itself to a permanent frozen state.
      • Xenoamorphous 1 day 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.

      • darick 1 day ago
        This is possible with the asserts x is y pattern no?

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

        • Waterluvian 1 day 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 1 day ago
            Hmm, I see, yes it's quite limited.
      • z3t4 1 day 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.
    • homebrewer 1 day 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 1 day ago
        I hear you, but this also affects the good discussion below it.
    • OptionOfT 1 day 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 1 day 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 1 day 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 1 day 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 1 day ago
      Immutability is underrated in general. It's a sore point every time I have to handle non-clojure code.
      • recursive 1 day 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 1 day 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 1 day 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 1 day 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 1 day 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 1 day 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 1 day 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 1 day 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 1 day 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 1 day 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 1 day 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...

        • Dragory 1 day ago
          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

          • WorldMaker 1 day ago
            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.)

      • kandros 1 day 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 1 day 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 1 day ago
      They seem to have taken it from Joda time that revolutionized time in java 10+ years ago. Sadly no mention of Joda.
      • tadfisher 1 day 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 1 day ago
      I think that actually may be the MOST appreciated design decision in Temporal ;) either way, I'm also a big fan
    • refulgentis 1 day ago
      Flagged because account is bot operated (posted again 2h40m later with same general comment)
  • shevy-java 23 hours ago
    Good. Now someone has to fix JavaScript.
  • patchnull 1 day ago
    [flagged]
    • sharifhsn 1 day ago
      Your bot messed up and posted twice in the same thread.
  • sriramgonella 1 day ago
    [flagged]
  • newzino 1 day ago
    [flagged]
  • patchnull 1 day ago
    [dead]
  • aplomb1026 1 day ago
    [flagged]
  • eggsandbeer 1 day ago
    [dead]
  • ilovesamaltman 1 day ago
    [flagged]
  • julius_eth_dev 1 day ago
    [flagged]
    • cityofdelusion 1 day 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.

      • wesselbindt 1 day ago
        > Assuming this isn’t an LLM bot, I don’t see how you ship that bug multiple times

        I don't know about the guy you're replying to, but I've made many mistakes in my coding life, and some of them more than once. The Date API is written in a way to obfuscate the real complexities of date and time management, so I find it quite easy to imagine someone stepping in the same footgun more than once.

        EDIT: oh ew, grandparent comment is a bot. How did you recognize it?

      • SchemaLoad 1 day ago
        They do seem to be an LLM bot from comment history
      • tshaddox 1 day ago
        Good luck making sure no one ever uses a “yyyy-mm-dd” string to represent a calendar date in a JSON API, then passes the value to the Date constructor, then formats that Date in a browser. It’s an extremely easy mistake to make without very strict conventions around how calendar dates and timestamps are represented across the entire stack.
        • p1necone 1 day ago
          This is the most common way this happens in my experience - people naively assume that by giving just a date and not a time surely it wont do timezone conversion, but it does (and even worse that behaviour is not at all consistent between different languages/systems). Oh and fun fact JS parses 'YYYY/MM/DD' (slashes instead of dashes) differently from the dashed format as well...

          The 'safe' way that I try to make everyone use for 'wall clock'/'business' dates is 'YYYY-MM-DDT00:00:00' (without the Z) - this unambiguously parses as 'this date in the current timezone' in basically every languages Date type and it's ISO 8601 compliant. However it's still a pain in the ass to keep straight when serializing as the 'default' output is usually a timezone converted UTC string (Z at the end).

      • p1necone 1 day ago
        You clearly haven't worked on codebases with other developers
  • patchnull 1 day ago
    [flagged]