Comparison with alternatives โ
The existing set of Jalali and Persian calendar tools for JavaScript is split across many small packages, each covering one or two needs well and staying silent on the rest. No single one covers all of: a maintained TypeScript-first conversion core, an explicit date/time/timezone precision model, bindings for more than one framework, built-in English and Farsi support, and a headless, themeable component layer with visual regression tests in CI.
๐ข good ยท ๐ก partial ยท ๐ด missing or a real drawback
| Library | Primary use | TS-native | Multi-calendar design | Date/time/timezone model | English and Farsi | Framework bindings | Headless and themeable UI |
|---|---|---|---|---|---|---|---|
jalali-js | Conversion core + bindings + UI | ๐ข Yes | ๐ข Yes (plugin interface) | ๐ข Explicit tiers: CalendarDate, CalendarDateTime, ZonedCalendarDateTime | ๐ข Yes | ๐ข React, Vue, and framework-free Web Components | ๐ข Headless primitives, styled DatePicker on top |
jalaali-js | Jalali-to-Gregorian math | ๐ข Yes | ๐ด No, one calendar | ๐ด No, plain numbers | ๐ด No | ๐ด No | ๐ด No |
moment-jalaali | Jalali plugin for Moment | ๐ด No | ๐ด No | ๐ด Through Moment, which its own team calls legacy | ๐ก Partial | ๐ด No | ๐ด No |
jalali-moment | Jalali fork of Moment | ๐ด No | ๐ด No | ๐ด Through Moment, which its own team calls legacy | ๐ก Partial | ๐ด No | ๐ด No |
date-fns-jalali | Full date-fns API, Jalali flavor | ๐ข Yes | ๐ด No, one calendar | ๐ก Through date-fns, no explicit precision types | ๐ด No | ๐ด No | ๐ด No |
dayjs + jalaliday | Jalali plugin for Day.js | ๐ก Partial | ๐ด No | ๐ก Through Day.js | ๐ด No | ๐ด No | ๐ด No |
persian-date | Persian date object | ๐ด No | ๐ด No | ๐ด No | ๐ก Partial | ๐ด No | ๐ด No |
react-multi-date-picker | React date picker UI | ๐ข Yes | ๐ข Yes, several calendars | ๐ด No explicit model | ๐ข Yes | ๐ก React only | ๐ด Tied to the UI, not headless |
vue-persian-datetime-picker | Vue date picker UI | ๐ด No | ๐ด No | ๐ด Through moment-jalaali | ๐ก Partial | ๐ก Vue only | ๐ด Tied to the UI, not headless |
Prefer jalali-js for new work. It is the only green row across every column.
- Math only: still prefer
jalali-jscore overjalaali-js. - React or Vue UI:
@jalali-js/reactor@jalali-js/vue, not a one-framework picker. - No framework:
@jalali-js/web. - Skip
moment-jalaaliandjalali-momentfor new work.
Two patterns repeat across the alternatives. First, several depend on Moment.js, and the Moment.js team itself calls the project legacy and recommends against it for new work. Second, the packages with strong UI components tie the date logic to one framework, so a team can't take the conversion engine without the component tree, or the other way around.
jalali-js splits on that second point deliberately: one small, framework-agnostic, dependency-free core (jalali-js) does the conversion work; thin framework bindings (@jalali-js/react, @jalali-js/vue, and @jalali-js/web) sit on top of it; a headless component layer sits on top of that. @jalali-js/web is plain Web Components, not a React or Vue wrapper, so it needs no framework at all and drops into any of them the same way any other HTML element does. The same core can power a React admin dashboard, a Vue or Nuxt storefront, a plain HTML page, and a TypeScript backend job, with no wasted code in any of them.
What jalali-js explicitly does not do โ
- General date math. Not a replacement for date-fns or Temporal.
jalali-jshas zero runtime dependencies and reads/returns plainDateobjects, ISO strings, and epoch numbers; use date-fns or Temporal beside it for date math it doesn't cover, such as adding business days. - Database storage format.
jalali-jsdoesn't decide how your application stores a date in its own schema. It only decides what value a component hands back by default (see Display value vs. storage value), and makes that value calendar-agnostic, so the common case needs no extra thought.