What date-fns Does
- Format — 50+ format tokens, locale-aware
- Parse — strict parsing, ISO, custom formats
- Arithmetic — add/sub days, months, years, hours, minutes, weeks
- Comparison — isAfter, isBefore, isEqual, closestTo
- Difference — differenceInDays/Hours/Minutes
- Distance — formatDistance, formatDistanceToNow (relative strings)
- Locales — 70+ locales
- Timezone — via date-fns-tz adapter
- Immutable — every function returns a new Date
Architecture
Pure functions over native Date objects — no classes, no wrappers. Each function is a separate module. Locales are separate imports for tree-shakeability. Types are native TypeScript (not @types).
Self-Hosting
Client or server library, zero runtime deps.
Key Features
- 200+ pure functions
- Tree-shakeable (v2+)
- TypeScript native
- 70+ locales
- Immutable
- Small (~15KB with common functions)
- No Moment-style mutable object
- ESM and CJS builds
- Native Date compatible
Comparison
| Library | Size | API Style | Tree-shake | Timezone |
|---|---|---|---|---|
| date-fns | ~15KB used | Functional | Yes | Via plugin |
| Day.js | ~6KB | Chainable (Moment-like) | Plugins | Via plugin |
| Luxon | ~30KB | OO (classes) | No | Built-in |
| Moment | ~230KB | Mutable classes | No | Built-in |
| Temporal (TC39) | Native | Modern API | N/A | Native |
FAQ
Q: date-fns or Day.js — which should I choose? A: date-fns is more functional and tree-shakes better; Day.js feels more like Moment with a smoother chainable API. It comes down to personal preference.
Q: How do I handle timezones?
A: Use the date-fns-tz companion package, which provides zonedTimeToUtc, formatInTimeZone, and more.
Q: Will I not need it once Temporal ships? A: Temporal isn't fully landed yet (Safari has partial support) and the polyfill is ~60KB. date-fns will remain mainstream for the foreseeable future.
Sources & Credits
- Docs: https://date-fns.org
- GitHub: https://github.com/date-fns/date-fns
- License: MIT