JavaScript's Date Object Has Been Broken for 30 Years — Temporal Is the Nine-Year Fix That Finally Ships

JavaScript's Date Object Has Been Broken for 30 Years — Temporal Is the Nine-Year Fix That Finally Ships

Every JavaScript developer has a Date horror story. Mine happened at 2:47 AM on a Sunday in November 2019, when I discovered that our scheduling app was showing users in Australia their Monday appointments on Sunday. Not because of a logic error. Because JavaScript's Date object treats months as zero-indexed (January is 0, December is 11) but days as one-indexed (the 1st is 1), and somewhere in our timezone conversion code, this inconsistency had created a bug that only manifested during daylight saving transitions in the Southern Hemisphere.

I fixed it with moment.js and two cups of terrible gas station coffee. But I never forgot the feeling of staring at my screen thinking: why is this so hard?

Turns out, a group of engineers at Bloomberg, TC39, and Igalia had been asking the same question — and actually doing something about it. For nine years.

JavaScript code on developer screen

Photo by Markus Winkler via Pexels

The Problem Everyone Knows But Nobody Fixed (Until Now)

JavaScript's Date object was born in 1995, during Brendan Eich's legendary 10-day sprint to create the language. Under pressure to make JavaScript look like Java, the team made a pragmatic decision: port Java's Date implementation directly into JavaScript.

This made sense in 1995. Java was the "big brother" language, and consistency mattered more than elegance. As Eich later explained, changing the API would have created "confusion and bugs" and Sun Microsystems "would have objected too."

The irony? Java deprecated its own Date class in 1997 and replaced it with Calendar. Then replaced Calendar with java.time in 2014. JavaScript's Date, meanwhile, has remained essentially unchanged for 30 years. The web grew up. Date didn't.

My colleague Rachel, who builds financial dashboards for a living, summed up the developer experience perfectly: "Working with Date is like using a flip phone that's also on fire."

Why Date Is Actually Broken (Not Just Annoying)

If you've never had to deal with JavaScript Date in a serious application, here's a taste of what makes developers lose sleep:

Mutability. Date objects mutate in place. Call setMonth() on a Date and you've just changed the original object. Every function that touches that Date might have silently modified it. In a language that's increasingly embracing immutability (const, Object.freeze, React's state model), Date is a relic from a different philosophy.

Zero-indexed months. new Date(2026, 2, 12) creates March 12, not February 12. January is 0. This has caused more bugs than I care to count, and every single one of them made the developer question their career choices.

No timezone support. Date stores everything as UTC milliseconds internally but displays in the user's local timezone. Want to work with a specific timezone? You can't. Not natively. You need a library. For something as fundamental as "what time is it in Tokyo?", the language has no answer.

No calendar support. JavaScript assumes the Gregorian calendar. If your app serves users in Ethiopia (Ethiopian calendar), Saudi Arabia (Islamic calendar), or Japan (Japanese Imperial calendar), Date has nothing for you.

My friend Tom, who maintains a booking system used across 14 countries, keeps a sticky note on his monitor that reads: "Date is not your friend. Date has never been your friend."

Enter Temporal: Nine Years in the Making

The Temporal proposal first appeared as a Stage 1 TC39 proposal in 2017. For context, TC39 is the committee that governs JavaScript's evolution — getting something through TC39 requires consensus from browser vendors (Google, Apple, Mozilla), major tech companies, and the broader community.

Jason Williams, a senior software engineer at Bloomberg who helped champion the proposal, published a detailed account this week of the nine-year journey. The post hit Hacker News with over 600 upvotes, and the comments section reads like a support group for Date trauma survivors.

Here's what Temporal brings to the table:

Immutability. Every Temporal object is immutable. Operations return new objects instead of mutating existing ones. If you've worked with modern JavaScript patterns, this is how everything should have worked from the start.

Proper types. Instead of one monolithic Date object, Temporal gives you Temporal.PlainDate (just a date, no time), Temporal.PlainTime (just a time, no date), Temporal.ZonedDateTime (date + time + timezone), Temporal.Duration (a span of time), and several others. Each type does exactly what its name suggests. Revolutionary concept, I know.

First-class timezone support. Temporal.ZonedDateTime handles timezone conversions, daylight saving transitions, and UTC offsets correctly. That bug I spent my Sunday night fixing in 2019? It literally cannot happen with Temporal.

Calendar support. Temporal supports non-Gregorian calendars natively. Your app can handle Islamic dates, Hebrew dates, or Japanese Imperial dates without a third-party library.

Why Did It Take Nine Years?

This is the part that fascinates me. Temporal isn't a small proposal — it's a complete date/time library being added to a language that runs in every browser on earth. Getting it right matters because once it ships, you can't take it back.

According to Williams' post, the journey involved:

API redesign after API redesign. The Temporal API went through multiple significant revisions as feedback came in from implementers and users. The committee had to balance completeness with simplicity — too many types and developers won't use it, too few and it doesn't solve the problem.

Browser implementation challenges. Each browser engine (V8 for Chrome, SpiderMonkey for Firefox, JavaScriptCore for Safari) had to implement Temporal independently. Bloomberg, Igalia, and the browser teams collaborated closely, but implementing a date/time library that handles every edge case across every timezone and calendar system is genuinely hard computer science.

Polyfill development. The TC39 team developed and maintained a polyfill so developers could start testing Temporal before browser support landed. This created a feedback loop that caught issues early but also meant maintaining two implementations simultaneously.

Political consensus. TC39 operates by consensus, meaning every major stakeholder has to agree. One objection from any browser vendor could have blocked the entire proposal. Navigating that political landscape for nearly a decade is an achievement in itself.

Sandra, who works on developer tooling at a major tech company, had a telling reaction: "The fact that it took nine years tells you either the problem is really hard or the process is really broken. Probably both."

What This Means for Your Projects

If you're already using moment.js, date-fns, Luxon, or Day.js — first of all, I understand you. Second, Temporal doesn't mean you need to rip out your existing code tomorrow. But here's the roadmap:

For new projects: Use the Temporal polyfill now. Start building with the new API. When browser support is universal, you'll drop the polyfill and everything will "just work."

For existing projects: No rush, but start planning the migration. The date libraries you depend on will likely add Temporal compatibility layers, making the transition gradual rather than a big bang.

For library authors: This is a bigger deal. If you maintain a date-related library, Temporal might make your library unnecessary — which is actually the point. The ecosystem consolidating around a standard is healthier for everyone.

Tom removed his sticky note, by the way. He replaced it with a new one: "Temporal is coming. There is hope."

(I'm keeping my moment.js dependency for at least another six months, though. Trust issues don't heal overnight.)

Found this helpful?

Subscribe to our newsletter for more in-depth reviews and comparisons delivered to your inbox.