mrkeyoor.com_
Wed 05 Aug 05:03 UTC
npmUtilsupdated 05 Aug 2026

dayjs

Day.js is a tiny date library for parsing, formatting, comparing, and doing arithmetic on dates. It deliberately clones the Moment.js API (chainable calls like dayjs().add(1, 'day').format('YYYY-MM-DD')) but ships as an immutable core of about 3 KB gzipped with zero dependencies. Everything beyond the basics (timezones, relative time, strict parsing, week numbers) lives in optional plugins you load one at a time. It is the default answer for teams migrating off Moment without rewriting call sites.

Verdict

Still the best pick for Moment migrations and for apps that just need small, familiar date handling. If timezones are central to your product, or you are starting fresh in 2026, look at Luxon or the Temporal polyfill instead.

API stability5/5Has stayed on 1.x since 2018 with no breaking rewrites; the Moment-compatible API is effectively frozen, so upgrades are low risk.
Docs4/5day.js.org covers the full API and every plugin with examples, but plugin discovery is scattered and some behaviors (fallback Date parsing, timezone quirks) are underdocumented.
Maintenance3/5Repo still gets pushes (last June 2026) and releases, but cadence is slow for its usage level and 1,292 issues sit open, including known timezone bugs.
Ecosystem4/565.9M weekly downloads, 48.6K stars, a large official plugin list, and 100+ locales; smaller third-party ecosystem than Moment had at its peak.

Use it if

  • You are migrating a codebase off Moment.js and want a near drop-in API without rewriting every date call
  • You need basic parse, format, add/subtract, and compare operations in the browser and care about bundle size
  • You need i18n formatting: 100+ locales exist and each one is only loaded when you import it
  • You want an immutable API so passing date objects around cannot mutate them, which was a classic Moment bug source
Skip it if

Setup reality

npm install dayjs and the core works immediately with no config and no dependencies. The friction is plugins: UTC, timezone, customParseFormat, relativeTime, and advancedFormat all need a separate import plus dayjs.extend() before first use, and if a module runs before the extend call you get runtime errors like 'dayjs.tz is not a function'. Locales are also manual imports. TypeScript types are bundled, but plugin types only appear after you import the plugin module.

Patterns

Parse a date string and format itparse-and-format

import dayjs from 'dayjs'

const d = dayjs('2026-08-04')
d.format('DD MMM YYYY')      // '04 Aug 2026'
d.format('YYYY-MM-DDTHH:mm') // '2026-08-04T00:00'

Only ISO 8601 strings parse reliably; anything else falls back to the native Date constructor, which differs across engines. Use the customParseFormat plugin for other formats.

Add or subtract timeadd-subtract-time

import dayjs from 'dayjs'

const nextWeek = dayjs().add(7, 'day')
const lastMonth = dayjs().subtract(1, 'month')
const combo = dayjs().add(1, 'year').subtract(2, 'hour')

Every call returns a new instance; dayjs objects are immutable, so chaining never mutates the original.

Get the difference between two datesdiff-between-dates

import dayjs from 'dayjs'

const a = dayjs('2026-01-01')
const b = dayjs('2026-08-04')
b.diff(a, 'day')        // 215
b.diff(a, 'month')      // 7
b.diff(a, 'month', true) // 7.09... (float instead of truncation)

diff truncates toward zero by default; pass true as the third argument to get the fractional value.

Show 'x minutes ago' stringsrelative-time

import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'

dayjs.extend(relativeTime)

dayjs('2026-08-01').fromNow() // '3 days ago'
dayjs().to(dayjs('2027-01-01')) // 'in 5 months'

fromNow does not exist until you extend with the plugin; forgetting extend() throws at runtime, not at build time.

Work in UTC instead of local timeutc-mode

import dayjs from 'dayjs'
import utc from 'dayjs/plugin/utc'

dayjs.extend(utc)

dayjs.utc('2026-08-04T12:00:00Z').format() // stays in UTC
dayjs('2026-08-04T12:00:00Z').utc().local() // convert back to local

Server code that formats timestamps should use utc mode; otherwise output silently depends on the host machine timezone.

Convert a date into a named timezonetimezone-convert

import dayjs from 'dayjs'
import utc from 'dayjs/plugin/utc'
import timezone from 'dayjs/plugin/timezone'

dayjs.extend(utc)
dayjs.extend(timezone)

dayjs('2026-08-04T12:00:00Z').tz('America/New_York').format('HH:mm') // '08:00'
dayjs.tz('2026-08-04 12:00', 'Asia/Kolkata') // parse as Kolkata wall time

The timezone plugin requires the utc plugin to be extended first, relies on the runtime Intl API, and is slow in loops over many dates.

Strictly parse and validate a custom formatstrict-parse-validate

import dayjs from 'dayjs'
import customParseFormat from 'dayjs/plugin/customParseFormat'

dayjs.extend(customParseFormat)

dayjs('04/08/2026', 'DD/MM/YYYY', true).isValid() // true
dayjs('31/02/2026', 'DD/MM/YYYY', true).isValid() // false

Without the third argument (strict mode) partial matches can still pass; always pass true when validating user input.

Compare two datescompare-dates

import dayjs from 'dayjs'

const deadline = dayjs('2026-12-31')
dayjs().isBefore(deadline)          // true
dayjs().isAfter('2026-01-01')       // true
dayjs().isSame('2026-08-04', 'day') // compare at day granularity

The second argument sets granularity; without it isSame compares to the millisecond, which is almost never what you want for calendar logic.

Snap to the start or end of a periodstart-end-of-period

import dayjs from 'dayjs'

dayjs().startOf('month').format('YYYY-MM-DD') // first of month, 00:00
dayjs().endOf('day')    // today 23:59:59.999
dayjs().startOf('week') // depends on locale's first day of week

startOf('week') is locale dependent (Sunday vs Monday); load the right locale or use isoWeek from the isoWeek plugin for ISO Monday weeks.

Format in another languageswitch-locale

import dayjs from 'dayjs'
import 'dayjs/locale/es'

dayjs.locale('es') // global default
dayjs('2026-08-04').format('dddd D MMMM') // 'martes 4 agosto'

dayjs('2026-08-04').locale('en').format('dddd') // per-instance override

Locales are not bundled by default; each one must be imported explicitly or format falls back to English silently.

Alternatives

PackageRegistryPick it when
date-fnsnpmYou want tree-shakeable pure functions that operate on native Date objects instead of a wrapper class
luxonnpmTimezone and Intl-heavy work matters more than bundle size; its zone support is first class rather than a plugin
momentnpmOnly for maintaining legacy code; Moment is in maintenance mode and its own docs point new projects elsewhere