ShopperCove
Menu
All writingBlogTopicsCategoriesAboutRSS
Blog
Categories
Observability & SRE62All categories
About

Plate 89

  1. Blog

Dayjs vs date-fns: 3.5 KB vs 6.9 KB Gzip

Aditya Challa·5 October 2026·4 min read

Hands-on
On this page
  1. What I tested
  2. How big was each bundle?
  3. Which one was faster?
  4. Which one should you pick?
  5. Sources
  6. Related

I bundled the same six date operations on this box: dayjs 1.11.23 came in at 3,468 B gzip against date-fns 4.4.0 at 6,860 B. On a 100,000-call parse, add 7 days, and format loop, dayjs took 4.3 µs per call and date-fns 5.8 µs.

Short answer: pick dayjs when you want the smallest date helper for a browser bundle and a chainable API. Pick date-fns when you prefer plain functions on native Date objects and already format with its tokens. No affiliate links in this post.

What I tested

  • Machine: 8 vCPU Intel Xeon / 15 GB RAM shared Linux cloud box, tested 6 Oct 2026 about 01:04–01:06 IST.
  • Versions: dayjs 1.11.23, date-fns 4.4.0, Node 22.20.0, esbuild 0.28.2 (browser platform, ESM, minify) + gzip -9.
  • Fixture: /workspace/bench-dayjs-datefns/. The 6-op entry parses an ISO string, adds 7 days, formats, takes a day diff, compares with isBefore, and formats the start of the month. A second entry does parse + format only.
  • Speed: TZ=UTC, 100,000 calls × 9 rounds (median) after warm-up, over 1,000 ISO strings. I ran the full speed script twice; the second run landed within about 7% of the first on every row.
  • Findings: 6-op bundle 3,468 B vs 6,860 B gzip. Parse + format alone was 3,424 B vs 6,767 B. Pipeline 428 ms vs 578 ms per 100k calls. Both libraries printed the same output ("2026-10-13 01:15", diff 7) on the parity check.
  • One surprise: date-fns tree-shakes, but a single format() call still pulled in the en-US locale strings ("less than a second", "about 1 hour"), so parse + format alone weighed 6.8 KB gzip. Format-only speed was a tie: 183 ms vs 174 ms.
  • Not tested: dayjs plugins (utc, timezone, customParseFormat), other locales, DST edge cases, date-fns-tz, the Temporal API, React Native, or tree-shaking in Rollup or webpack.

How big was each bundle?

Entry (esbuild browser, minify)Minifiedgzip -9
dayjs, 6 ops7,904 B3,468 B
date-fns, 6 ops22,548 B6,860 B
dayjs, parse + format7,803 B3,424 B
date-fns, parse + format22,272 B6,767 B

dayjs was about 2.0× smaller gzip on both entries. The dayjs number barely moves as you add calls because the core is one object; date-fns grows with each imported function. Budget it in CI with size-limit vs bundlesize, and see where the bytes go with source-map-explorer vs webpack-bundle-analyzer.

Which one was faster?

Path (100,000 calls, median of 9, TZ=UTC)dayjsdate-fns
parse ISO + add 7 days + format + diff428.2 ms (4.3 µs)578.2 ms (5.8 µs)
format a timestamp only183.3 ms174.3 ms
parse ISO only34.6 ms153.4 ms

The pipeline gap comes mostly from parsing: dayjs parsed ISO strings about 4.4× faster here. Formatting alone was within noise. If your hot path is rendering a list of timestamps, speed is not the reason to switch. I validate API date strings with schemas from Zod vs Valibot before they reach either library.

Which one should you pick?

SituationMy pick
Browser app, tight bundle budget, a few date opsdayjs
You like immutable chains: dayjs(x).add(7, 'day')dayjs
You want plain functions on native Datedate-fns
Heavy use of many helpers (intervals, weeks, ISO weeks)date-fns
Migrating off moment.js with similar syntaxdayjs

