X Xerobit

Moment.js Alternatives — date-fns, Day.js, Luxon, and Temporal

Moment.js is deprecated. Compare modern alternatives: date-fns (tree-shakable functions), Day.js (2KB Moment drop-in), Luxon (immutable API), and the TC39 Temporal proposal....

Mian Ali Khalid · · 5 min read
Use the tool
Timestamp Converter
Convert Unix timestamps, epoch seconds/milliseconds, and ISO 8601 dates.
Open Timestamp Converter →

Moment.js is in legacy maintenance mode as of 2020. The team themselves recommend switching. Here’s a comparison of the best modern alternatives and migration patterns.

Convert timestamps between formats with the Timestamp Converter.

Why leave Moment.js?

  • Size: 72KB minified (294KB with all locales)
  • Mutable: moment.add() modifies the original object — a common source of bugs
  • No tree-shaking: Bundlers cannot eliminate unused code
  • Deprecated: No new features, only security patches

The alternatives compared

LibrarySizeAPI styleTimezoneMutability
Moment.js72KBFluent/mutablemoment-timezoneMutable
date-fns~13KB (used)Function-baseddate-fns-tzImmutable
Day.js2KBMoment-compatiblepluginImmutable
Luxon23KBOOP/fluentbuilt-inImmutable
TemporalN/A (native)OOP/fluentbuilt-inImmutable

date-fns — best for tree-shaking

npm install date-fns date-fns-tz
import { format, addDays, parseISO, differenceInDays, isAfter } from 'date-fns';
import { toZonedTime, formatInTimeZone } from 'date-fns-tz';

// Format:
format(new Date(), 'MMMM d, yyyy');        // "May 12, 2026"
format(new Date(), 'yyyy-MM-dd HH:mm:ss'); // "2026-05-12 14:30:00"

// Parse:
parseISO('2026-05-12T14:30:00Z');          // Date object

// Arithmetic:
addDays(new Date(), 7);                     // 7 days from now
differenceInDays(new Date('2026-06-01'), new Date('2026-05-12')); // 20

// Comparison:
isAfter(new Date('2026-06-01'), new Date()); // true

// Timezone:
formatInTimeZone(new Date(), 'America/New_York', 'yyyy-MM-dd HH:mm zzz');
// "2026-05-12 10:30 EDT"

Best for: Projects using bundlers (Vite, webpack) where tree-shaking matters.

Day.js — easiest Moment.js migration

npm install dayjs
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';
import relativeTime from 'dayjs/plugin/relativeTime';

dayjs.extend(utc);
dayjs.extend(timezone);
dayjs.extend(relativeTime);

// Almost identical to Moment.js API:
dayjs().format('MMMM D, YYYY');           // "May 12, 2026"
dayjs('2026-05-12').add(7, 'day');        // 7 days later
dayjs('2026-05-12').subtract(1, 'month'); // April 12

// Timezone:
dayjs.utc('2026-05-12T14:30:00Z').tz('America/New_York').format();
// "2026-05-12T10:30:00-04:00"

// Relative:
dayjs('2025-12-01').fromNow();            // "5 months ago"

Best for: Moment.js migration with minimal code changes.

Luxon — best built-in timezone support

npm install luxon
import { DateTime, Duration, Interval } from 'luxon';

// Create:
const dt = DateTime.now();                 // Current time, local zone
const utc = DateTime.utc();               // Current time, UTC
const from = DateTime.fromISO('2026-05-12T14:30:00Z');
const fromTS = DateTime.fromMillis(1747066800000);

// Format:
dt.toISO();                               // "2026-05-12T14:30:00.000+00:00"
dt.toLocaleString(DateTime.DATE_FULL);    // "May 12, 2026"
dt.toFormat('yyyy-MM-dd HH:mm:ss');       // "2026-05-12 14:30:00"

// Timezone:
const ny = from.setZone('America/New_York');
ny.toFormat('HH:mm zzz');                 // "10:30 EDT"

// Arithmetic:
dt.plus({ days: 7, hours: 2 });
dt.minus({ months: 1 });

// Duration:
const dur = Duration.fromObject({ hours: 2, minutes: 30 });
dur.toISO();                              // "PT2H30M"

// Diff:
const diff = DateTime.fromISO('2026-06-01').diff(DateTime.now(), 'days');
diff.days;                                // ~20

Best for: Complex timezone handling, calendar applications, scheduling systems.

Temporal (TC39 proposal — future native)

The Temporal API is in Stage 3 (as of 2026, available via polyfill):

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

// Unambiguous date types:
const date = Temporal.PlainDate.from('2026-05-12');
const time = Temporal.PlainTime.from('14:30:00');
const dt = Temporal.PlainDateTime.from('2026-05-12T14:30:00');
const zoned = Temporal.ZonedDateTime.from('2026-05-12T14:30:00[America/New_York]');
const instant = Temporal.Now.instant();  // UTC timestamp

// Format:
date.toString();                          // "2026-05-12"
zoned.toLocaleString('en-US', { dateStyle: 'full' }); // "Tuesday, May 12, 2026"

// Arithmetic (returns new object, never mutates):
date.add({ days: 7 });                   // 2026-05-19

// Comparison:
Temporal.PlainDate.compare(date, date.add({ days: 1 })); // -1

Best for: New projects that want to future-proof with the upcoming native API.

Migration cheat sheet

// Moment.js → date-fns:
moment().format('YYYY-MM-DD')            → format(new Date(), 'yyyy-MM-dd')
moment(str).add(7, 'days')              → addDays(parseISO(str), 7)
moment(a).isBefore(b)                   → isBefore(parseISO(a), parseISO(b))
moment.duration(2, 'hours').asSeconds() → 7200

// Moment.js → Day.js (mostly same API):
moment().format(...)       → dayjs().format(...)
moment().add(...)          → dayjs().add(...)
moment().tz(zone).format() → dayjs().tz(zone).format()

Related posts

Related tool

Timestamp Converter

Convert Unix timestamps, epoch seconds/milliseconds, and ISO 8601 dates.

Written by Mian Ali Khalid. Part of the Dev Productivity pillar.