You've probably been here: you want Jalali dates in the UI, but not a pile of packages, Moment plugins, and Jalali strings leaking into your API.
jalali-js (currently 0.4.2) is the small toolkit I reach for in that situation. Core does conversion and date math. React, Vue, or plain Web Components sit on top. Show Jalali. Store Gregorian by default, same idea as a native <input type="date">. Farsi docs are also available: jalali-js.yanovian.com/fa.
Who it is for
- You ship for Persian (or other Jalali-reading) users and need a date picker that doesn't fight your stack
- You want conversion / date math on the server or in shared code, with zero UI
- You're on React, Vue, Nuxt, Next, or no framework at all (Web Components)
- You're done stitching Moment plugins, math-only packages, and one-framework pickers together
Skip it if you only need a one-off Gregorian date and never show Jalali.
What you get
- Jalali on screen, Gregorian in storage by default (opt out when you really need Jalali-shaped values)
- A tiny TypeScript core: conversion, date math, selection rules
- Ready pickers for React / Vue / Web Components, plus ranges and event calendars (month, week, day, timeline / roadmap)
en/fa/ps, Iran holidays, and a bit of natural-language parsing ("فردا","next Farvardin")- Light and dark themes via CSS variables
Install only what you need
npm install jalali-js # currently 0.4.2
npm install @jalali-js/react # or @jalali-js/vue / @jalali-js/web
Want ranges, event calendars, NLP, or Iran holidays? Grab @jalali-js/ui-*, @jalali-js/nlp, @jalali-js/holidays, @jalali-js/i18n as you go. Same version everywhere.
Core
import { createCalendar, toGregorian, fromGregorian, addMonths } from 'jalali-js';
const jalali = createCalendar({ system: 'jalali' });
jalali.today();
toGregorian({ year: 1403, month: 5, day: 15 }, 'jalali');
// { year: 2024, month: 8, day: 5 }
addMonths({ year: 1403, month: 1, day: 31 }, 6, 'jalali');
// day clamps to the target month
Arithmetic leap years are the default (matches ICU for normal app ranges). If you ever need equinox-based leaps way outside that, pass engine: 'astronomical'.
Pickers
This is the important part: Jalali on screen, Gregorian out. Default onChange is an ISO string your DB can treat like any other date.
import '@jalali-js/react/date-picker.css';
import { DatePicker } from '@jalali-js/react';
<DatePicker
system="jalali"
locale="fa"
showHolidays
rules={{
minDate: { year: 1403, month: 1, day: 1 },
maxDate: { year: 1403, month: 12, day: 29 },
disabledWeekdays: [4, 5],
}}
onChange={(value) => {
// e.g. '2024-08-05'
}}
/>;
Need a time too? precision="datetime". On Vue, v-model just works. No framework? @jalali-js/web and <jalali-date-picker>.
<script setup lang="ts">
import '@jalali-js/vue/date-picker.css';
import { DatePicker } from '@jalali-js/vue';
import type { StorageValue } from 'jalali-js';
import { ref } from 'vue';
const stored = ref<StorageValue>();
</script>
<template>
<DatePicker v-model="stored" system="jalali" locale="fa" show-holidays />
</template>
Ranges and events
@jalali-js/ui-react (and the Vue / web twins) give you RangePicker and EventCalendar. You own the event data; it handles month, week, day, and timeline layouts. Overlaps sit side by side.
import { EventCalendar } from '@jalali-js/ui-react';
<EventCalendar
system="jalali"
locale="fa"
view="week"
initialDate={{ year: 1403, month: 5, day: 15 }}
events={events}
/>;
For a project-style list, try view="timeline" with layout: 'single' | 'alternating' | 'roadmap'.
<EventCalendar
system="jalali"
locale="fa"
view="timeline"
timeline={{ layout: 'roadmap', showIcons: true }}
events={milestones}
/>;
Format, phrases, holidays
import { format, formatRelative, fa } from '@jalali-js/i18n';
import { parse } from '@jalali-js/nlp';
import { isHoliday } from '@jalali-js/holidays';
format(date, fa); // '۱۵ مرداد ۱۴۰۳'
formatRelative(earlier, date, fa); // '۳ روز پیش'
parse('فردا', 'fa');
isHoliday({ year: 1403, month: 1, day: 1 });
Locales out of the box: en, fa, ps.
Which package?
| Package | Grab it when… |
|---|---|
jalali-js | You only need conversion / math |
@jalali-js/react / vue / web | You want a picker |
@jalali-js/ui-* | Ranges, events, themes |
@jalali-js/i18n / nlp / holidays | Formatting, "فردا", Iran holidays |
That's it
Start here if you like reading: getting started. Or just open a playground and steal a snippet: React · Vue · Web Components.
MIT. If you hit a weird edge or something's confusing, drop it on GitHub issues. Always glad when people poke at this stuff.