Bottom line: dayjs 1.11.23 shipped 3.5 KB gzip against date-fns 4.4.0 at 6.9 KB for the same six operations, and its parse-heavy pipeline took about 26% less time. Who should not switch: teams with a large date-fns codebase. A 3.4 KB gzip win does not pay for rewriting every call site and its tests. If you do swap, keep the parity tests in Jest vs Vitest and drop the old dependency with knip vs depcheck.

How this was made: I installed dayjs and date-fns on the ShopperCove box, measured esbuild minify + gzip sizes for two entries, timed parse, format, and pipeline loops twice, and saved the JSON (res-bundle.json, res-speed-run1.json, res-speed-run2.json). The write-up was drafted with AI help and checked against that output.

Sources

  • https://github.com/iamkun/dayjs
  • https://www.npmjs.com/package/dayjs
  • https://github.com/date-fns/date-fns
  • https://www.npmjs.com/package/date-fns

Related

  • https://www.shoppercove.com/blog/size-limit-vs-bundlesize
  • https://www.shoppercove.com/blog/source-map-explorer-vs-webpack-bundle-analyzer
  • https://www.shoppercove.com/blog/zod-vs-valibot
  • https://www.shoppercove.com/blog/jest-vs-vitest
  • https://www.shoppercove.com/blog/knip-vs-depcheck
  • https://www.shoppercove.com/blog/rolldown-vs-rollup
  • https://www.shoppercove.com/blog/terser-vs-esbuild-swc-minify
  • https://www.shoppercove.com/blog/tanstack-query-vs-swr
dayjsdate-fnsjavascriptbundle sizeperformanceweb developmentdate library

Lab evidence

What I found running this

Hands-on on ShopperCove box 6 Oct 2026 ~01:04-01:06 IST (8 vCPU Intel Xeon / 15 GB shared Linux, Node 22.20.0). dayjs 1.11.23 vs date-fns 4.4.0, esbuild 0.28.2 browser ESM minify + gzip -9. Fixture /workspace/bench-dayjs-datefns/: 6-op entry (parse ISO, add 7 days, format, day diff, isBefore, startOf month) and parse+format entry. Speed: TZ=UTC, 100,000 calls x 9 rounds median after warm, 1,000 ISO strings, run twice (within ~7%). Run 1: gzip 3,468 vs 6,860 B (parse+format 3,424 vs 6,767 B); pipeline 428.170 vs 578.229 ms; format 183.317 vs 174.339 ms; parse 34.643 vs 153.373 ms. Parity output identical. Surprise: date-fns format() pulls en-US locale strings. Disk ~2.1 MB vs ~27 MB. Raw: res-bundle.json, res-speed-run1.json, res-speed-run2.json. Not tested: dayjs utc/timezone plugins, locales, DST, date-fns-tz, Temporal, Rollup/webpack. No affiliate.

Notes when a lab post goes up

Occasional email for new hands-on reviews. No sequence and no sponsors.

Related links

  • Plate 64

    Ky vs Axios: 9.8 KB vs 19.6 KB Gzip

    5 Oct 2026

  • Plate 17

    Immer vs Mutative: 86 us vs 3 us per Update

    5 Oct 2026

  • Plate 48

    Zod vs Valibot: 1.14M vs 0.97M Parses

    zod 4.6.5 vs valibot 1.5.0 on one nested user schema (uuid/email/age/tags/profile/enum). Warm medians after 2k warmup + 9×50k: zod.parse 1,144,494 ops/s vs valibot.parse 968,187 (~1.18×). safeParse fail: valibot 697,760 vs zod 415,523 (~1.7×). esbuild minify+gzip9: 452,999/92,636 B vs 85,126/15,422 B. Package trees ~6.1 MB vs ~1.9 MB. Fixture /workspace/bench-zod-valibot/.

    5 Oct 2026

On this page

  1. What I tested
  2. How big was each bundle?
  3. Which one was faster?
  4. Which one should you pick?
  5. Sources
  6. Related
All writingBlogCategoriesTopicsAboutPrivacyRSS

© 2026 ShopperCove