jalaali-js

Zero-dependency TypeScript library for converting between Jalaali (Persian) and Gregorian calendar dates.

Library
npm
v2.0.1
365stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
58/100Fair
Development Activity60
Maintenance32
Community60
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
79/100Good
Architecture82
Code Quality88
Innovation80
Learning Curve65

jalaali-js is a zero-dependency TypeScript library that converts dates between the Jalaali (Persian, Shamsi) calendar and the Gregorian calendar. It implements the algorithm published by Kazimierz M. Borkowski in The Persian calendar for 3000 years, producing bit-for-bit compatible results with the original v1 release while adding first-class TypeScript types and a dual ESM/CommonJS build.

Beyond the headline toJalaali/toGregorian conversions, the library exposes lower-level primitives — Julian Day number conversion (j2d/d2j, g2d/d2g), leap-year detection, month-length lookups, and Jalaali week boundaries — so applications that need date arithmetic, calendar validation, or custom date-picker logic aren’t limited to a single high-level API.

What You Get

  • Bidirectional Gregorian ↔ Jalaali conversion via toJalaali/toGregorian, accepting either individual date components or a native Date object
  • Low-level Julian Day number helpers (j2d, d2j, g2d, d2g) for building custom date arithmetic
  • Leap-year and month-length utilities (isLeapJalaaliYear, jalaaliMonthLength, isValidJalaaliDate) for calendar validation
  • Jalaali week-boundary calculation (jalaaliWeek) that returns the Saturday–Friday span containing a given date
  • First-class .d.ts type definitions with zero runtime dependencies, published as both ESM and CommonJS

Common Use Cases

  • Persian date pickers - front-end developers building calendar/date-picker UI for Iranian or Afghan users convert between the visible Jalaali date and the Gregorian Date objects JavaScript works with natively.
  • Localized business applications - backend teams building invoicing, scheduling, or reporting systems for Iran need to store and display dates in the Jalaali calendar while keeping Gregorian dates for interoperability.
  • Calendar validation and arithmetic - applications need to validate Jalaali dates, determine leap years, or compute month lengths without hand-rolling the leap-cycle rules themselves.
  • Migrating off unmaintained Jalaali libraries - teams replace older, abandoned Jalaali conversion packages with a maintained, typed alternative that ships a modern ESM/CJS dual build.

Under The Hood

Architecture The library is a single well-factored module (src/index.ts, ~500 lines) with a clear public/internal split — high-level conversions (toJalaali, toGregorian, isValidJalaaliDate, isLeapJalaaliYear, jalaaliMonthLength) layered over Julian Day number primitives (j2d/d2j, g2d/d2g), which in turn sit on top of internal cycle-lookup helpers (jalCalCore, leapFromCycle, jalCalLeap) that implement the Borkowski 33-year-cycle table (BREAKS). There are no classes, no external state, and no I/O — every function is pure, operating on plain object literals and numbers, so the whole module is really one dependency chain funneling through a single cycle-lookup core; changing that core would ripple through every exported function, and the code isolates that risk deliberately rather than duplicating the lookup logic elsewhere.

Tech Stack Written in TypeScript targeting ES2022 with NodeNext module resolution and strict mode enabled. Built with tsdown into dual ESM (.js/.d.ts) and CommonJS (.cjs/.d.cts) outputs, with a custom outExtensions mapping to keep published file paths stable across major versions. Tests run under Vitest with v8 coverage, package correctness is checked with publint —strict, and benchmarks run via tsx. There are zero runtime dependencies — only devDependencies (typescript, vitest, tsdown, publint, tsx, @types/node) — and the package is published through pnpm, targeting Node >=20.

Code Quality Three dedicated test files cover unit-level correctness against hand-verified Gregorian/Jalaali fixture pairs and known leap/common years, plus separate build-equivalence and build-integration suites that verify the compiled dist/ output matches source behavior. CI builds once on Node 24 and fans the same dist/ artifact out across a 3-OS by 3-Node-version matrix, re-running typecheck, tests, and publint on each combination rather than rebuilding per job. TypeScript strict mode is on, with noImplicitOverride and noFallthroughCasesInSwitch enabled, and every export carries a documentation comment describing thrown errors and valid ranges.

API Design The public API stays small and consistent — every function takes and returns plain object literals (JalaaliDate, GregorianDate) rather than custom classes, so there’s no wrapper type to learn beyond what’s documented. toJalaali accepts either three numeric components or a native Date, minimizing boilerplate for the common case of converting an existing JS date. Every export carries a documentation block with a runnable example, explicit error-throwing behavior, and remarks calling out edge cases (DST handling in jalaaliWeek, overflow semantics in jalaaliToDateObject), so hover-documentation alone is generally enough to use the library correctly. Getting started requires a single import and no configuration.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search