moment-jalaali teaches moment.js to speak the Persian calendar
A Jalaali (Jalali, Persian, Khorshidi, Shamsi) calendar system plugin for moment.js.
At a glance
- What is it?
- moment-jalaali is a calendar plugin for moment.js that adds the Jalaali, Persian, Khorshidi or Shamsi calendar through a simple convention, a j in front of the format token. It also ships a note from February 2022 telling you that if you only need to display a Persian date, the built-in Intl API may be all you want, which is a more useful recommendation than it sounds.
- Who is it for?
- moment-jalaali suits a project that already uses moment.js and needs Persian calendar arithmetic, parsing and formatting rather than a display string, since the j-prefixed tokens and the helper methods cover the whole API surface.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 75 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A j in front of the token is the whole idea
The Jalaali calendar is a solar calendar that was used in Persia, and variants of it are still in use in Iran and in Afghanistan. The plugin adds it to moment.js by following one convention: when you want to format or parse a string, you add a j to the format token, so `jYYYY` or `jM` instead of `YYYY` or `M`. The reasoning behind that design is that it keeps the entire moment API intact, so everything the library already does, parsing, arithmetic, duration, start of, end of, all of it works with the Persian calendar once the tokens are switched over. The result is that a caller does not have to learn a second date library, only a second set of format characters. The conversion itself is based on an algorithm provided by Kazimierz M. Borkowski, and the documentation describes its performance as very good, which matters because a calendar conversion sits in the hot path of any screen that shows a date.
The February 2022 note is the most useful paragraph in the README
Before the tutorial, the README inserts a note dated February 2022 that says, in effect, if you only need to display a date and time in the Persian calendar, you may use `Intl`, the ECMAScript Internationalisation API, which has very good browser support. The examples show what it does. Formatting a date with the `fa-IR` locale gives the Persian calendar with Persian numerals, the same format with the `fa-IR-u-nu-latn` locale gives the Persian calendar with Latin numerals, and the `en-US-u-ca-persian` locale gives the Persian calendar inside an English date format, and the year, month and day can each be asked for on their own. So the built-in API covers a large part of the use case with no dependency at all. The plugin earns its place in the case that note does not cover, which is arithmetic and parsing in the Persian calendar rather than formatting a single date.
The API surface is a set of j-prefixed methods and tokens
The documented API mirrors moment, with the j convention applied to both formats and methods:
m = moment('1360/5/26', 'jYYYY/jM/jD') // Parse a Jalaali date
m.format('jYYYY/jM/jD [is] YYYY/M/D') // 1360/5/26 is 1981/8/17
m.jYear() // 1360
m.jMonth() // 4
m.jDate() // 26
m.jDayOfYear() // 150
m.jWeek() // 22
m.jWeekYear() // 1360On top of the getters there are setters and the moment arithmetic verbs, so `m.add(1, 'jYear')`, `m.add(2, 'jMonth')` and `m.subtract(1, 'jMonth')` all work, and `m.jMonth(11)` sets the month, as does `m.startOf('jMonth')` and `m.startOf('jYear')`. The calendar specific helpers are `jIsLeapYear`, which reports whether a year has the extra day, and `jDaysInMonth`, which returns the length of a month, and the validity check handles the interesting case correctly, since `1391/12/30` is a valid date in a leap year and `1392/12/30` is not in a common year. Parsing also works across calendars, so a Gregorian string can be formatted into a Persian one and the reverse.
Persian digits and the dialect switch are opt in
Persian language support is added by a single call, `moment.loadPersian()`, and it takes an options object with two fields. The first is `usePersianDigits`, a boolean that defaults to false and that the documentation annotates with a warning to use at your own risk, since it changes the numerals in every formatted string. The second is `dialect`, which defaults to `persian` and can also be `persian-modern`, and the difference is in the names of the days and months, where the default dialect uses forms such as the traditional day names and the modern one uses the names in current everyday use. Both are worth knowing about because the same date rendered in the two dialects looks different in a way that is not a bug, and a mixed audience can notice. The `loadPersian` call is also separate from the calendar support, which means a project can use the Jalaali calendar with Gregorian numerals without pulling in the locale at all.
The rough edges are documented, which is rare
Two rough edges get explicit mention. The first is an error message people hit, the `humanize` of undefined error, and the fix is to require the `fa` locale as well, since the Persian locale has to be loaded for the humanised relative time strings to exist. The second is React Native, where the relative time formatting needs the locale supplied by hand, because the bundler will not resolve it the way Node does:
import moment from "moment-jalaali";
import fa from "moment/src/locale/fa";
moment.locale("fa", fa);
moment.loadPersian();The `humanize` failure is worth understanding rather than memorising. The calendar and the language are separate layers, and the plugin only provides the calendar, so an application that formats a date in Persian and also wants a sentence like three days ago in Persian needs the moment locale as well. The TypeScript situation is the third small sharp edge, the type definitions are not bundled and have to be installed separately as `@types/moment-jalaali`.
The package shape and how the build works
The manifest is small and tells you what the plugin is made of. It is named `moment-jalaali` at version 0.10.5, authored by Behrang Noruzi Niya, MIT licensed, with `index.js` as the main entry. The runtime dependencies are three: `moment` itself at 2.30.1, `moment-timezone` at 0.6.2, and `jalaali-js` at 1.2.8, which is the calendar arithmetic the plugin builds on. The scripts are equally plain. The tests run under mocha with the spec reporter and the bdd interface and a leak check, the linter runs eslint over the source and the test file separately because the test file needs the mocha environment, and the build is a single node script, `umd-build.js`, which produces the browser bundle. There is a `prepublishOnly` hook that runs the build before publishing, and the package declares `publishConfig` with provenance enabled, so the published artefact carries a build attestation. The tree has a `builder/` directory, a `build/` directory with the compiled output, a `umd-build.js` and a single `test.js` file, and the top level is a `.eslintrc.yml` and a changelog.
The tags lag the package, and the ecosystem has grown around it
One inconsistency is worth flagging for anyone pinning a version. The listed GitHub releases stop at v0.7.3 from 2018, with v0.7.1 and v0.7.0 in 2017, while the package manifest is at 0.10.5 and the last push to the repository was on 2026-08-09. The npm version is the one that matters for an install, and the release list is simply not a complete record of what has been published, which is the same situation as any repository that publishes from the default branch without cutting a tag for every version. The other thing the README does well is point at the ecosystem, and the list is a good map of what this plugin enables. There is a React date picker with Persian calendar support, a React module with range, date and time pickers, two Angular pickers, one of them a lightweight angular.js component built on this library, a Vue date time picker, a library for calculating holidays in the Persian calendar, and a sibling plugin for the Hijri calendar in the same family. That is a good sign for the health of the package, since several independent projects have built on it.
Editorial conclusion
moment-jalaali suits a project that already uses moment.js and needs Persian calendar arithmetic, parsing and formatting rather than a display string, since the j-prefixed tokens and the helper methods cover the whole API surface. It is a poor fit for a new project that only has to print a Persian date, because the built-in Intl API does that with no dependency at all, and it is a poor fit for a project that has moved off moment.js, since the plugin is a moment extension by definition. Before you adopt it, check three things: whether moment is still in your dependency tree, since the plugin depends on moment and moment-timezone directly, whether you need the Persian locale as well as the calendar, since `humanize` breaks without the `fa` locale, and the version you pin, since the package is at 0.10.5 while the last tagged GitHub release is v0.7.3 from 2018 and the last push to the repository was on 2026-08-09.
Frequently asked questions
How do I install moment-jalaali?
With `npm install moment-jalaali`. In the browser you can load the built file, `node_modules/build/moment-jalaali.js`, after moment itself, and TypeScript users need the definitions installed separately with `npm install @types/moment-jalaali`.
How do I format a Persian date with moment-jalaali?
Add a j in front of the moment format token, so `jYYYY`, `jM` and `jD` instead of `YYYY`, `M` and `D`. The plugin mirrors the moment API, and there are matching accessors such as jYear, jMonth, jDate, jDayOfYear, jWeek and jWeekYear, plus jIsLeapYear and jDaysInMonth for the calendar specific values.
Do I need moment-jalaali if I only want to display a Persian date?
Probably not. The note in the README from February 2022 points to the built-in Intl API, where `new Intl.DateTimeFormat('fa-IR')` formats a date in the Persian calendar, and `en-US-u-ca-persian` gives the Persian calendar inside an English format. The plugin earns its place when you need calendar arithmetic and parsing rather than a formatted string.
What causes the 'humanize' of undefined error in moment-jalaali?
The Persian locale has not been loaded, since the plugin provides the calendar and not the language strings. Requiring the locale with `require('moment/locale/fa')` fixes it, and in React Native the locale is imported from moment/src/locale/fa and registered with moment.locale before calling loadPersian.
How do I get Persian digits and the modern dialect?
Call `moment.loadPersian({usePersianDigits: true})` for Persian numerals, which the documentation flags as use at your own risk, and `moment.loadPersian({dialect: 'persian-modern'})` for the modern day and month names instead of the default persian dialect.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/jalaali-moment-jalaali)Was this useful?