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....
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
| Library | Size | API style | Timezone | Mutability |
|---|---|---|---|---|
| Moment.js | 72KB | Fluent/mutable | moment-timezone | Mutable |
| date-fns | ~13KB (used) | Function-based | date-fns-tz | Immutable |
| Day.js | 2KB | Moment-compatible | plugin | Immutable |
| Luxon | 23KB | OOP/fluent | built-in | Immutable |
| Temporal | N/A (native) | OOP/fluent | built-in | Immutable |
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 tools
- Timestamp Converter — convert timestamps online
- JSON Formatter — inspect API date fields
- URL Encoder — encode datetime strings in URLs
Related posts
- Unix Timestamps and Timezones: What Can Go Wrong — Unix timestamps are always UTC — but displaying, parsing, and storing them is wh…
- Date to Unix Timestamp — Convert Any Date to Unix Time — Converting a date to a Unix timestamp gives you the seconds since January 1, 197…
- Epoch Time Explained — What Is Unix Epoch and Why Does It Start January 1, 1970? — Unix epoch time counts seconds from January 1, 1970 00:00:00 UTC. Learn why 1970…
- ISO 8601 Date Format — The Standard for Dates in APIs and Databases — ISO 8601 is the international standard for representing dates and times. Learn t…
- JavaScript Date Formatting — Intl.DateTimeFormat, date-fns, and Custom Formats — Format dates in JavaScript using the built-in Intl.DateTimeFormat API, date-fns …
Related tool
Convert Unix timestamps, epoch seconds/milliseconds, and ISO 8601 dates.
Written by Mian Ali Khalid. Part of the Dev Productivity pillar.