Plate 89
Dayjs vs date-fns: 3.5 KB vs 6.9 KB Gzip
Aditya Challa4 min read
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) | Minified | gzip -9 |
|---|---|---|
| dayjs, 6 ops | 7,904 B | 3,468 B |
| date-fns, 6 ops | 22,548 B | 6,860 B |
| dayjs, parse + format | 7,803 B | 3,424 B |
| date-fns, parse + format | 22,272 B | 6,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) | dayjs | date-fns |
|---|---|---|
| parse ISO + add 7 days + format + diff | 428.2 ms (4.3 µs) | 578.2 ms (5.8 µs) |
| format a timestamp only | 183.3 ms | 174.3 ms |
| parse ISO only | 34.6 ms | 153.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?
| Situation | My pick |
|---|---|
| Browser app, tight bundle budget, a few date ops | dayjs |
| You like immutable chains: dayjs(x).add(7, 'day') | dayjs |
| You want plain functions on native Date | date-fns |
| Heavy use of many helpers (intervals, weeks, ISO weeks) | date-fns |
| Migrating off moment.js with similar syntax | dayjs |
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
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.
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