Working with JavaScript Date has always been a struggle. Libraries like moment (18kB gzipped), day.js (3kB gzipped) and luxon (23kB gzipped) filled the gap by giving a more developer friendly API, but they take up more network bandwidth, add dependencies and increase build times. That’s where Temporal comes in.

Browsers have been working hard to implement Temporal with the TC39 Stage 3 draft specification so we hope to see it fairly soon. In the meantime we can test it out with Deno 1.40.0 under the unstable flag --unstable-temporal or using the polyfill for npm.

Temporal fixes a lot of the problems that Date had, here’s a few examples and tips to get you started using Temporal.

Notable changes

  • Values follow ISO 8601 standards

    // Months start at 1 instead of 0
    (new Date("2024-01-01")).getMonth(); // returns 0 (January)
    Temporal.PlainDate.from("2024-01-01").month // returns 1 (January)
    
    // Weekdays start at 1 instead of 0
    (new Date("2024-01-01")).getDay(); // returns 0 (Monday)
    Temporal.PlainDate.from("2024-01-01").dayOfWeek; // returns 1 (Monday)
    
  • Dates can be created independent of timezone (no need for .split("T")[0])

    new Date(); // 2024-01-01T07:00:00.000Z (I'm in Mountain Standard Time)
    Temporal.Now.instant(); // similar to `new Date()`
    Temporal.Now.plainDateISO(); // 2024-01-01
    Temporal.Now.plainDate(calendar); // let's you specify a calendar
    
  • Time can exist without a date Temporal.PlainTime

  • Time span has a dedicated object Temporal.Duration, with built in calculations and ability to cast the unit by rounding to a unit of choice e.g. years, days, seconds, nanoseconds.

  • Supports daylight savings time arithmetic (those bugs are the worst)

  • Powerful options for parsing to machine readable strings with toString(), and human readable strings .toLocaleString()

    Temporal.Now.instant().toLocaleString("en-US", {
      calendar: "gregory",
      era: "short",
      year: "numeric",
      month: "long",
      day: "numeric",
    });
    
  • Immutable values, so mutations will return new instances

    // adding time (you can go back in time with negatives or `.subtract()`)
    const now = Temporal.Now.zonedDateTimeISO();
    const newInstant = now.add({ years: 20, months: 4, nanoseconds: 500 });
    
    // or, overwriting the time
    const old = Temporal.Now.plainDateTimeISO();
    const changed = old.with({ minutes: 0, second: 30 });