Back to blog

JavaScript Temporal API: The End of Date and Moment.js Is Near

Hello HaWkers, after years of development, the Temporal API is finally arriving in major browsers. This new native API promises to solve all the historical problems of JavaScript's Date object.

Let's explore how to use the Temporal API and prepare your projects for this change.

Why We Need the Temporal API

Current Date Problems

JavaScript's Date object was created in 10 days in 1995, copied from Java, and was never fixed.

Classic Date problems:

// Problem 1: Months start at 0
const date = new Date(2026, 0, 20); // January, not February
console.log(date.getMonth()); // 0, not 1

// Problem 2: 2-digit years
const y2k = new Date(99, 0, 1);
console.log(y2k.getFullYear()); // 1999, not 99 or 2099

// Problem 3: Mutability
const original = new Date(2026, 0, 20);
const modified = original;
modified.setMonth(5);
console.log(original.getMonth()); // 5 - original was changed!

// Problem 4: Inconsistent parsing
new Date('2026-01-20'); // UTC
new Date('2026/01/20'); // Local
new Date('01-20-2026'); // Invalid in some browsers

// Problem 5: No timezone support
// No native way to work with time zones

// Problem 6: No duration support
// No way to represent "2 hours and 30 minutes"

What Temporal Solves

The Temporal API was designed to fix all these problems:

Temporal principles:

  1. Immutability: All objects are immutable
  2. Clarity: Explicit APIs without ambiguity
  3. Timezones: Complete timezone support
  4. Precision: Nanosecond precision
  5. Separate types: Different types for different needs

Main Temporal Types

Type Overview

Temporal introduces several specialized types:

// Temporal.Instant - exact moment in time (UTC)
const instant = Temporal.Instant.from('2026-01-20T15:30:00Z');

// Temporal.ZonedDateTime - date/time with timezone
const zonedDateTime = Temporal.ZonedDateTime.from({
  year: 2026,
  month: 1,
  day: 20,
  hour: 15,
  minute: 30,
  timeZone: 'America/New_York'
});

// Temporal.PlainDateTime - date/time without timezone
const plainDateTime = Temporal.PlainDateTime.from({
  year: 2026,
  month: 1,
  day: 20,
  hour: 15,
  minute: 30
});

// Temporal.PlainDate - date only
const plainDate = Temporal.PlainDate.from({
  year: 2026,
  month: 1,
  day: 20
});

// Temporal.PlainTime - time only
const plainTime = Temporal.PlainTime.from({
  hour: 15,
  minute: 30,
  second: 0
});

// Temporal.Duration - time duration
const duration = Temporal.Duration.from({
  hours: 2,
  minutes: 30
});

When to Use Each Type

Type Use Case Example
Instant Event timestamps Logs, auditing
ZonedDateTime Local events Meetings, flights
PlainDateTime Timezone-free events Templates
PlainDate Dates only Birthdays, holidays
PlainTime Times only Business hours
Duration Intervals Execution time

Using Temporal in Practice

Creating Dates

// From ISO string
const date1 = Temporal.PlainDate.from('2026-01-20');

// From object
const date2 = Temporal.PlainDate.from({
  year: 2026,
  month: 1,
  day: 20
});

// Current date
const today = Temporal.Now.plainDateISO();
console.log(today.toString()); // "2026-01-20"

// Current DateTime with timezone
const now = Temporal.Now.zonedDateTimeISO('America/New_York');

Manipulating Dates

const date = Temporal.PlainDate.from('2026-01-20');

// Add time (returns new instance)
const nextWeek = date.add({ days: 7 });
console.log(nextWeek.toString()); // "2026-01-27"

// Subtract time
const lastMonth = date.subtract({ months: 1 });
console.log(lastMonth.toString()); // "2025-12-20"

// Modify specific fields
const newYear = date.with({ month: 12, day: 31 });
console.log(newYear.toString()); // "2026-12-31"

// Original remains unchanged (immutability)
console.log(date.toString()); // "2026-01-20"

Comparing Dates

const date1 = Temporal.PlainDate.from('2026-01-20');
const date2 = Temporal.PlainDate.from('2026-02-15');

// Comparison
console.log(Temporal.PlainDate.compare(date1, date2)); // -1

// Equality
console.log(date1.equals(date2)); // false

// Difference between dates
const diff = date1.until(date2);
console.log(diff.days); // 26

Working with Timezones

ZonedDateTime

// Create datetime with timezone
const meeting = Temporal.ZonedDateTime.from({
  year: 2026,
  month: 1,
  day: 20,
  hour: 15,
  minute: 0,
  timeZone: 'America/New_York'
});

// Convert to another timezone
const meetingInTokyo = meeting.withTimeZone('Asia/Tokyo');

// The moment is the same, only representation changes
console.log(meeting.toInstant().equals(meetingInTokyo.toInstant())); // true

Handling Daylight Saving Time

Temporal correctly handles DST transitions.

Migrating from Existing Libraries

Replacing Moment.js

// Moment.js (old)
import moment from 'moment';
const m = moment('2026-01-20');
const added = m.add(7, 'days');

// Temporal (new)
const t = Temporal.PlainDate.from('2026-01-20');
const addedT = t.add({ days: 7 });

// Bundle size comparison
// Moment.js: ~70KB minified
// Temporal: 0KB (native browser)

Equivalence Table

Operation Moment/date-fns Temporal
Create date moment() Temporal.Now.plainDateISO()
Add days .add(7, 'days') .add({ days: 7 })
Subtract months .subtract(1, 'month') .subtract({ months: 1 })
Format .format('DD/MM/YYYY') Intl.DateTimeFormat
Difference differenceInDays() .until().days
Compare .isBefore() Temporal.PlainDate.compare()
Timezone moment.tz() Temporal.ZonedDateTime

Current Support and Polyfills

Implementation Status

As of January 2026:

Browser Status
Chrome Experimental flag
Firefox In development
Safari In development
Node.js --harmony-temporal flag
Deno Supported
Bun Supported

Using Polyfill

While native support arrives, use the official polyfill:

npm install @js-temporal/polyfill
import { Temporal } from '@js-temporal/polyfill';

const now = Temporal.Now.plainDateISO();
console.log(now.toString());

Conclusion

The Temporal API represents the biggest evolution in JavaScript date handling since its creation. We finally have a native solution that solves historical Date problems.

Key points:

  1. Immutable objects prevent common bugs
  2. Separate types for different needs
  3. Complete timezone support
  4. Nanosecond precision
  5. Clear and unambiguous API

Recommendations:

  • Start using the polyfill in new projects
  • Plan gradual migration from Moment.js/date-fns
  • Learn the different types and when to use each
  • Follow browser implementation progress

The transition will take time, but it's worth getting familiar with the Temporal API now.

Let's go!

Comments (0)

This article has no comments yet 😢. Be the first! 🚀🦅

Add comments