1.227 Calendar Internationalization Libraries#
Comprehensive analysis of libraries for calendar internationalization: non-Gregorian calendar systems (Islamic/Hijri, Chinese Lunar, Persian/Jalali, Hebrew, Thai Buddhist, Japanese Imperial, Ethiopian, Coptic, Indian national), locale-aware date formatting (Intl.DateTimeFormat, @formatjs, Babel, ICU4X, date-fns), RTL calendar layout strategies, and CJK-specific date handling (solar terms, era systems, numeral representations). Evaluates both JavaScript and Python ecosystems. Key finding: Intl.DateTimeFormat covers 12+ calendar systems natively in modern browsers and is the correct starting point; dedicated libraries like hijri-converter and jdatetime fill gaps for server-side computation and calendar-specific arithmetic that Intl cannot perform.
Explainer
Calendar Internationalization: Domain Explainer#
What This Solves#
If software libraries were tools in a hardware store, calendar internationalization libraries would be in the “Measurement Conversion & Universal Adapters” aisle – tools that let you translate between fundamentally different systems of measuring and expressing the passage of time.
The Core Problem#
Most software assumes the Gregorian calendar. January 1 is New Year’s Day. A year has 365 or 366 days. Months alternate between 30 and 31 days (except February). This assumption is baked into programming languages, databases, date pickers, and every scheduling interface on the web.
But the Gregorian calendar is only one of dozens of calendar systems actively used by billions of people worldwide:
1.8 billion Muslims use the Islamic (Hijri) calendar for religious observances. Ramadan, Eid al-Fitr, and Hajj dates are determined by the Hijri calendar, which has 354 or 355 days per year. A Hijri month starts when the new crescent moon is sighted – or when a tabular calculation says it should.
1.4 billion Chinese speakers use the Chinese lunisolar calendar for traditional festivals. Chinese New Year, Mid-Autumn Festival, and Qingming are all determined by the lunar calendar. The 24 solar terms (jieqi) govern agricultural practices and cultural observances.
90 million Iranians and Persian-speaking communities use the Solar Hijri (Jalali) calendar as their primary civil calendar. Government documents, school calendars, and everyday dates all use Jalali dates. Today might be 18 Esfand 1404 to an Iranian user, not March 9, 2026.
15 million Hebrew speakers use the Hebrew calendar for religious observances. Shabbat times, holiday dates, and lifecycle events require Hebrew date computation.
70 million Thai citizens use the Buddhist Era calendar, where 2026 CE is 2569 BE. The Thai government uses this system on all official documents.
126 million Japanese use the Imperial era system alongside Gregorian. The current era, Reiwa (令和), began in 2019. Official documents, government forms, and many business contexts require era-based dates.
120 million Ethiopians use the Ethiopian calendar, which is 7-8 years behind the Gregorian calendar and has 13 months (12 months of 30 days plus a 13th month of 5-6 days).
What Happens When Software Ignores This#
When a booking application only displays Gregorian dates, an Iranian user must mentally convert every date to understand their schedule. When a social media platform sets event times for Ramadan Iftar, it must know the Hijri date to calculate the correct timing. When a Japanese government form requires a date in Reiwa format, entering “2026” is incorrect.
The consequences range from user frustration to operational failure:
- Healthcare: A patient’s medication schedule anchored to Ramadan fasting requires Hijri calendar awareness.
- Finance: Islamic banking products calculate profit-sharing periods on the Hijri calendar.
- Government: Thai, Ethiopian, and Japanese official systems require their native calendar systems.
- Agriculture: Chinese farming communities still reference the 24 solar terms for planting and harvesting.
- E-commerce: Sale dates tied to Chinese New Year, Diwali, or Nowruz must compute dates from non-Gregorian calendars.
The Hardware Store Analogy#
Imagine a hardware store that only sells metric tools. It works well in most of the world – until customers from the United States, United Kingdom, or Myanmar walk in needing imperial measurements. They don’t need a different hardware store. They need the same hardware store with adapters and conversion tools that let them work in their native measurement system.
Calendar internationalization libraries are those adapters. They sit between your application’s internal date representation (usually Gregorian, stored as Unix timestamps or ISO 8601 strings) and the user-facing display and input layer where dates must appear in the user’s native calendar system.
Solution Categories#
Calendar internationalization breaks down into four distinct problem areas, each with different library needs:
1. Display Formatting (Easiest)#
Converting a Gregorian date into locale-appropriate text: “March 9, 2026” becomes
“18 اسفند ۱۴۰۴” for Persian or “令和8年3月9日” for Japanese. Modern browsers handle
this natively through Intl.DateTimeFormat – no library required for most cases.
2. Calendar Arithmetic (Moderate)#
Adding 30 days to a Hijri date, finding the next Friday in the Persian calendar, or determining which Hebrew month a Gregorian date falls in. This requires understanding each calendar system’s rules for month lengths, leap years, and intercalation. Libraries are essential here because each system has unique rules.
3. Calendar-Specific Features (Specialized)#
Computing Islamic prayer times, Hebrew holiday dates, Chinese solar terms, or Japanese era boundaries. These go beyond date conversion into domain-specific calculations that require astronomical data or cultural rulesets.
4. Visual Layout (CSS + Libraries)#
Rendering a calendar grid that reads right-to-left for Arabic and Hebrew users, displays CJK characters correctly, or starts the week on Saturday (many Middle Eastern countries) or Monday (most of Europe). This spans both calendar UI libraries and CSS layout concerns.
Trade-offs at a Glance#
Native APIs vs. libraries: Intl.DateTimeFormat is free and handles display
formatting for 12+ calendar systems. But it cannot do calendar arithmetic (add
3 Hijri months) or compute holidays. Libraries fill that gap.
Accuracy vs. simplicity: Islamic calendars face a fundamental tension between astronomical calculation (moon sighting) and tabular calculation (mathematical prediction). Different countries use different methods. No single library can be “correct” for all users.
Data size vs. coverage: Chinese lunar calendar libraries ship precomputed lookup tables spanning 1900-2100. More coverage means more data. ICU4X ships CLDR data as a ~200 KB WASM binary. Babel for Python installs ~30 MB of locale data.
Browser-native vs. portable: Intl.DateTimeFormat works everywhere browsers
run but is unavailable in embedded systems, edge workers without V8/JSC, or
languages other than JavaScript. ICU4X bridges this gap with Rust/WASM.
Key Terminology#
- CLDR (Common Locale Data Repository): Unicode consortium’s database of locale-specific formatting rules. The source of truth that Intl, ICU, and Babel all consume.
- ICU (International Components for Unicode): The C/C++/Java library that implements CLDR rules. Browsers embed ICU for Intl support.
- ICU4X: The next-generation Rust rewrite of ICU, designed for WASM and resource-constrained environments.
- Hijri: The Islamic calendar. “Islamic” and “Hijri” are interchangeable in library naming.
- Jalali / Shamsi: The Persian solar calendar. “Jalali,” “Shamsi,” and “Solar Hijri” refer to the same system.
- Lunisolar: A calendar system that tracks both moon phases (months) and solar year (seasons). Chinese, Hebrew, and Hindu calendars are lunisolar.
- Era system: Counting years from a culturally significant epoch. Japanese Imperial eras, Thai Buddhist era, and the Islamic Hijri era are all era systems.
- BiDi: Bidirectional text rendering. Arabic and Hebrew text flows right-to-left, but embedded numbers and Latin text flow left-to-right within the same line.
- Temporal: The TC39 proposal (Stage 3 as of 2025) that adds calendar-aware date types to JavaScript. When shipped, it will reduce the need for many calendar libraries.
Who Should Read the Full Survey#
- Developers building applications for Middle Eastern, East Asian, or South Asian markets – you need calendar system support beyond Gregorian.
- Teams localizing existing applications – understanding which problems
Intl.DateTimeFormatsolves natively vs. what requires libraries. - Architects choosing i18n infrastructure – evaluating ICU4X vs. Intl vs. Babel vs. date-fns for your tech stack.
- Product managers scoping i18n work – understanding the complexity spectrum from “just format dates” to “full non-Gregorian calendar support.”
The full survey covers specific libraries, their maturity, accuracy trade-offs, and strategic recommendations for each calendar system and use case.
S1: Rapid Discovery
S1: Rapid Discovery – Calendar Internationalization#
Methodology#
Rapid ecosystem scan focused on identifying all viable libraries for calendar internationalization across JavaScript and Python ecosystems. Emphasis on:
- Calendar systems supported (Hijri, Jalali, Hebrew, Chinese, Japanese, etc.)
- Accuracy model (astronomical vs. tabular vs. lookup table)
- Ecosystem maturity (GitHub activity, downloads, maintenance status)
- License model (MIT/permissive vs. restrictive)
- Whether the library handles formatting, computation, or both
Inclusion Criteria#
A library qualifies if it provides at least one of:
- Non-Gregorian calendar date conversion (Gregorian to/from another system)
- Locale-aware date formatting with non-Gregorian calendar support
- Calendar arithmetic in a non-Gregorian system (add months, find weekdays)
- Calendar-system-specific features (holidays, solar terms, prayer times)
Exclusion#
- General date libraries (Moment.js, Day.js, Luxon, date-fns core): These handle Gregorian dates with locale formatting. They are part of the Gregorian ecosystem, not calendar internationalization. Exception: date-fns locale packs are included for their locale formatting capabilities.
- Timezone libraries (covered in 1.224 Timezone Handling)
- Calendar UI libraries (covered in 1.221 JavaScript Calendar UI Libraries)
- Full i18n frameworks that happen to include date formatting (e.g., i18next): too broad; we focus on date/calendar-specific tools.
Candidate Discovery Sources#
- npm and PyPI registry searches
- GitHub topic searches (“hijri”, “jalali”, “lunar-calendar”, “hebrew-calendar”)
- Unicode consortium projects (ICU4X)
- TC39 proposals (Temporal)
- Regional developer communities (Iranian, Arabic, Chinese tech communities)
Libraries Evaluated#
| Library | Lang | Calendar Systems | Type | Stars | Downloads/wk | Maintained |
|---|---|---|---|---|---|---|
| Intl.DateTimeFormat | JS | 12+ systems | Built-in | N/A | N/A | Yes (browsers) |
| Temporal (proposal) | JS | 12+ systems | Upcoming built-in | N/A | N/A | Stage 3 |
| ICU4X | Rust/WASM | 20+ systems | Comprehensive | ~1,800 | N/A | Yes (Unicode) |
| hijri-converter | Python | Hijri | Computation | ~200 | ~5K | Yes |
| jdatetime | Python | Jalali | Computation + format | ~500 | ~15K | Yes |
| persiantools | Python | Jalali | Utilities | ~200 | ~3K | Yes |
| jalaali-js | JS | Jalali | Computation | ~700 | ~8K | Yes |
| hebcal | JS | Hebrew | Computation + holidays | ~300 | ~4K | Yes |
| lunardate | Python | Chinese lunar | Computation | ~150 | ~2K | Minimal |
| LunarCalendar | Python | Chinese lunar | Computation | ~100 | ~1K | Minimal |
| chinese-lunar-calendar | JS | Chinese lunar | Computation | ~50 | ~500 | Minimal |
| Babel | Python | Gregorian + locale | Formatting | ~8,500 | ~2M | Yes |
| @formatjs/intl | JS | Gregorian + locale | Formatting + ICU | ~14K | ~500K | Yes |
| date-fns | JS | Gregorian + locale | Formatting | ~34K | ~20M | Yes |
Layered Architecture#
Calendar internationalization is not a single problem with competing solutions. It is a stack of complementary layers:
Layer 4: Calendar-specific features (holidays, solar terms, prayer times)
hebcal, specialized APIs
Layer 3: Calendar arithmetic (add months, date ranges in non-Gregorian systems)
hijri-converter, jdatetime, jalaali-js, lunardate
Layer 2: Comprehensive i18n (full CLDR, all locales, all calendars)
ICU4X, Babel, @formatjs
Layer 1: Display formatting (convert dates to locale-appropriate text)
Intl.DateTimeFormat (free, native, 12+ calendars)Most projects need Layer 1 (always) + one or two Layer 3 libraries for their specific calendar systems. Layer 2 is for comprehensive i18n stacks. Layer 4 is for domain-specific features.
Sources#
- MDN Intl.DateTimeFormat – Accessed 2026-03-09
- TC39 Temporal Proposal – Accessed 2026-03-09
- ICU4X – Accessed 2026-03-09
- hijri-converter – Accessed 2026-03-09
- jdatetime – Accessed 2026-03-09
- jalaali-js – Accessed 2026-03-09
- hebcal – Accessed 2026-03-09
- lunardate – Accessed 2026-03-09
- Babel – Accessed 2026-03-09
- formatjs – Accessed 2026-03-09
- date-fns – Accessed 2026-03-09
- Unicode CLDR – Accessed 2026-03-09
CJK Calendar Libraries#
At a Glance#
Libraries for Chinese lunisolar calendar conversion, Japanese Imperial era dates, Korean date formatting, and CJK-specific calendar features like the 24 solar terms. The CJK calendar ecosystem spans three distinct needs: Chinese lunar dates, Japanese era formatting, and locale-specific display conventions.
Chinese Lunar Calendar#
The Chinese lunisolar calendar determines the dates of Chinese New Year, Mid-Autumn Festival, Qingming, Dragon Boat Festival, and other major holidays observed by 1.4+ billion Chinese speakers worldwide. It also defines the 24 solar terms (jieqi) that govern traditional agricultural practices.
Computational Approach#
All Chinese lunar calendar libraries use precomputed lookup tables rather than astronomical calculation. The Chinese calendar’s rules are based on astronomical observations (actual new moon times, actual solar longitude positions), making real-time computation complex. Libraries ship tables covering 1900-2100, derived from published astronomical data.
Critical limitation: Every library has a hard expiration at 2100. Dates beyond this range will fail or return incorrect results. This is acceptable for current applications but is a long-term architectural concern.
lunardate (Python)#
Package: lunardate on PyPI
GitHub: ~150 stars
Downloads: ~2,000/week on PyPI
License: MIT
Simple Python library for Chinese lunar-Gregorian conversion. Clean, minimal API.
Key capabilities:
- Gregorian to Chinese lunar conversion
- Chinese lunar to Gregorian conversion
- Leap month handling
- Date range: 1900-2100
Limitations: No solar terms, no festival names, no CJK numeral formatting. Pure date conversion only.
LunarCalendar (Python)#
Package: LunarCalendar on PyPI
GitHub: ~100 stars
Downloads: ~1,000/week on PyPI
License: MIT
Slightly more feature-rich than lunardate, with festival awareness.
Key capabilities:
- Gregorian-lunar conversion
- Chinese festival name lookup
- Leap month handling
- Date range: 1900-2100
chinese-lunar-calendar (JavaScript)#
Package: chinese-lunar-calendar on npm
GitHub: ~50 stars
Downloads: ~500/week
License: MIT
JavaScript equivalent of the Python lunar libraries. Lookup-table based conversion.
Key capabilities:
- Gregorian-lunar conversion
- Lunar month and day names
- Leap month detection
- Date range: 1900-2100
Japanese Imperial Era System#
Japan uses the Imperial era (gengo) system alongside Gregorian dates. The current era, Reiwa (令和), began May 1, 2019 with Emperor Naruhito’s accession. Previous eras: Heisei (1989-2019), Showa (1926-1989), Taisho (1912-1926), Meiji (1868-1912).
Library Support#
Japanese era formatting is well-handled by Intl.DateTimeFormat with
calendar: 'japanese'. This converts any date to era-based format:
“令和8年3月9日” for March 9, 2026.
No dedicated JavaScript or Python library is needed for Japanese era dates. The browser-native Intl API handles this comprehensively, including era name display in both kanji and romaji.
Edge case: New era transitions. When Reiwa was announced in 2019, browser vendors pushed ICU data updates within weeks. Future era changes will follow the same pattern – a brief period where browsers need updating.
Korean Date Formatting#
Korean date formatting follows a straightforward pattern: 년 (year), 월 (month), 일 (day). “2026년 3월 9일” is the standard format. Korea primarily uses the Gregorian calendar with Korean locale formatting.
Library support: Intl.DateTimeFormat with locale ko-KR handles Korean
date formatting natively. No dedicated library needed.
Korean also uses the Dangi calendar (similar to Chinese lunisolar) for traditional
contexts, supported by Intl as calendar: 'dangi'.
24 Solar Terms (Jieqi / 节气)#
The 24 solar terms divide the solar year into segments based on the Sun’s longitude. They are used for traditional agriculture, Chinese medicine, and cultural practices. Terms include Lichun (start of spring), Qingming (clear and bright), Dongzhi (winter solstice), etc.
Library support: Sparse. Most Chinese lunar calendar libraries do not compute
solar terms. Specialized libraries or astronomical calculation libraries are
needed. The ephem Python package (astronomical computation) can compute solar
longitudes from which terms are derived.
CJK Numeral Date Representations#
CJK dates can be written using native numerals:
- Chinese: 二〇二六年三月九日 (using Chinese numerals)
- Japanese: 令和八年三月九日 (using kanji numerals with era)
Intl.DateTimeFormat supports this via the numberingSystem option:
numberingSystem: 'hanidec'for Chinese decimal numeralsnumberingSystem: 'jpan'for Japanese numerals
Maturity Assessment#
| Library/API | Production Ready | Coverage | Maintained |
|---|---|---|---|
| Intl (japanese) | Yes | Era formatting | Yes (browser) |
| Intl (chinese/dangi) | Yes | Display formatting | Yes (browser) |
| Intl (ko-KR) | Yes | Korean formatting | Yes (browser) |
| lunardate | Yes | Lunar conversion | Minimal updates |
| LunarCalendar | Partial | Lunar + festivals | Minimal updates |
| chinese-lunar-calendar | Partial | Lunar conversion | Minimal updates |
Recommendation#
Japanese era dates: Use Intl.DateTimeFormat exclusively. No library needed.
Korean formatting: Use Intl.DateTimeFormat with ko-KR locale. No library needed.
Chinese lunar conversion: lunardate (Python) or chinese-lunar-calendar (JS)
for basic conversion. Be aware of the 2100 expiration.
Solar terms: No good library solution. Use astronomical computation (ephem) or precomputed tables for the 24 solar terms.
Sources#
- MDN Intl.DateTimeFormat – Accessed 2026-03-09
- lunardate – Accessed 2026-03-09
- LunarCalendar – Accessed 2026-03-09
- Chinese calendar Wikipedia – Accessed 2026-03-09
- Japanese era Wikipedia – Accessed 2026-03-09
Hebrew Calendar Libraries#
At a Glance#
The Hebrew calendar is a lunisolar system used for Jewish religious observances worldwide. It determines the dates of Shabbat, holidays (Rosh Hashanah, Yom Kippur, Passover, Sukkot, etc.), lifecycle events, and daily prayer times (zmanim). Unlike the Islamic calendar, the Hebrew calendar follows a fixed 19-year Metonic cycle with deterministic leap year rules, making algorithmic computation reliable.
Why Hebrew Calendar is Unique#
The Hebrew calendar has several features that make it computationally interesting:
- Variable month count: Regular years have 12 months; leap years have 13 (an extra month of Adar I is inserted).
- Variable month lengths: Cheshvan can be 29 or 30 days; Kislev can be 29 or 30 days. This creates three year types: deficient (353/383 days), regular (354/384), and complete (355/385).
- Postponement rules (dehiyot): Rosh Hashanah (the new year) cannot fall on Sunday, Wednesday, or Friday. When it would, it is postponed by 1-2 days.
- Holiday dependencies: Many holidays are computed relative to other dates (e.g., Passover is always 15 Nisan, but Nisan’s start depends on the year type).
hebcal (JavaScript)#
Package: @hebcal/core on npm (plus @hebcal/hdate, @hebcal/leyning)
GitHub: ~300 stars across org, actively maintained
Downloads: ~4,000/week on npm
License: GPL-2.0 (core), some packages BSD
The most comprehensive Hebrew calendar library in any language. Maintained by the Hebcal project, which has provided Hebrew date services since 1994.
Key capabilities:
- Hebrew-Gregorian bidirectional conversion
- Full Hebrew calendar arithmetic
- Holiday and fast day computation (all major and minor holidays)
- Shabbat candle-lighting and havdalah times (location-aware)
- Zmanim (halachic prayer times) computation
- Torah reading schedule (parashat hashavua, leyning)
- Daf Yomi (daily Talmud study) tracking
- Hebrew month and day name localization
Unique features: hebcal goes far beyond date conversion. It is a complete Jewish liturgical calendar engine that computes location-dependent prayer times, holiday observance rules (including diaspora vs. Israel differences), and the full cycle of Jewish religious life.
License note: The core package is GPL-2.0, which may be problematic for proprietary applications. Some utility packages use BSD licensing. Check the specific package license before integrating.
Intl.DateTimeFormat with Hebrew Calendar (JavaScript)#
The browser-native approach supports the Hebrew calendar:
calendar: 'hebrew' formats dates in the Hebrew calendar system. This covers
display formatting (month names, year numbers, day numbers) but not holiday
computation, zmanim, or any religious calendar features.
Suitable for: displaying “9 Adar 5786” instead of “March 9, 2026” – nothing more.
Python Options#
The Python ecosystem for Hebrew calendar support is thinner:
- hebrew-date: Basic Hebrew date class. Limited functionality compared to hebcal.
- pyluach: Hebrew-Gregorian conversion with holiday awareness. Smaller community but clean API.
- hdate: Basic Hebrew date computation. Minimal maintenance.
None of these approach hebcal’s comprehensiveness for religious calendar features. For Python applications needing full Hebrew calendar support, calling hebcal via subprocess or building a microservice is sometimes the pragmatic choice.
Maturity Assessment#
| Library | Production Ready | Scope | License | Maintained |
|---|---|---|---|---|
| hebcal (JS) | Yes | Full religious calendar | GPL-2.0 | Active (since 1994) |
| Intl (hebrew) | Yes | Display formatting only | N/A (built-in) | Yes |
| pyluach | Partial | Dates + holidays | AGPL-3.0 | Active |
| hebrew-date | Partial | Basic dates | MIT | Sporadic |
Recommendation#
JavaScript: hebcal for any application with religious calendar features
(holidays, zmanim, Torah readings). Intl.DateTimeFormat for simple date display.
Python: pyluach for basic Hebrew date handling. Consider hebcal via
JavaScript interop for comprehensive features.
License warning: Both hebcal (GPL-2.0) and pyluach (AGPL-3.0) use copyleft licenses. Proprietary applications must evaluate license compatibility or use Intl.DateTimeFormat (display only) + custom computation.
Sources#
- hebcal – Accessed 2026-03-09
- Hebcal Interactive Jewish Calendar – Accessed 2026-03-09
- pyluach – Accessed 2026-03-09
- Hebrew Calendar Wikipedia – Accessed 2026-03-09
Islamic/Hijri Calendar Libraries#
At a Glance#
Libraries for converting between Gregorian and Islamic (Hijri) calendar dates, performing Hijri date arithmetic, and handling the fundamental complexity that the Islamic calendar has multiple calculation methods that can differ by 1-2 days.
The Accuracy Challenge#
The Islamic calendar is observation-based: months begin when the new crescent moon is sighted by a qualified observer. This means the “correct” date on any given day can differ between Saudi Arabia, Turkey, Morocco, and Indonesia. Libraries must choose a calculation method:
- Umm al-Qura: Saudi Arabia’s official tabular calendar, precomputed by the Institute of Astronomical and Geophysical Research. The most widely used algorithmic approximation. Used by most government systems.
- Astronomical: Based on moon phase calculations. More scientifically precise but does not match any single country’s official calendar.
- Tabular (civil): A simplified mathematical model with fixed rules for month lengths. Fast to compute but less accurate than Umm al-Qura.
- Sighting-based: Cannot be precomputed. Requires real-time input from religious authorities. No library can fully handle this.
hijri-converter (Python)#
Package: hijri-converter on PyPI
GitHub: ~200 stars, actively maintained
Downloads: ~5,000/week on PyPI
License: MIT
The most reliable Python library for Hijri-Gregorian conversion. Uses the Umm al-Qura calendar by default (covering 1356-1500 AH / 1937-2076 CE). Also supports algorithmic Hijri calculation for dates outside the Umm al-Qura range.
Key capabilities:
- Gregorian to Hijri and Hijri to Gregorian conversion
- Hijri date arithmetic (add/subtract days)
- Month and day name localization (Arabic and English)
- Validation of Hijri dates
Limitations:
- No prayer time computation
- No holiday awareness
- Limited to Umm al-Qura and algorithmic methods (no sighting-based)
- Python only
Intl.DateTimeFormat with Islamic Calendars (JavaScript)#
The browser-native approach supports three Islamic calendar variants:
islamic: Algorithmic Islamic calendarislamic-umalqura: Umm al-Qura calendar (Saudi)islamic-civil: Tabular/civil Islamic calendar
This covers display formatting but not date arithmetic. To add 3 Hijri months in JavaScript, you would need either Temporal (when shipped) or a dedicated library.
Other Hijri Libraries (npm)#
Several npm packages exist for Hijri date handling, but the ecosystem is fragmented:
- hijri-date: Small package, basic conversion. Low download count, sporadic maintenance.
- moment-hijri: Moment.js plugin for Hijri. Functional but tied to the deprecated Moment.js ecosystem.
- hijri-js: Lightweight conversion utility. Minimal maintenance.
None of these approach the reliability of hijri-converter (Python) or the convenience of Intl.DateTimeFormat (JS). The JavaScript Hijri ecosystem lacks a single authoritative library.
Maturity Assessment#
| Library | Production Ready | Accuracy Model | Maintained |
|---|---|---|---|
| hijri-converter | Yes | Umm al-Qura + algorithmic | Active |
| Intl (islamic-umalqura) | Yes | Umm al-Qura (via ICU) | Yes (browser) |
| moment-hijri | Legacy | Algorithmic | No (deprecated) |
| hijri-date | No | Basic algorithmic | Sporadic |
Recommendation#
For Python server-side: hijri-converter is the clear choice. Well-tested,
Umm al-Qura based, actively maintained.
For JavaScript display: Intl.DateTimeFormat with calendar: 'islamic-umalqura'
covers formatting needs with zero bundle cost.
For JavaScript arithmetic: Wait for Temporal API or use ICU4X WASM bindings. The npm Hijri ecosystem is too fragmented for confident recommendation.
Sources#
- hijri-converter – Accessed 2026-03-09
- Umm al-Qura Calendar – Accessed 2026-03-09
- MDN Intl.DateTimeFormat calendar option – Accessed 2026-03-09
Intl.DateTimeFormat (Browser/Node.js Built-in)#
At a Glance#
The browser-native API for locale-aware date formatting. Part of the ECMAScript Internationalization API (ECMA-402), backed by ICU data compiled into every modern browser and Node.js runtime. Zero bundle cost, zero dependencies, 12+ calendar systems supported.
Ecosystem Position#
Intl.DateTimeFormat is not a library – it is a platform API. Every modern browser (Chrome, Firefox, Safari, Edge) and Node.js 13+ ships it with full ICU data. This means there is nothing to install, nothing to bundle, and nothing to maintain. It is the single most important tool for calendar internationalization.
Calendar Systems Supported#
Intl.DateTimeFormat supports specifying a calendar system via the calendar option
or the -u-ca- Unicode extension in the locale string:
| Calendar Key | System | Example Output |
|---|---|---|
gregory | Gregorian (default) | March 9, 2026 |
islamic | Islamic (algorithmic) | 9 Sha’ban 1447 |
islamic-umalqura | Islamic (Umm al-Qura) | 9 Sha’ban 1447 |
islamic-civil | Islamic (tabular) | 9 Sha’ban 1447 |
persian | Persian/Jalali | 18 Esfand 1404 |
hebrew | Hebrew | 9 Adar 5786 |
chinese | Chinese lunisolar | … |
japanese | Japanese Imperial | Reiwa 8, March 9 |
buddhist | Thai Buddhist | March 9, 2569 |
coptic | Coptic | 30 Amshir 1742 |
ethiopic | Ethiopian | 30 Yekatit 2018 |
indian | Indian National (Saka) | 18 Phalguna 1947 |
roc | Republic of China | March 9, 115 |
Key Capabilities#
Formatting: Converts any JavaScript Date object (or Temporal object, when available) to locale-appropriate text in any supported calendar system. Supports full customization of date/time components (era, year, month, day, weekday, hour, minute, second), number systems (latn, arab, hans, etc.), and date styles (full, long, medium, short).
Locale negotiation: Automatically falls back to best-match locale when an exact match is unavailable. Handles regional variants (ar-SA vs ar-EG, zh-TW vs zh-CN).
Number systems: Can output dates with native numerals (Arabic-Indic digits for
Persian, Chinese numerals for Chinese calendar, etc.) via the numberingSystem
option.
What It Does NOT Do#
- No calendar arithmetic: Cannot add 3 Hijri months to a date or compute the next Persian New Year. It only formats existing Date objects.
- No date parsing: Cannot parse “18 اسفند ۱۴۰۴” back into a Date object.
- No holiday computation: Cannot determine if a date is Eid, Nowruz, or Rosh Hashanah.
- No prayer times or astronomical data: Purely a formatting API.
- No server-side without V8/JSC: Not available in Python, Ruby, or Go without embedding a JS runtime or using ICU bindings directly.
Maturity Indicators#
- Standardized in ECMA-402, stable since 2012, continuously updated
- Backed by ICU (International Components for Unicode), maintained by the Unicode Consortium with contributions from Google, Apple, Microsoft, and Mozilla
- Calendar data sourced from CLDR, updated twice yearly
- 100% browser support in evergreen browsers (Can I Use: 97%+ global coverage)
- No maintenance burden on application developers
Why Start Here#
Every calendar internationalization project should begin with Intl.DateTimeFormat because it is free, native, and covers the most common use case (display formatting) for the broadest set of calendar systems. Only add dedicated libraries when you need capabilities Intl cannot provide: calendar arithmetic, holiday computation, date parsing, or server-side computation in non-JS languages.
Sources#
- MDN Intl.DateTimeFormat – Accessed 2026-03-09
- ECMA-402 Specification – Accessed 2026-03-09
- Can I Use: Intl.DateTimeFormat – Accessed 2026-03-09
- Unicode CLDR Calendar Data – Accessed 2026-03-09
Locale-Aware Date Formatting Libraries#
At a Glance#
Libraries that format dates according to locale conventions: month/day order, separator characters, number systems, and calendar system integration. This covers the Layer 2 “comprehensive i18n” tools that sit between raw Intl.DateTimeFormat and calendar-specific computation libraries.
Babel (Python)#
Package: Babel on PyPI
GitHub: ~8,500 stars, actively maintained by Pallets project
Downloads: ~2,000,000/week on PyPI
License: BSD-3-Clause
The definitive Python library for locale-aware formatting. Consumes CLDR data directly and provides comprehensive locale support for dates, times, numbers, currencies, and more.
Key capabilities:
- Date/time formatting with 600+ locales
- CLDR-based locale data (updated with each CLDR release)
- Timezone-aware formatting
- Relative time expressions (“3 days ago” in any locale)
- Number and currency formatting
- Plural rules and list formatting
Calendar support: Babel formats Gregorian dates in any locale. It does not support non-Gregorian calendar systems for arithmetic – you must convert to Gregorian first, then format with Babel. However, Babel’s locale data includes month names and patterns for many calendar systems via CLDR.
Install note: Babel ships ~30 MB of CLDR locale data. This is a one-time install cost, not a runtime cost.
@formatjs/intl (JavaScript)#
Package: @formatjs/intl on npm (umbrella for react-intl, intl-messageformat)
GitHub: ~14,000 stars, actively maintained
Downloads: ~500,000/week on npm
License: MIT
The JavaScript implementation of ICU MessageFormat. Primarily used for UI string internationalization but includes date/time formatting capabilities that build on top of Intl.DateTimeFormat.
Key capabilities:
- ICU MessageFormat syntax for complex i18n strings
- Date/time formatting via Intl.DateTimeFormat (inherits all calendar support)
- Relative time formatting (“in 3 days” localized)
- Number and currency formatting
- React integration via react-intl
- Plural rules, select expressions
Calendar relevance: @formatjs delegates date formatting to Intl.DateTimeFormat, so it inherits all 12+ calendar systems. Its value-add is in composing formatted dates into larger localized strings using ICU MessageFormat patterns.
date-fns Locale Packs (JavaScript)#
Package: date-fns on npm
GitHub: ~34,000 stars, actively maintained
Downloads: ~20,000,000/week on npm
License: MIT
The most popular modular date utility library for JavaScript. Provides locale packs for locale-aware Gregorian date formatting.
Key capabilities:
- 80+ locale packs, tree-shakeable (~1 KB per locale)
- Locale-aware
format(),formatDistance(),formatRelative() - Custom format patterns with locale tokens
- Functional API (each function is a separate import)
Calendar limitation: date-fns only handles the Gregorian calendar. It has no
non-Gregorian calendar support. However, the date-fns-jalali fork adds Jalali
support, demonstrating how the modular architecture enables calendar extensions.
When to choose: When you need Gregorian date formatting with clean locale support and want tree-shaking. Not for non-Gregorian calendars.
ICU4X (Rust/WASM)#
Package: icu4x on crates.io, WASM bindings available
GitHub: ~1,800 stars, actively maintained by Unicode Consortium
License: Unicode License (permissive, MIT-compatible)
The next-generation internationalization library from the Unicode Consortium. Written in Rust with WASM, C, and C++ bindings. Designed to replace legacy ICU (C/C++) for resource-constrained environments.
Key capabilities:
- 20+ calendar systems (more than any other library)
- Full CLDR locale data in compact binary format
- Date/time formatting across all supported calendars
- Timezone handling
- Collation, normalization, segmentation
- ~200 KB WASM binary for full calendar + formatting support
Calendar systems: Supports Buddhist, Chinese, Coptic, Dangi, Ethiopian, Ethiopic (Amete Alem), Gregorian, Hebrew, Indian, Islamic (civil, observational, tabular, Umm al-Qura), ISO, Japanese, Japanese extended, Persian, and ROC calendars.
When to choose: When you need comprehensive calendar support outside a browser environment (edge computing, embedded, WASM runtimes, server-side Rust). Or when you need the broadest calendar system coverage available.
Maturity: Production-ready as of v1.5. Backed by the Unicode Consortium with funding from Google, Amazon, and Mozilla. Long-term viability is strong.
Temporal API (TC39 Stage 3)#
Not a library but an upcoming JavaScript built-in that will significantly change the landscape. Temporal adds calendar-aware date types to JavaScript:
Temporal.PlainDatewith calendar annotations- Calendar-aware arithmetic (add 3 Hijri months)
- All ICU-supported calendars available natively
- No library needed for basic calendar arithmetic
Status: Stage 3 (as of 2025), shipping behind flags in some browsers. Expected to reach Stage 4 and broad availability in 2026-2027.
Impact: When Temporal ships, many calendar-specific arithmetic libraries become less necessary. Display formatting (Intl) + arithmetic (Temporal) cover most needs. Specialized features (holidays, solar terms, prayer times) still require libraries.
Comparison Matrix#
| Library | Lang | Calendars | Arithmetic | Formatting | Bundle |
|---|---|---|---|---|---|
| Intl.DateTimeFormat | JS | 12+ | No | Yes | 0 KB |
| Temporal | JS | 12+ | Yes | Via Intl | 0 KB (native) |
| ICU4X | Rust/WASM | 20+ | Yes | Yes | ~200 KB |
| Babel | Python | Gregorian* | No | Yes | ~30 MB install |
| @formatjs | JS | Via Intl | No | Yes | ~15 KB |
| date-fns | JS | Gregorian | Yes | Yes | ~1 KB/locale |
*Babel includes CLDR calendar data but doesn’t expose non-Gregorian arithmetic.
Sources#
- Babel – Accessed 2026-03-09
- formatjs – Accessed 2026-03-09
- date-fns – Accessed 2026-03-09
- ICU4X – Accessed 2026-03-09
- TC39 Temporal – Accessed 2026-03-09
- Unicode CLDR – Accessed 2026-03-09
Other Calendar Systems: Thai Buddhist, Ethiopian, Coptic, Indian#
At a Glance#
Calendar systems that are actively used by significant populations but have limited dedicated library ecosystems. For these systems, the browser-native Intl.DateTimeFormat (and eventually Temporal) provides the primary library-free path, with ICU4X as the comprehensive cross-platform alternative.
Thai Buddhist Calendar#
Users: ~70 million (Thailand) System: Gregorian structure with Buddhist Era year numbering. 2026 CE = 2569 BE. Usage: All Thai government documents, official forms, national IDs. The Thai civil calendar is structurally identical to Gregorian except for the year offset.
Library Support#
Intl.DateTimeFormat: calendar: 'buddhist' or locale th-TH-u-ca-buddhist.
Fully supported in all modern browsers. Outputs dates with Buddhist Era year
numbering and Thai month names.
Dedicated libraries: None of significance. Because the Buddhist calendar is a simple year offset from Gregorian (add 543 years), no computation library is needed. Any date library can handle this with a trivial transformation.
Recommendation: Intl.DateTimeFormat exclusively. No library needed.
Ethiopian Calendar#
Users: ~120 million (Ethiopia, Eritrea) System: Solar calendar with 13 months (12 months of 30 days + 1 month of 5-6 days). Currently 7-8 years behind Gregorian. Based on the Coptic calendar with different era counting.
Library Support#
Intl.DateTimeFormat: calendar: 'ethiopic' is supported. Handles display
formatting including month names (Meskerem, Tikimt, Hidar, etc.) and era display.
Dedicated libraries: Very sparse.
- ethiopian-calendar (npm): Small package for Ethiopian-Gregorian conversion. Minimal downloads, sporadic maintenance.
- Ethiopian Date (various npm packages): Several attempts, none with significant adoption.
- Python: No notable dedicated library on PyPI.
Gap: The Ethiopian developer community has not yet produced a production-grade calendar library comparable to jdatetime (Persian) or hebcal (Hebrew). This is a significant ecosystem gap given the population size.
Recommendation: Intl.DateTimeFormat for display formatting. For arithmetic, use ICU4X (supports ethiopic) or implement conversion manually (the algorithm is well-documented and relatively simple due to the fixed month-length structure).
Coptic Calendar#
Users: ~15-20 million (Coptic Christians in Egypt) System: Solar calendar structurally identical to Ethiopian but with different era counting (Coptic era starts from the Era of Martyrs, 284 CE).
Library Support#
Intl.DateTimeFormat: calendar: 'coptic' is supported.
Dedicated libraries: Essentially none. The Coptic calendar is structurally identical to Ethiopian with a year offset, so Ethiopian conversion libraries work with minor adjustments.
Recommendation: Intl.DateTimeFormat for display. Manual conversion or ICU4X for arithmetic. The small user base and structural simplicity (fixed month lengths) make dedicated libraries unnecessary.
Indian National Calendar (Saka)#
Users: Officially adopted by India (1.4 billion population), though the Gregorian calendar dominates in practice. The Saka calendar appears on official government gazettes and publications alongside Gregorian dates.
System: Solar calendar starting from the Saka Era (78 CE). Months follow the traditional Indian names (Chaitra, Vaishakha, etc.). Structurally tied to the vernal equinox.
Library Support#
Intl.DateTimeFormat: calendar: 'indian' is supported. Outputs dates with
Saka era year and Indian month names.
Dedicated libraries: Minimal.
- No notable npm or PyPI packages focused on Indian National Calendar computation.
- Hindu religious calendar libraries exist for panchang (almanac) computation, but these serve a different purpose (lunar tithis, nakshatras) and are not the same as the Indian National Calendar.
Gap: Despite India’s enormous developer population, the Indian National Calendar has poor library support. This reflects the practical reality that most Indian software uses Gregorian dates, with the national calendar appearing primarily in government contexts.
Recommendation: Intl.DateTimeFormat for display. The Indian National Calendar’s structure (known month lengths with a leap day rule) makes manual conversion straightforward.
Maturity Summary#
| Calendar | Intl Support | Dedicated Libraries | Recommended Path |
|---|---|---|---|
| Thai Buddhist | Yes | None needed | Intl (year offset) |
| Ethiopian | Yes | Sparse, immature | Intl + ICU4X |
| Coptic | Yes | Essentially none | Intl + ICU4X |
| Indian (Saka) | Yes | Minimal | Intl + manual |
The Pattern#
For calendar systems without strong dedicated library ecosystems, Intl.DateTimeFormat provides adequate display formatting. The gap is in arithmetic and computation – adding months, finding holidays, computing religious dates. ICU4X fills this gap comprehensively but requires WASM infrastructure. The Temporal API (when shipped) will fill it natively in JavaScript.
The calendar systems with the best library ecosystems (Persian, Hebrew, Chinese lunar) are the ones where large developer communities have a daily practical need for non-Gregorian dates. Calendar systems used primarily in government contexts (Indian, Thai) or by smaller developer communities (Ethiopian, Coptic) have weaker ecosystems.
Sources#
- MDN Intl.DateTimeFormat – Accessed 2026-03-09
- Ethiopian Calendar Wikipedia – Accessed 2026-03-09
- Indian National Calendar Wikipedia – Accessed 2026-03-09
- ICU4X calendar documentation – Accessed 2026-03-09
Persian/Jalali Calendar Libraries#
At a Glance#
The Persian Solar Hijri (Jalali/Shamsi) calendar is the official civil calendar of Iran and Afghanistan. Unlike the Islamic lunar Hijri calendar, it is solar-based and astronomically precise – years start at the vernal equinox (Nowruz, around March 20-21). This precision makes algorithmic computation straightforward, and the large Iranian tech community has produced the most mature non-Gregorian calendar libraries in both Python and JavaScript.
Why Jalali is Special in This Survey#
The Jalali ecosystem is a model for what other non-Gregorian calendar libraries could be. Both jdatetime (Python) and jalaali-js (JavaScript) are:
- Well-tested with comprehensive test suites
- Actively maintained for years
- Used in production by major Iranian applications
- Clean API designs that mirror standard datetime interfaces
- Properly documented
This maturity stems from practical necessity: 90 million Iranians use Jalali dates daily, and Iranian developers build software in both Python and JavaScript.
jdatetime (Python)#
Package: jdatetime on PyPI
GitHub: ~500 stars, actively maintained
Downloads: ~15,000/week on PyPI
License: Python Software Foundation License
A drop-in replacement for Python’s datetime module. Provides jdatetime.date,
jdatetime.datetime, and jdatetime.time classes that mirror the stdlib API but
operate in the Jalali calendar system.
Key capabilities:
- Full Jalali date arithmetic (add/subtract days, months, years)
strftime/strptimewith Jalali-aware format codes- Gregorian-Jalali bidirectional conversion
- Locale support (Persian and English month/day names)
- Django integration (JalaliDateField, JalaliDateTimeField)
Why it works: Mirrors the stdlib datetime API exactly, so developers who know Python’s datetime module can use jdatetime with zero learning curve. The API familiarity is its strongest feature.
persiantools (Python)#
Package: persiantools on PyPI
GitHub: ~200 stars, actively maintained
Downloads: ~3,000/week on PyPI
License: MIT
A broader Persian utilities library that includes Jalali date handling alongside Persian number conversion, character normalization, and phone number validation.
Key capabilities:
- Jalali-Gregorian conversion
- Persian digit conversion (۱۲۳ <-> 123)
- Persian character normalization (Arabic Kaf/Yeh to Persian)
- Phone number validation (Iranian formats)
When to choose: If you need Persian text utilities beyond just dates. If you only need dates, jdatetime is more focused and more mature.
jalaali-js (JavaScript)#
Package: jalaali-js on npm
GitHub: ~700 stars, actively maintained
Downloads: ~8,000/week on npm
License: MIT
The definitive JavaScript library for Jalali calendar conversion. Pure JavaScript, zero dependencies, ~2 KB minified. Provides low-level conversion functions that other libraries build upon.
Key capabilities:
- Gregorian to Jalali and Jalali to Gregorian conversion
- Jalali leap year detection
- Month length calculation
- Day-of-year computation
- Julian Day Number conversion (intermediate astronomical representation)
Design philosophy: Functional, stateless API. No date objects, no formatting – just pure conversion functions. Higher-level libraries (jalali-moment, date-fns-jalali) build formatting and parsing on top of jalaali-js.
Higher-Level JavaScript Options#
- jalali-moment: Moment.js wrapper with Jalali support. Full formatting and parsing. Tied to deprecated Moment.js.
- date-fns-jalali: Fork of date-fns with Jalali support. Modern, tree-shakeable, but maintained separately from upstream date-fns.
Maturity Assessment#
| Library | Production Ready | API Style | Bundle/Install | Maintained |
|---|---|---|---|---|
| jdatetime | Yes | OOP (mirrors stdlib) | Pure Python | Active |
| persiantools | Yes | Mixed utilities | Pure Python | Active |
| jalaali-js | Yes | Functional | ~2 KB, zero deps | Active |
| jalali-moment | Legacy | OOP (Moment-style) | ~300 KB (Moment) | Maintenance mode |
| date-fns-jalali | Yes | Functional | Tree-shakeable | Active |
Recommendation#
Python: jdatetime is the default choice. Production-proven, stdlib-compatible API,
Django integration.
JavaScript (conversion): jalaali-js for pure conversion. Tiny, reliable, zero
dependencies.
JavaScript (formatting): Intl.DateTimeFormat with calendar: 'persian' for
display. Use date-fns-jalali if you need date-fns-style utility functions.
Sources#
- jdatetime – Accessed 2026-03-09
- persiantools – Accessed 2026-03-09
- jalaali-js – Accessed 2026-03-09
- Jalali Calendar Algorithm (Jalaali) – Accessed 2026-03-09
S1 Recommendation: Calendar Internationalization#
Tier Ranking#
Tier 1: Start Here (Every Project)#
Intl.DateTimeFormat – Zero-cost display formatting for 12+ calendar systems. If your need is “show dates in the user’s calendar system,” this is the answer. No library to install, no bundle cost, no maintenance burden.
Tier 2: Add as Needed (Calendar-Specific Arithmetic)#
jdatetime (Python, Jalali) – Production-grade. Best non-Gregorian calendar library available. Use for Iranian/Afghan applications.
jalaali-js (JS, Jalali) – Tiny, reliable, zero dependencies. The JavaScript companion to jdatetime for Persian calendar conversion.
hijri-converter (Python, Hijri) – Umm al-Qura based. The only reliable Hijri computation library for Python.
hebcal (JS, Hebrew) – Goes beyond dates into full religious calendar features. Essential for Jewish religious applications. GPL-2.0 license requires evaluation.
Tier 3: Specialized Use Cases#
ICU4X (Rust/WASM) – Broadest calendar coverage (20+ systems) in a portable binary. Use when Intl is unavailable or when you need comprehensive cross-platform coverage.
Babel (Python) – Comprehensive locale formatting. Use when you need localized date strings in Python with full CLDR support.
@formatjs/intl (JS) – ICU MessageFormat for composing formatted dates into localized strings. Use in React/JS applications with complex i18n needs.
lunardate / chinese-lunar-calendar – Chinese lunar conversion. Use for applications computing Chinese festival dates. Be aware of 2100 expiration.
Tier 4: Watch (Not Yet Ready for Default Recommendation)#
Temporal API – When shipped (2026-2027), will provide native calendar-aware arithmetic in JavaScript. Will reduce the need for many Tier 2 libraries.
date-fns-jalali – Good for teams already using date-fns who need Jalali support. Not the default recommendation because jalaali-js is lighter and more focused.
Key Decision Framework#
Q1: Do you only need to DISPLAY dates in non-Gregorian calendars?
→ Yes: Intl.DateTimeFormat only. Done.
→ No: Continue to Q2.
Q2: Do you need to COMPUTE dates (add months, find holidays)?
→ Yes: Add a calendar-specific library:
- Hijri → hijri-converter (Python) or wait for Temporal (JS)
- Jalali → jdatetime (Python) or jalaali-js (JS)
- Hebrew → hebcal (JS)
- Chinese lunar → lunardate (Python) or chinese-lunar-calendar (JS)
→ No: Continue to Q3.
Q3: Do you need calendar support outside a browser?
→ Yes: ICU4X (broadest coverage) or Babel (Python locales)
→ No: Intl.DateTimeFormat covers you.Proceed to S2#
The following libraries warrant deep technical analysis in S2:
- Intl.DateTimeFormat + Temporal – architecture, calendar system internals
- hijri-converter – accuracy models, Umm al-Qura vs. astronomical
- jdatetime / jalaali-js – architecture, the Jalaali algorithm
- ICU4X – WASM integration, data size, calendar coverage
- RTL layout – CSS strategies for right-to-left calendar rendering
- CJK date systems – solar terms, era systems, numeral conventions
S2: Comprehensive
S2: Comprehensive Analysis – Calendar Internationalization#
Methodology#
Deep technical analysis of the top-tier calendar internationalization tools identified in S1. Focus areas:
- Architecture: How each library represents and converts calendar dates internally. Algorithm choice, data model, extensibility.
- Accuracy: Comparison of calculation methods, edge cases, known discrepancies between libraries and real-world calendars.
- Data models: How CLDR data flows from Unicode through ICU to browsers and libraries. The data supply chain for calendar internationalization.
- RTL layout: Technical strategies for right-to-left calendar rendering, CSS logical properties, BiDi text handling.
- CJK specifics: Solar term computation, era system boundaries, numeral conventions.
Sources#
Primary sources are official documentation, source code, CLDR data files, and Unicode technical standards. All accessed March 2026.
- ECMA-402 Specification – Intl.DateTimeFormat
- TC39 Temporal Proposal – Calendar-aware dates
- ICU4X Documentation – Calendar implementations
- Unicode CLDR – Locale data repository
- hijri-converter source – Hijri algorithms
- jalaali-js source – Jalaali algorithm
- hebcal source – Hebrew calendar algorithms
- CSS Logical Properties – RTL layout
CJK Date Systems: Deep Technical Analysis#
Overview#
CJK (Chinese, Japanese, Korean) date handling encompasses several distinct technical challenges: the Chinese lunisolar calendar with its 24 solar terms, the Japanese Imperial era system with its irregular era boundaries, Korean locale formatting, and CJK numeral representations. Each has different library implications.
Chinese Lunisolar Calendar: Architecture#
The Lookup Table Approach#
Every Chinese lunar calendar library – without exception – uses precomputed lookup tables rather than astronomical calculation. Understanding why reveals an important architectural constraint.
The Chinese calendar defines months by actual astronomical new moons (conjunctions) and defines the year structure by the positions of major solar terms. Computing these precisely requires:
Lunar conjunction times: The exact moment of each new moon, accounting for the complex gravitational interactions between Earth, Moon, and Sun. This is not a simple periodic calculation – lunar month lengths vary between 29.27 and 29.83 days due to orbital eccentricities.
Solar longitude positions: The Sun’s ecliptic longitude at specific moments, used to determine which month is the intercalary (leap) month. Major solar terms occur when the Sun reaches multiples of 30 degrees longitude.
Timezone considerations: The Chinese calendar is computed for Beijing time (UTC+8). A new moon occurring at 23:50 UTC (07:50 the next day in Beijing) starts a new month on the Beijing-time date, not the UTC date.
Computing all of this from first principles requires an astronomical library (like VSOP87 for solar position and ELP/MPP for lunar position) with millisecond accuracy. The computational cost is non-trivial, and the algorithms are complex.
The pragmatic solution: Precompute all new moon times and solar term positions for a fixed date range, encode the results as a compact lookup table, and ship the table with the library.
Table Structure#
Most Chinese lunar calendar libraries encode data as a bitmask per year:
- Bits 0-11: Month lengths for months 1-12 (0 = 29 days, 1 = 30 days)
- Bits 12-15: Which month is the leap month (0 = no leap month)
- Additional data: Leap month length
This encodes an entire year’s calendar structure in 16-20 bits (~2-3 bytes per year). A 200-year table (1900-2100) is ~400-600 bytes – trivially small.
The 2100 Problem#
All current libraries cover 1900-2100. Extending beyond 2100 requires either:
- Computing new tables: Running astronomical algorithms to generate conjunction and solar term data for 2100-2200+
- Updating existing tables: Libraries publishing new releases with extended tables
This is a known, manageable problem – not a crisis. But it means every Chinese lunar calendar library has a built-in expiration. Applications planning for dates beyond 2100 (rare outside financial and astronomical contexts) need to be aware.
Solar Terms (Jieqi / 节气)#
The 24 solar terms divide the tropical year into 24 segments of approximately 15.22 days each, based on the Sun’s ecliptic longitude:
| # | Name (Pinyin) | Chinese | Solar Longitude | Approximate Date |
|---|---|---|---|---|
| 1 | Lichun | 立春 | 315° | Feb 3-5 |
| 2 | Yushui | 雨水 | 330° | Feb 18-20 |
| 3 | Jingzhe | 惊蛰 | 345° | Mar 5-7 |
| 4 | Chunfen | 春分 | 0° (equinox) | Mar 20-22 |
| 5 | Qingming | 清明 | 15° | Apr 4-6 |
| 6 | Guyu | 谷雨 | 30° | Apr 19-21 |
| … | … | … | … | … |
| 22 | Dongzhi | 冬至 | 270° (solstice) | Dec 21-23 |
| 23 | Xiaohan | 小寒 | 285° | Jan 5-7 |
| 24 | Dahan | 大寒 | 300° | Jan 20-21 |
Library support for solar terms: Poor. Most Chinese lunar calendar libraries do not compute solar terms. To get solar term dates, you need either:
- Precomputed tables (some Chinese calendar websites publish these)
- An astronomical library (Python
ephemorskyfield) to compute solar longitudes - ICU4X, which includes some solar term data in its Chinese calendar implementation
Japanese Imperial Era System#
Era Boundaries#
The Japanese era (gengo) system counts years from the accession of each emperor:
| Era | Kanji | Start Date | End Date |
|---|---|---|---|
| Meiji | 明治 | 1868-01-25 | 1912-07-30 |
| Taisho | 大正 | 1912-07-30 | 1926-12-25 |
| Showa | 昭和 | 1926-12-25 | 1989-01-07 |
| Heisei | 平成 | 1989-01-08 | 2019-04-30 |
| Reiwa | 令和 | 2019-05-01 | present |
Key architectural note: Era boundaries are not on January 1. A single Gregorian year can span two eras (e.g., January-April 2019 = Heisei 31, May-December 2019 = Reiwa 1). Libraries must handle intra-year era transitions.
Intl.DateTimeFormat Support#
The browser-native implementation handles Japanese eras comprehensively:
With calendar: 'japanese', Intl.DateTimeFormat produces era-prefixed dates.
Supported output patterns include:
- Full era name: 令和8年3月9日 (Reiwa 8, March 9)
- Abbreviated era: R8.3.9
- Narrow era: R8/3/9
Era name display: Intl supports both the kanji era name (令和) and the romanized form (Reiwa) depending on locale settings.
New Era Handling#
When Emperor Naruhito acceded in 2019, the era name “Reiwa” was:
- Announced April 1, 2019 (one month before accession)
- Added to Unicode CLDR
- Compiled into ICU updates
- Shipped in browser updates within 2-4 weeks
Future era transitions will follow the same pipeline. The political constraint is that Japan’s Imperial Household Agency announces era names shortly before (or simultaneously with) accession, giving software vendors a tight update window.
Defensive coding: Applications that format future Japanese dates should handle the possibility that a new era may be declared. Using Intl.DateTimeFormat ensures you inherit era updates from browser updates without code changes.
Korean Date Formatting#
Standard Format#
Korean dates follow a consistent pattern:
- Full: 2026년 3월 9일 월요일 (2026 year 3 month 9 day Monday)
- Medium: 2026. 3. 9.
- Short: 26. 3. 9.
The particle markers (년/월/일) are integral to the format, not optional suffixes.
Intl.DateTimeFormat with ko-KR locale handles these correctly.
Dangi Calendar#
Korea’s traditional lunisolar calendar (Dangi) is structurally similar to the
Chinese calendar. Intl.DateTimeFormat supports calendar: 'dangi' for display
formatting. Dangi month and day names differ slightly from Chinese equivalents.
Practical use is limited to traditional/cultural contexts. The vast majority of Korean applications use the Gregorian calendar with Korean locale formatting.
CJK Numeral Date Representations#
Number Systems via Intl#
Intl.DateTimeFormat supports multiple CJK number systems:
numberingSystem | Example | Use Case |
|---|---|---|
latn | 2026年3月9日 | Default (Latin digits) |
hanidec | 二〇二六年三月九日 | Chinese formal documents |
jpan | 二千二十六年三月九日 | Japanese formal writing |
hanidays | 三月九日 | Chinese traditional day |
When to use CJK numerals: Primarily in formal/traditional contexts. Modern digital applications in China, Japan, and Korea predominantly use Latin digits (0-9) for dates, even when the surrounding text is in CJK characters.
Fullwidth Digits#
CJK typography sometimes uses fullwidth Latin digits (0123) instead of halfwidth (0123) for visual consistency with CJK character widths. This is a font/CSS concern rather than a calendar library concern.
/* Force fullwidth digits in CJK contexts */
.date-display { font-variant-numeric: fullwidth; }Week Start Conventions#
| Country | Week Starts | Notes |
|---|---|---|
| China | Monday (or Sunday) | Monday official, Sunday common |
| Japan | Sunday | Traditional Sunday start |
| South Korea | Sunday | Traditional Sunday start |
| Taiwan | Sunday | Traditional Sunday start |
CLDR provides firstDay data per territory. Applications should use this rather
than hardcoding assumptions.
Recommendations#
Japanese era dates: Intl.DateTimeFormat with calendar: 'japanese'. No library
needed. Stay current with browser updates for era transitions.
Korean formatting: Intl.DateTimeFormat with ko-KR. No library needed.
Chinese lunar dates: Use lunardate (Python) or chinese-lunar-calendar (JS) for
festival date computation. Use Intl with calendar: 'chinese' for display.
Solar terms: No good library-only solution in 2026. Use the ephem or
skyfield Python packages for astronomical computation, or precomputed tables.
CJK numerals: Intl.DateTimeFormat handles this natively via numberingSystem.
Sources#
- ICU Japanese Calendar – Accessed 2026-03-09
- Chinese Calendar Algorithms – Accessed 2026-03-09
- 24 Solar Terms Wikipedia – Accessed 2026-03-09
- CLDR Territory Info – Accessed 2026-03-09
- Japanese Era Name Wikipedia – Accessed 2026-03-09
CLDR Data Pipeline: How Calendar Data Reaches Your Application#
Overview#
The Common Locale Data Repository (CLDR) is the single source of truth for internationalization data worldwide. Understanding how CLDR data flows from the Unicode Consortium to your application is essential for understanding why certain calendar systems work in certain environments and not others.
The Data Supply Chain#
Unicode Consortium (CLDR project)
↓ publishes twice/year (April + October)
↓
CLDR XML/JSON data files
↓ consumed by
↓
┌──────────┬──────────┬──────────┬──────────┐
│ ICU (C++) │ ICU4J │ ICU4X │ Direct │
│ │ (Java) │ (Rust) │ consumers│
└────┬─────┴────┬─────┴────┬─────┴────┬─────┘
↓ ↓ ↓ ↓
┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐
│ V8 │ │ JDK │ │ WASM │ │ Babel │
│ (Chrome)│ │ (Java) │ │ apps │ │(Python)│
│ JSC │ │ │ │ │ │ │
│(Safari)│ │ │ │ │ │ │
│SpiderM.│ │ │ │ │ │ │
│(Firefox)│ │ │ │ │ │ │
└────┬───┘ └────────┘ └────────┘ └────┬───┘
↓ ↓
Intl.DateTimeFormat Babel API
(your browser) (your Python)What CLDR Contains for Calendars#
CLDR provides structured data for each calendar system and locale combination:
Calendar-locale data includes:
- Month names (wide, abbreviated, narrow) in the target locale
- Day names in the target locale
- Era names and abbreviations
- Date format patterns (full, long, medium, short)
- Date-time combining patterns
- Number systems (which digits to use: Latin, Arabic-Indic, etc.)
- First day of week (Sunday in US, Monday in Europe, Saturday in Middle East)
- Minimum days in first week (affects week numbering)
Calendar system data includes:
- Epoch (when year 1 starts)
- Month structure (how many months, which are leap)
- Era definitions (Japanese Imperial eras, Buddhist era offset, etc.)
Data Volume#
CLDR v44 (2023) contains data for:
- 600+ locales
- 20+ calendar systems
- ~100 MB of raw XML data
- ~35 MB of JSON data
Not all of this ships to your browser. ICU implementations cherry-pick relevant subsets based on the platform’s locale support.
How Browsers Consume CLDR#
Modern browsers embed ICU (International Components for Unicode), which consumes
CLDR data at build time. This is why Intl.DateTimeFormat “just works” without
downloading anything:
Chrome/V8: Compiles ICU with full CLDR data. Ships ~27 MB of ICU data as part of Chrome’s binary. Node.js can be compiled with
full-icu(default since Node 13) orsmall-icu(English only).Firefox/SpiderMonkey: Also embeds ICU with CLDR data. Full locale support in desktop builds.
Safari/JavaScriptCore: Embeds ICU. Apple platforms ship comprehensive ICU data due to macOS/iOS locale requirements.
What This Means in Practice#
new Intl.DateTimeFormat('fa-IR-u-ca-persian')works in Chrome, Firefox, and Safari because all three embed the Persian calendar CLDR data.- Calendar system support is consistent across modern browsers because they all consume the same CLDR source.
- CLDR updates propagate through browser releases, typically 2-4 months after a CLDR release.
When CLDR Data Matters#
CLDR updates can change:
- Japanese era names: When a new emperor accedes (last: 2019, Reiwa)
- Calendar formatting patterns: When a locale’s preferred date format changes
- First day of week: When a country changes its official week start
The 2019 Reiwa era transition was a real-world test: CLDR published the new era name, ICU was updated, and browser vendors shipped updates within weeks. Future era transitions will follow the same pipeline.
How Python Consumes CLDR#
Python’s standard library does NOT consume CLDR. Python’s locale module uses the
operating system’s locale data, which varies by platform and installation.
Babel fills this gap by bundling CLDR data directly:
- Babel ships as a Python package with embedded CLDR data files (~30 MB installed)
- Updated when Babel releases new versions incorporating new CLDR releases
- Provides consistent behavior regardless of operating system
This means Python date formatting via Babel is deterministic and portable, while
Python date formatting via locale.strftime() depends on the OS locale installation.
How ICU4X Consumes CLDR#
ICU4X takes a different approach: rather than embedding all CLDR data, it uses a compact binary format (“data blobs”) that can be:
- Compiled in: Full CLDR data in a ~200 KB WASM binary
- Loaded dynamically: Fetch only the locales and calendar systems needed
- Tree-shaken: Include only the CLDR data your application actually uses
This data-on-demand approach is what makes ICU4X viable for resource-constrained environments where embedding 27 MB of ICU data (like browsers do) is not feasible.
Practical Implications#
For JavaScript Applications#
You almost certainly don’t need to think about CLDR. Browsers embed it.
Intl.DateTimeFormat surfaces it. The data pipeline is invisible.
The exception: if you need specific CLDR data directly (e.g., accessing the raw
locale data for a custom formatting engine), you can use the cldr-json npm
package, which publishes CLDR releases as JSON files.
For Python Applications#
Use Babel for consistent locale-aware formatting. Don’t rely on locale.strftime()
unless you control the operating system’s locale installation.
For Edge/Embedded Applications#
ICU4X is your path to CLDR data. If your environment doesn’t have ICU (no V8, no JDK), ICU4X provides CLDR-backed calendar support in a portable Rust/WASM binary.
For Calendar Arithmetic Libraries#
hijri-converter, jdatetime, jalaali-js, and hebcal do NOT use CLDR. They implement their own calendar algorithms and carry their own data (Umm al-Qura tables, Jalaali cycle patterns, Hebrew postponement rules). CLDR is for formatting output; these libraries handle computation.
Version Synchronization Risks#
A subtle risk: your application may use different CLDR versions simultaneously.
Example: Your browser (CLDR v44 via ICU) formats a Hijri date as “9 Sha’ban 1447”. Your server (Babel with CLDR v43) formats the same date differently because a month name translation was updated between CLDR versions.
In practice, this is rare and usually cosmetic (slightly different month name transliterations). But for applications requiring exact consistency between server and client rendering, pin your CLDR version or use the same formatting engine (e.g., ICU4X on both).
Sources#
- Unicode CLDR – Accessed 2026-03-09
- ICU User Guide: Calendars – Accessed 2026-03-09
- ICU4X Data Management – Accessed 2026-03-09
- Babel CLDR Data – Accessed 2026-03-09
- V8 Intl Implementation – Accessed 2026-03-09
- cldr-json npm – Accessed 2026-03-09
Hijri Calendar Accuracy: Deep Technical Analysis#
The Fundamental Problem#
The Islamic calendar is the only major calendar system where the “correct” date on any given day is not universally agreed upon. This is not a technical limitation – it is a theological and political reality. Understanding this is essential for any developer building Hijri-aware applications.
Three Calculation Methods#
1. Umm al-Qura (Tabular, Saudi Official)
The calendar maintained by the King Abdulaziz City for Science and Technology (KACST) in Saudi Arabia. It is a precomputed tabular calendar that approximates astronomical new moon times, adjusted by the Saudi government for civil purposes.
How it works:
- Tables are published covering specific date ranges (currently 1356-1500 AH)
- Month start dates are determined in advance using astronomical calculations
- Adjustments are made to ensure certain religious dates fall on preferred days
- The Umm al-Qura calendar is NOT purely astronomical – it includes policy adjustments
hijri-converter uses Umm al-Qura as its primary method. The library ships the complete Umm al-Qura table and provides direct lookup for any date in the covered range. Outside the table range, it falls back to an algorithmic calculation.
2. Astronomical Calculation
Based on computing the exact time of the astronomical new moon (conjunction) and moonset/sunrise times for a given location. This is scientifically precise but does not match any single country’s official calendar because:
- Different countries use different criteria (moonset after sunset? moon altitude above threshold? moon elongation above threshold?)
- Some countries require the moon to be visible from within their borders
- Atmospheric conditions affect theoretical visibility
No widely-used library implements full astronomical Hijri calculation with
location-aware criteria. The astronomia JavaScript package provides moon phase
computation, but translating phases into calendar dates requires country-specific
visibility criteria that are not codified in any library.
3. Tabular (Civil) Calculation
A simplified mathematical model with fixed rules:
- 30-year cycle with 11 leap years
- Months alternate 30/29 days
- Leap years add one day to the last month (Dhul Hijjah: 30 days instead of 29)
This is the simplest to implement and the least accurate. It drifts from both
astronomical observation and Umm al-Qura over time. Intl.DateTimeFormat with
calendar: 'islamic-civil' uses this method.
Practical Discrepancies#
On any given Gregorian date, the Hijri date can differ by 1-2 days depending on which method (and which country’s rules) you use:
| Gregorian Date | Umm al-Qura | Astronomical | Tabular | Sighting (varies) |
|---|---|---|---|---|
| 2026-03-09 | 9 Sha’ban 1447 | 9 Sha’ban 1447 | 9-10 Sha’ban | 8-10 Sha’ban |
The 1-2 day variance is not a bug. It reflects genuine disagreement about when Islamic months begin. Different countries may celebrate Eid on different days because they follow different calendar authorities.
Implications for Application Design#
Critical decision: Your application must choose which Hijri calendar method to use, and this choice is a policy decision, not a technical one.
If your application serves:
- Saudi Arabia: Use Umm al-Qura (hijri-converter default)
- Turkey: Turkey uses a Turkish Diyanet calendar that may differ from Umm al-Qura
- Pakistan/Bangladesh: Often follow local moon sighting, which cannot be precomputed
- Indonesia/Malaysia: Use government astronomical calculations that may differ from Umm al-Qura
- Global Muslim audience: You may need to support multiple methods with user selection
Architectural recommendation: Store dates internally as Gregorian timestamps. Convert to Hijri at the display layer using the user’s preferred calendar method. Never store Hijri dates as the source of truth – the same Hijri date can map to different Gregorian dates depending on the calculation method.
hijri-converter Architecture#
The hijri-converter Python library is structured around two core classes:
Hijri(year, month, day): Represents a Hijri dateGregorian(year, month, day): Represents a Gregorian date
Conversion uses a lookup table for Umm al-Qura dates (O(1) lookup) with fallback to algorithmic calculation:
# The core algorithm (simplified):
# 1. Convert Gregorian to Julian Day Number (JDN)
# 2. Look up JDN in Umm al-Qura month-start table
# 3. Compute Hijri year/month/day from table positionThe Umm al-Qura table is embedded as a Python data structure containing the Julian Day Number of the first day of each Hijri month from 1356 AH to 1500 AH. This covers 1937-2076 CE, which is sufficient for virtually all practical applications.
Edge cases handled:
- Dates outside Umm al-Qura range fall back to algorithmic calculation
- Invalid Hijri dates (e.g., Sha’ban 30 in a 29-day month) raise ValueError
- Gregorian dates before the Islamic epoch (622 CE) are handled gracefully
Test coverage: The library includes extensive test suites with known conversion pairs verified against the official Umm al-Qura tables published by KACST.
Intl.DateTimeFormat Islamic Calendar Internals#
Browsers implement Islamic calendar support through ICU (International Components for Unicode). ICU provides four Islamic calendar variants:
islamic: Uses an astronomical algorithm based on the Islamic Civil calendar with astronomical correctionsislamic-umalqura: Uses the Umm al-Qura tabular dataislamic-civil: Uses the simple 30-year tabular cycleislamic-tbla: Tabular Islamic calendar (astronomical epoch)
The ICU Umm al-Qura implementation uses the same KACST data as hijri-converter.
Browser-displayed dates using islamic-umalqura should match hijri-converter output
for dates within the Umm al-Qura range.
Verification approach: For critical applications (Islamic finance, government systems), compare outputs of hijri-converter and Intl.DateTimeFormat for your date range. Discrepancies indicate either a data version mismatch (ICU ships with specific CLDR versions) or an edge case in the Umm al-Qura table boundaries.
Recommendations#
Default to Umm al-Qura unless your users are in a country that explicitly uses a different calculation method.
Never store Hijri dates as primary keys. Store Gregorian/UTC timestamps and convert at display time.
Document your calendar method in your application’s settings or about page. Users should know which Hijri calendar variant they are seeing.
For sighting-based calendars: Build a configuration mechanism where religious authorities can adjust dates after moon sighting announcements. This cannot be automated.
Test with real data: Verify your library’s output against published Umm al-Qura tables for your target date range.
Sources#
- hijri-converter source code – Accessed 2026-03-09
- Umm al-Qura Calendar – Historical analysis
- ICU Calendar Classes – Accessed 2026-03-09
- KACST Umm al-Qura – Official Saudi calendar
- Islamic Calendar Wikipedia – Overview
ICU4X Architecture: Deep Technical Analysis#
What ICU4X Is#
ICU4X is the Unicode Consortium’s next-generation internationalization library, written in Rust with WASM, C, C++, and JavaScript bindings. It is designed to replace legacy ICU (C/C++) for environments where embedding a full ICU installation (~27 MB) is impractical: WASM runtimes, embedded systems, edge computing, mobile applications, and non-C/C++ language ecosystems.
Why ICU4X Matters for Calendar Internationalization#
ICU4X provides the broadest calendar system support of any standalone library:
| Calendar System | ICU4X | Intl.DateTimeFormat | ICU (C++) |
|---|---|---|---|
| Buddhist | Yes | Yes | Yes |
| Chinese | Yes | Yes | Yes |
| Coptic | Yes | Yes | Yes |
| Dangi (Korean) | Yes | Yes | Yes |
| Ethiopian | Yes | Yes | Yes |
| Ethiopic (Amete Alem) | Yes | Partial | Yes |
| Gregorian | Yes | Yes | Yes |
| Hebrew | Yes | Yes | Yes |
| Indian (Saka) | Yes | Yes | Yes |
| Islamic (civil) | Yes | Yes | Yes |
| Islamic (observational) | Yes | Yes | Yes |
| Islamic (tabular) | Yes | Yes | Yes |
| Islamic (Umm al-Qura) | Yes | Yes | Yes |
| ISO 8601 | Yes | Yes | Yes |
| Japanese | Yes | Yes | Yes |
| Japanese (extended) | Yes | Partial | Partial |
| Persian | Yes | Yes | Yes |
| ROC (Republic of China) | Yes | Yes | Yes |
ICU4X supports calendar arithmetic (add months, compare dates) across all these systems – something Intl.DateTimeFormat cannot do.
Architecture#
Data Model#
ICU4X separates code from data. The internationalization algorithms are compiled into the binary (Rust or WASM), while the CLDR locale data is loaded separately via a “data provider” abstraction:
┌──────────────────────┐
│ Application Code │
│ │
│ ICU4X API calls │
└──────────┬───────────┘
│
┌──────────▼───────────┐
│ ICU4X Core │
│ (Rust / WASM) │
│ │
│ Calendar algorithms │
│ Formatting logic │
│ Collation rules │
└──────────┬───────────┘
│
┌──────────▼───────────┐
│ Data Provider │
│ │
│ ┌─────────────────┐ │
│ │ Baked-in data │ │ ← Compiled into binary
│ │ (default) │ │
│ └─────────────────┘ │
│ ┌─────────────────┐ │
│ │ Blob provider │ │ ← Load from file/network
│ │ (dynamic) │ │
│ └─────────────────┘ │
│ ┌─────────────────┐ │
│ │ Custom provider │ │ ← User-defined data source
│ │ (pluggable) │ │
│ └─────────────────┘ │
└──────────────────────┘Key design choice: By separating data from code, ICU4X allows applications to include only the locale data they need. An application targeting only Persian and Arabic locales can ship a much smaller data blob than one supporting all 600+ CLDR locales.
WASM Binary Size#
Full ICU4X with all calendar systems and formatting:
- Core WASM binary: ~150-200 KB (compiled from Rust)
- Full locale data: ~1-5 MB depending on locale count
- Minimal data (1-2 locales): ~100-200 KB
Total for a typical deployment (5-10 locales, all calendars): ~300-500 KB. This is dramatically smaller than legacy ICU (~27 MB) while providing equivalent functionality.
Calendar Arithmetic#
Unlike Intl.DateTimeFormat (format-only), ICU4X supports date arithmetic across all calendar systems:
- Create a date in any calendar system
- Add/subtract years, months, days
- Compare dates across calendar systems
- Convert between calendar systems
- Compute weekday, day-of-year, week-of-year
This makes ICU4X the only library (besides the forthcoming Temporal API) that provides universal calendar arithmetic without calendar-specific libraries.
API Design#
ICU4X exposes a type-safe API where calendar types are part of the type system:
The Rust API uses generic types parameterized by calendar system, ensuring at compile time that you cannot accidentally mix dates from different calendars without explicit conversion. The WASM/JS bindings relax this to runtime checks.
Production Readiness#
As of v1.5 (2025), ICU4X is production-ready:
- Conformance: Passes the ICU conformance test suite for all supported features
- Unicode Consortium backing: Developed by the same organization that maintains CLDR and ICU
- Funding: Google, Amazon, and Mozilla fund ICU4X development
- Users: Firefox uses ICU4X for some Intl operations. Android is evaluating ICU4X to replace parts of its ICU deployment.
- Stable API: v1.0+ with semantic versioning guarantees
What is NOT Ready#
- Full API parity with ICU (C++): ICU4X does not yet implement every ICU feature. Missing features include some collation options and message formatting.
- Ecosystem maturity: npm/PyPI packaging is functional but less polished than established libraries. Documentation targets Rust developers primarily.
- Community size: Small compared to Intl or Babel. Finding help on Stack Overflow is limited. GitHub issues are the primary support channel.
When to Choose ICU4X#
Choose ICU4X when:
- You need calendar arithmetic across multiple non-Gregorian systems and Temporal is not yet available
- Your environment lacks native Intl support (edge workers, embedded systems, non-V8 WASM runtimes)
- You need portable i18n that works identically across platforms (not dependent on host ICU version)
- You need to minimize data size by including only specific locales
- You are building Rust applications with i18n requirements
Do NOT choose ICU4X when:
- Intl.DateTimeFormat satisfies your needs (zero cost, already available)
- You only need one calendar system (use a dedicated library instead)
- Your team lacks Rust/WASM experience and your requirements are simple
- Bundle size is extremely constrained (< 100 KB total for all i18n)
Comparison with Alternatives#
| Feature | ICU4X | Intl.DateTimeFormat | Babel (Python) |
|---|---|---|---|
| Calendar systems | 20+ | 12+ | Gregorian + CLDR |
| Calendar arithmetic | Yes | No | No |
| Formatting | Yes | Yes | Yes |
| Portable | Yes (WASM) | Browser/Node only | Python only |
| Data size | Configurable | Fixed (browser) | ~30 MB |
| Maintenance | Unicode Consortium | Browser vendors | Pallets project |
Sources#
- ICU4X GitHub – Accessed 2026-03-09
- ICU4X Documentation – Accessed 2026-03-09
- ICU4X Calendar Module – Accessed 2026-03-09
- ICU4X Design Documents – Accessed 2026-03-09
- Firefox ICU4X Integration – Accessed 2026-03-09
Persian/Jalali Calendar Architecture: Deep Technical Analysis#
The Jalaali Algorithm#
The Persian Solar Hijri (Jalali) calendar is astronomically precise. Unlike the Islamic lunar calendar with its observation-based ambiguity, the Jalali calendar is deterministic: the new year (Nowruz) always falls on the vernal equinox, computed to within seconds.
The conversion algorithm used by both jdatetime (Python) and jalaali-js (JavaScript) is based on the work of Iranian mathematician Ahmad Birashk, later refined and implemented as the “Jalaali algorithm” by Behrooz Parhami.
Core Algorithm Steps#
The Jalaali algorithm converts between Jalali and Gregorian via the Julian Day Number (JDN) as an intermediate representation:
Jalali Date ↔ Julian Day Number ↔ Gregorian DateStep 1: Jalali to JDN
- Determine the Jalali year’s position in the 2820-year grand cycle
- The grand cycle has a complex pattern of leap years (683 leap years per cycle)
- Calculate the JDN of the first day of the Jalali year
- Add the day offset within the year
Step 2: JDN to Gregorian
- Standard JDN-to-Gregorian conversion (well-known algorithm, RFC-derived)
The key insight is the 2820-year cycle. Unlike the Gregorian calendar’s simple 4/100/400 leap year rule, the Jalali calendar uses a cycle of 2820 years containing exactly 683 leap years. This produces an average year length of 365.24219858… days, which is more accurate than the Gregorian calendar’s 365.2425 days.
Leap Year Rules#
Jalali leap years follow an irregular pattern within subcycles:
- The 2820-year grand cycle contains subcycles of varying lengths
- Within each subcycle, leap years are spaced 4 or 5 years apart
- The pattern ensures the vernal equinox always falls on Farvardin 1
This complexity is why an algorithmic approach (rather than simple modular arithmetic) is necessary. jalaali-js and jdatetime both encode this pattern in lookup tables within their source code.
Month Lengths#
The first 6 months (Farvardin through Shahrivar) have 31 days each. The next 5 months (Mehr through Bahman) have 30 days each. The last month (Esfand) has 29 days in regular years and 30 in leap years. This gives 365 or 366 days per year.
Unlike the Gregorian calendar’s irregular month lengths, the Jalali pattern is simple and regular, making date arithmetic straightforward once you have the conversion function.
jdatetime (Python) Architecture#
jdatetime takes the approach of subclassing Python’s standard datetime types:
Design pattern: Mirror the stdlib API. jdatetime.date has the same interface
as datetime.date. jdatetime.datetime mirrors datetime.datetime. Methods like
strftime(), today(), fromtimestamp(), replace(), timedelta arithmetic –
all work identically but in the Jalali calendar.
Internal representation: Jalali year, month, and day as integers. Conversion to/from Gregorian happens on demand (e.g., when interacting with stdlib datetime objects or databases).
Django integration: jdatetime provides JalaliDateField and
JalaliDateTimeField that store Gregorian dates in the database but render as
Jalali in forms and admin. This follows the architectural principle of storing
UTC/Gregorian internally and converting at the display layer.
Formatting: Full strftime/strptime support with Persian month names,
weekday names, and both Persian and English output options. Supports the %G
directive for Persian digit output.
Performance Characteristics#
Conversion involves:
- ~10 arithmetic operations for the 2820-year cycle position
- ~5 comparisons for month length determination
- No table lookups beyond the small subcycle pattern (< 1 KB data)
This is O(1) computation with negligible overhead. Bulk operations (converting thousands of dates) add no measurable latency beyond the iteration itself.
jalaali-js (JavaScript) Architecture#
jalaali-js takes a minimalist functional approach:
Design pattern: Pure functions, no classes, no state. Each function takes numeric arguments and returns numeric results.
Core functions:
toJalaali(gy, gm, gd)– Gregorian to Jalaali, returns{jy, jm, jd}toGregorian(jy, jm, jd)– Jalaali to Gregorian, returns{gy, gm, gd}isLeapJalaaliYear(jy)– BooleanjalaaliMonthLength(jy, jm)– Number of daysjalaaliToDateObject(jy, jm, jd)– Returns JavaScript Date
Bundle characteristics:
- ~2 KB minified, ~1 KB gzipped
- Zero dependencies
- No external data files
- Pure computation (no network, no locale data)
Why this design: jalaali-js is designed as a conversion primitive that higher-level libraries build upon. jalali-moment wraps it with Moment-style API. date-fns-jalali integrates it into the date-fns function set. By staying small and focused, jalaali-js maximizes its utility as a building block.
Algorithm Comparison: jdatetime vs. jalaali-js#
Both libraries implement the same Jalaali algorithm (Birashk/Parhami), producing identical results for any given date. The differences are entirely in API style:
| Aspect | jdatetime | jalaali-js |
|---|---|---|
| Language | Python | JavaScript |
| API style | OOP (mirrors stdlib) | Functional (pure) |
| Scope | Full datetime replacement | Conversion only |
| Formatting | Built-in (strftime) | None (use Intl) |
| Django/React | Django fields included | React via date-fns-jalali |
| Size | Pure Python, no deps | ~2 KB, zero deps |
Verification#
Both libraries can be verified against the official Iranian calendar published by the Institute of Geophysics at the University of Tehran. For any date in the modern era (1300-1500 SH / 1921-2121 CE), the conversion should match exactly.
Edge Cases and Pitfalls#
Year boundary: Nowruz (Farvardin 1) can fall on March 20 or March 21 depending on the vernal equinox. The Jalaali algorithm handles this correctly, but naive year-based assumptions (e.g., “Jalali year X always starts on March 21”) will occasionally be off by one day.
Negative years / historical dates: Both libraries handle modern dates (post-1 SH / 622 CE). Historical dates before the Islamic epoch may produce undefined behavior. Neither library is designed for historical astronomical research.
Timezone interaction: Nowruz is defined as the moment the Sun crosses the vernal equinox point, which depends on the observer’s timezone. The calendar transition happens at the official Tehran time. Applications in other timezones may need to handle the brief period where different timezones are in different Jalali years.
Formatting with Persian numerals: jdatetime handles this natively. In
JavaScript, use Intl.DateTimeFormat with numberingSystem: 'arabext' (extended
Arabic-Indic digits used in Persian) to get ۱۴۰۴ instead of 1404.
Integration Patterns#
Python Web Application#
# Store Gregorian in database, convert at display layer
# DB column: DATE (Gregorian)
# Display: jdatetime.date.fromgregorian(date=db_date).strftime('%Y/%m/%d')JavaScript Single-Page Application#
// Convert for display using jalaali-js + Intl
// const { jy, jm, jd } = jalaali.toJalaali(2026, 3, 9)
// Format with Intl.DateTimeFormat({ calendar: 'persian' })
The pattern is consistent: Gregorian storage, Jalali display. This avoids ambiguity in date storage and leverages the Gregorian-native database ecosystem.
Sources#
- jdatetime source – Accessed 2026-03-09
- jalaali-js source – Accessed 2026-03-09
- Jalaali Calendar Algorithm – Algorithm documentation
- Solar Hijri Calendar Wikipedia – Overview
- Behrooz Parhami, “A Unified Algorithm for Persian Calendar” – Original algorithm
S2 Recommendation: Calendar Internationalization#
Architecture Summary#
Calendar internationalization operates on a layered architecture where solutions complement rather than compete:
Layer 1: Display formatting → Intl.DateTimeFormat (free, native)
Layer 2: Calendar arithmetic → Dedicated libraries per calendar system
Layer 3: Comprehensive i18n → ICU4X (portable) or Babel (Python)
Layer 4: Specialized features → Domain-specific libraries (holidays, prayer times)Most applications need Layer 1 always and one or two Layer 2 libraries. Layers 3 and 4 are for specialized requirements.
Key Technical Findings#
1. The CLDR Pipeline is Your Foundation#
All roads lead to CLDR. Browsers consume it via ICU. Python consumes it via Babel. ICU4X repackages it as compact data blobs. Understanding this pipeline explains why calendar support is consistent across browsers and why Python needs Babel for equivalent functionality.
2. Hijri Accuracy is a Policy Decision#
The Islamic calendar’s three calculation methods (Umm al-Qura, astronomical, tabular) produce different results. The “correct” choice depends on the user’s country and religious authority. Applications must make this decision explicit – defaulting to Umm al-Qura is the safest choice for most contexts.
3. Persian/Jalali is the Reference Implementation#
The Jalaali algorithm (Birashk/Parhami) is deterministic, efficient (O(1)), and produces identical results across all implementations. jdatetime (Python) and jalaali-js (JavaScript) are both production-grade. Other calendar communities should aspire to this level of library maturity.
4. Chinese Lunar Tables Expire#
All Chinese lunar calendar libraries use lookup tables covering 1900-2100. This is a known limitation with a known solution (generate new tables). Applications planning for post-2100 dates need awareness but not panic.
5. RTL is a CSS Concern#
RTL calendar layout is primarily about CSS logical properties and dir attributes,
not calendar libraries. The most common bugs are hardcoded left/right in event
positioning and navigation arrow direction. CSS logical properties solve most issues.
6. ICU4X is the Portable Future#
ICU4X is the first viable alternative to platform-native ICU for comprehensive calendar internationalization. Its data-code separation and WASM support make it suitable for environments where Intl is unavailable.
Architecture Recommendations#
JavaScript Web Application#
Display: Intl.DateTimeFormat (free, native)
Arithmetic: Per-calendar library (jalaali-js, etc.) OR wait for Temporal
Formatting: @formatjs/intl for ICU MessageFormat integration
RTL: CSS logical properties + dir="rtl"Python Server Application#
Display: Babel (CLDR-backed locale formatting)
Arithmetic: Per-calendar library (jdatetime, hijri-converter, etc.)
Storage: Gregorian/UTC timestamps (convert at display layer)Cross-Platform / Edge / Embedded#
Everything: ICU4X (WASM or Rust native)Multi-Calendar Application#
If your application must support 3+ calendar systems simultaneously:
Preferred: Intl.DateTimeFormat (display) + Temporal (arithmetic, when available)
Alternative: ICU4X (portable, all calendars in one library)
Avoid: Installing separate libraries for each calendar systemProceed to S3#
The following use-case scenarios warrant analysis:
- Iranian SaaS developer – Building applications for Persian-speaking users
- Islamic finance application – Hijri-based financial products
- CJK e-commerce platform – Festival-aware marketing
- Global enterprise HR system – Multi-calendar employee management
- Hebrew religious application – Liturgical calendar features
- Government/civic application – Official calendar system compliance
RTL Calendar Layout: Deep Technical Analysis#
The Problem#
Right-to-left (RTL) calendar layout is a requirement for Arabic and Hebrew applications. It involves more than just mirroring a calendar grid – text direction, number rendering, day ordering, and interaction patterns all need adaptation.
RTL calendar support sits at the intersection of calendar internationalization and calendar UI (covered in 1.221). This analysis focuses on the CSS and layout strategies rather than specific UI library implementations.
What “RTL Calendar” Actually Means#
A calendar in an RTL language needs several adaptations:
1. Grid Direction#
In an LTR calendar, Sunday (or Monday) is on the left, Saturday (or Friday) is on the right. In an RTL calendar, this reverses: Saturday (or Friday) is on the left, Sunday (or Monday) is on the right.
The week still flows chronologically in the same direction from the user’s perspective – earlier days are at the “start” of the row, later days at the “end.” What changes is that “start” means the right side in RTL.
2. Week Start Day#
Week start day is a locale-specific setting, not an RTL-specific one:
- Sunday start: US, Canada, Japan, China, Brazil
- Monday start: Most of Europe, Australia, much of Asia
- Saturday start: Many Middle Eastern countries (Egypt, Iran, Afghanistan)
- Friday start: Maldives
CLDR provides firstDay data for each territory. Applications should respect this
independently of text direction.
3. Event Text and BiDi#
Event titles in an RTL calendar may contain mixed-direction text:
- Arabic/Hebrew text flows right-to-left
- Embedded numbers, times, and Latin text flow left-to-right
- A single event title like “اجتماع 3:00 PM” contains both directions
The Unicode BiDi algorithm handles this automatically in most rendering contexts.
Explicit dir="auto" on event title elements ensures correct detection.
4. Navigation Controls#
Previous/next month navigation arrows should reverse in RTL:
- “Previous month” arrow should point right (→) in RTL (toward the “start”)
- “Next month” arrow should point left (←) in RTL (toward the “end”)
5. Multi-Day Event Spans#
In LTR calendars, a multi-day event bar stretches from left to right. In RTL, it stretches from right to left. The event still starts on its start date and ends on its end date; only the visual direction changes.
CSS Strategy: Logical Properties#
The modern CSS approach to RTL calendar layout uses CSS logical properties, which replace physical directions (left/right) with logical ones (inline-start/inline-end):
| Physical Property | Logical Property | LTR Value | RTL Value |
|---|---|---|---|
margin-left | margin-inline-start | Left | Right |
margin-right | margin-inline-end | Right | Left |
padding-left | padding-inline-start | Left | Right |
text-align: left | text-align: start | Left | Right |
float: left | float: inline-start | Left | Right |
border-left | border-inline-start | Left | Right |
Grid Layout#
CSS Grid with logical properties handles RTL calendar grids naturally:
.calendar-grid {
display: grid;
grid-template-columns: repeat(7, 1fr);
direction: inherit; /* Inherits from parent dir attribute */
}
.calendar-cell {
padding-inline-start: 4px;
text-align: start;
}When the parent element has dir="rtl", the grid automatically flows from right
to left. No additional CSS needed for the basic grid structure.
Flexbox#
Flexbox also respects the direction property:
.calendar-week {
display: flex;
flex-direction: row; /* Reverses in RTL context */
}In an RTL context, flex-direction: row flows from right to left. This is the
correct behavior for calendar day rows.
Calendar UI Library RTL Support#
FullCalendar#
FullCalendar has the most mature RTL support of the major calendar UI libraries:
- Sets
dir="rtl"on the calendar root based on locale - Uses CSS logical properties in its stylesheets
- Reverses navigation arrows
- Handles multi-day event bar direction
- Supports RTL locale names in the toolbar
However, custom plugins and event renderers must also use logical properties to maintain RTL compatibility.
Schedule-X#
Schedule-X has basic RTL support:
- Respects
dir="rtl"attribute - Some CSS uses physical properties that need manual override
- Framework component injection (its unique feature) can render RTL-aware components
Other Libraries#
Most other calendar UI libraries (tui.calendar, DayPilot, EventCalendar) have limited or no documented RTL support. Building RTL calendar UI with these libraries requires significant CSS customization.
Common RTL Calendar Bugs#
1. Hardcoded left/right in event positioning
Many calendar libraries use pixel-based absolute positioning for events:
/* BUG: This doesn't reverse in RTL */
.event { left: 120px; width: 200px; }Fix: Use inset-inline-start instead of left:
.event { inset-inline-start: 120px; inline-size: 200px; }2. Arrow icons that don’t reverse
SVG or icon font arrows often have a fixed visual direction. Use CSS transforms or separate RTL icon sets:
[dir="rtl"] .nav-prev { transform: scaleX(-1); }
[dir="rtl"] .nav-next { transform: scaleX(-1); }3. Date range display
“March 1 - March 7” should display as “۷ مارس - ۱ مارس” in RTL (note: the
start date is on the right). Using Intl.DateTimeFormat with formatRange() handles
this correctly.
4. Drag-and-drop direction
Dragging an event to the “right” in an LTR calendar moves it later. In RTL, dragging “right” should move it earlier (toward the start of the week). Calendar libraries that hardcode drag direction to pixel movement will break in RTL.
5. Tooltip and popup positioning
Popups that appear “to the right” of a clicked cell should appear “to the left”
in RTL. Use logical positioning (inset-inline-end) for popup placement.
Implementation Recommendation#
Minimal RTL Calendar (CSS-only approach)#
For teams building custom calendar grids:
- Set
dir="rtl"on the calendar container (or inherit from document) - Use CSS Grid with
grid-template-columns: repeat(7, 1fr)– grid automatically respects direction - Use CSS logical properties exclusively (never
left/right/margin-left) - Use
Intl.DateTimeFormatfor all date text – it handles RTL formatting and number systems - Use
dir="auto"on event title text elements for BiDi text - Set
text-align: start(notleft) on all text elements
With FullCalendar#
FullCalendar + an RTL locale (ar, he, fa) is the simplest path to a functional
RTL calendar UI. Set the direction: 'rtl' option and the locale, and most
RTL concerns are handled automatically.
Testing#
Test with real RTL content (Arabic or Hebrew text), not just reversed English. Real RTL text reveals BiDi issues that reversed English does not. Test with:
- Pure Arabic/Hebrew event titles
- Mixed-language titles (Arabic + English, Hebrew + numbers)
- Long event titles that wrap
- Multi-day events spanning the week boundary
- Drag-and-drop interactions
Sources#
- CSS Logical Properties MDN – Accessed 2026-03-09
- FullCalendar RTL documentation – Accessed 2026-03-09
- Unicode BiDi Algorithm – Accessed 2026-03-09
- CLDR Week Data – firstDay data
- CSS Writing Modes Level 4 – Accessed 2026-03-09
S3: Need-Driven
S3: Need-Driven Analysis – Calendar Internationalization#
Methodology#
Persona-based analysis mapping real-world use cases to library recommendations. Each scenario describes:
- Who: The developer/team and their context
- Why: The business requirement driving calendar internationalization
- Requirements: Hard requirements and soft preferences
- Constraints: Budget, team skills, timeline, compliance needs
- Recommendation: Which libraries to use and why
Personas#
Six use cases were selected to cover the full spectrum of calendar internationalization needs:
Iranian SaaS Developer – A developer building products for the Persian-speaking market, where Jalali dates are the default.
Islamic Finance Application – A fintech team building Shariah-compliant financial products where Hijri dates have legal significance.
CJK E-Commerce Platform – A team building a shopping platform that needs festival-aware marketing across Chinese, Japanese, and Korean markets.
Global Enterprise HR System – An enterprise software team managing employees across regions with different calendar systems.
Hebrew Religious Application – A developer building liturgical tools that require Hebrew calendar computation, holiday awareness, and prayer times.
Government/Civic Application – A contractor building software for a government that officially uses a non-Gregorian calendar system.
Selection Criteria#
Personas were chosen to represent:
- Different calendar systems (Jalali, Hijri, Chinese, Hebrew, Buddhist/Ethiopian)
- Different accuracy requirements (display-only vs. computation vs. legal precision)
- Different tech stacks (Python server, JavaScript SPA, multi-platform)
- Different team sizes and budgets (solo developer to enterprise team)
Sources#
Analysis draws on library capabilities assessed in S1-S2, combined with domain-specific requirements gathered from developer community discussions, industry specifications (Islamic finance standards, government IT requirements), and documented use cases.
S3 Recommendation: Calendar Internationalization#
Persona-to-Library Mapping#
| Persona | Primary Library | Display | Key Concern |
|---|---|---|---|
| Iranian SaaS | jdatetime (Py) / jalaali-js (JS) | Intl (persian) | Jalali is the default, not optional |
| Islamic Finance | hijri-converter (Py) | Intl (islamic-umalqura) | Accuracy = legal compliance |
| CJK E-Commerce | lunardate (Py) / chinese-lunar-cal (JS) | Intl (ja/ko/zh locales) | Festival date computation |
| Enterprise HR | Per-calendar libraries or ICU4X | Intl (per-employee calendar) | Multi-calendar coordination |
| Hebrew Religious | hebcal (JS) | Intl (hebrew) | Full liturgical feature set |
| Government/Civic | Per-country library | Intl (per-country calendar) | Compliance, offline, longevity |
Cross-Cutting Findings#
1. Intl.DateTimeFormat is Universal#
Every persona uses Intl.DateTimeFormat for display formatting. This is the single most important finding from the persona analysis: no matter what your use case, Intl.DateTimeFormat is your display layer.
2. Computation Needs Vary Dramatically#
The Iranian SaaS developer needs Jalali arithmetic daily. The CJK e-commerce team needs Chinese lunar computation once a year (for festival planning). The Thai government application needs no computation at all (Buddhist Era is a year offset).
Implication: Do not over-invest in calendar computation infrastructure. Assess your actual computation needs before adding libraries.
3. Accuracy Requirements Differ by Domain#
| Domain | Accuracy Requirement | Consequence of Error |
|---|---|---|
| Display/UX | Approximate (1-2 day tolerance) | User annoyance |
| E-commerce | Moderate (correct festival week) | Missed marketing timing |
| Finance | Exact (to the day) | Contract/legal violation |
| Religious | Exact (to the minute for prayer times) | Religious observance error |
| Government | Exact (per official calendar) | Regulatory non-compliance |
Choose your library and configuration based on your accuracy tier, not on technical capability alone.
4. GPL License Tension#
hebcal (GPL-2.0) and pyluach (AGPL-3.0) are the most capable Hebrew calendar libraries but their copyleft licenses create friction for proprietary applications. This is a recurring pattern: the most capable calendar libraries are often community-maintained under copyleft licenses.
5. Storage Pattern is Universal#
Every persona stores dates as Gregorian/UTC internally and converts at the display or business logic layer. No persona stores native calendar dates as the source of truth. This pattern should be treated as a best practice for all calendar internationalization work.
Decision Framework Update#
Incorporating S3 persona insights, the decision framework from S1 is refined:
Q1: Which calendar systems do your users need?
→ List them. This determines which libraries to evaluate.
Q2: For each calendar system, what level of support?
→ Display only → Intl.DateTimeFormat (no library needed)
→ Date arithmetic → Add computation library
→ Domain-specific features → Add specialized library (hebcal, etc.)
Q3: What is your accuracy requirement?
→ UX/marketing → Any mainstream library is fine
→ Financial/legal → Use the official calendar variant (Umm al-Qura, etc.)
→ Religious → Use domain-specific libraries (hebcal, etc.)
Q4: Server-side or client-side computation?
→ Client-only → Intl + JS libraries (jalaali-js, hebcal, etc.)
→ Server needed → Python libraries (hijri-converter, jdatetime, Babel)
→ Both → Mirror the same calendar method on both sidesUse Case: CJK E-Commerce Platform#
Who Needs This#
A product team building or localizing an e-commerce platform for Chinese, Japanese, and/or Korean markets. This could be a company expanding into East Asian markets, a regional platform adding locale-aware features, or a global marketplace tailoring its experience for CJK users.
Why They Need It#
E-commerce in CJK markets is heavily seasonal, and the seasons are driven by traditional calendar systems:
Chinese New Year (Spring Festival): The biggest shopping event in China, determined by the Chinese lunisolar calendar. Date varies by 29 days across Gregorian years. Sale campaigns must start and end relative to the lunar calendar, not fixed Gregorian dates.
Mid-Autumn Festival (Moon Festival): Another major shopping event, also determined by the Chinese lunar calendar (15th of 8th lunar month). Moon cake sales, gift promotions, and logistics planning all depend on this date.
Qingming Festival: Tomb-sweeping day, determined by the solar term “Qingming” (approximately April 4-6). Drives specific product categories (flowers, incense, paper goods).
Japanese holiday system: Golden Week (late April - early May), Obon (mid-August), and year-end shopping season follow the Gregorian calendar but with Japanese-specific dates. Japanese era formatting is expected in formal contexts.
Korean holidays: Chuseok (Korean Thanksgiving, lunar calendar), Seollal (Korean New Year, lunar calendar). Both are major shopping periods.
Business impact: A platform that cannot compute Chinese New Year’s date for 2027 (January 29) cannot plan its marquee annual sale event. A Japanese checkout flow that displays “2026” instead of “令和8年” on receipts feels foreign to users who expect era-based dates in formal contexts.
Requirements#
Hard requirements:
- Chinese lunar date computation for festival dates (Chinese New Year, Mid-Autumn, Dragon Boat, Qingming)
- Korean lunar date computation for Chuseok and Seollal
- Japanese era date formatting on receipts, invoices, and formal documents
- Locale-aware date formatting for zh-CN, zh-TW, ja-JP, ko-KR
- Correct week start display per territory (Sunday for Japan/Korea/Taiwan, Monday for mainland China)
Soft preferences:
- 24 solar terms awareness for marketing campaigns
- Traditional festival greetings with correct dates
- Countdown timers (“X days until Chinese New Year”)
- CJK numeral display in formal/traditional contexts
- Multi-territory support (zh-CN vs zh-TW formatting differences)
Constraints#
- Marketing team needs festival dates 12+ months in advance for campaign planning
- Platform operates across multiple CJK territories with different conventions
- Performance-sensitive (e-commerce pages must load fast)
- Team’s i18n expertise is primarily in text translation, not calendar systems
- Budget for calendar-specific work is limited (not the core product)
Why This Solution Fits#
Festival Date Computation#
Chinese lunar calendar (lunardate for Python, chinese-lunar-calendar for JS):
- Compute Chinese New Year: 1st day of 1st lunar month
- Compute Mid-Autumn Festival: 15th day of 8th lunar month
- Compute Dragon Boat Festival: 5th day of 5th lunar month
These libraries use lookup tables (1900-2100) that provide instant computation. A backend service can precompute festival dates for the next 5-10 years and expose them as a simple API endpoint.
Korean lunar dates: The Korean Dangi calendar follows the same lunisolar structure as the Chinese calendar. lunardate/chinese-lunar-calendar output can be used for Korean festival dates (Chuseok = 15th of 8th lunar month, same as Mid-Autumn Festival; Seollal = 1st of 1st lunar month, same as Chinese New Year).
Date Display#
Intl.DateTimeFormat handles all CJK display formatting:
zh-CN: 2026年3月9日 (simplified Chinese)zh-TW: 2026年3月9日 (traditional Chinese, same format)ja-JP: 2026年3月9日 or 令和8年3月9日 (withcalendar: 'japanese')ko-KR: 2026년 3월 9일
No additional library needed for display formatting. Intl handles month/day names, date ordering, and era display natively.
Solar Terms (Marketing Bonus)#
For marketing teams that want to align promotions with solar terms (e.g., “Winter Solstice Sale”, “Spring Begins promotion”), precomputed solar term tables are the pragmatic approach. Solar term dates vary by only 1-2 days year-to-year:
- Lichun (Start of Spring): Feb 3-5
- Qingming (Clear and Bright): Apr 4-6
- Dongzhi (Winter Solstice): Dec 21-23
For a marketing use case, a hardcoded table of solar term dates for the next 10 years is simpler and more reliable than astronomical computation.
Architecture#
Marketing Dashboard → Festival Date API → Backend
├── lunardate (Python)
├── Solar term table (hardcoded)
└── Gregorian holiday table
Storefront → Intl.DateTimeFormat → Browser
├── zh-CN locale
├── ja-JP locale + calendar: 'japanese'
└── ko-KR localeThe festival date computation lives on the server. The display formatting happens in the browser. The marketing team gets an API that returns festival dates for any year. The storefront displays dates in the user’s locale.
What This Solution Does NOT Cover#
- Chinese zodiac years: Computing the animal year (Year of the Snake, etc.) requires lunar calendar data plus a simple 12-year cycle. Easily derived from lunar year data.
- Auspicious date selection: Traditional Chinese date selection for weddings, business openings, etc. This requires a Chinese almanac (通书/通胜), which is a specialized domain beyond calendar libraries.
- Full CJK text i18n: Locale-aware date display is one part of CJK i18n. Text translation, CJK typography, input methods, and search behavior are separate concerns.
Risk Assessment#
Low risk: CJK date formatting via Intl.DateTimeFormat is mature and reliable. Chinese lunar calendar libraries use static lookup tables that produce deterministic results. The 2100 table expiration is not a concern for e-commerce planning horizons.
Caveat: Chinese New Year dates can shift by nearly a month year-to-year. Marketing campaigns planned by fixed Gregorian dates (“February sale”) may miss the actual festival period. Always compute the lunar date first, then plan Gregorian campaigns around it.
Sources#
- lunardate – Accessed 2026-03-09
- chinese-lunar-calendar – Accessed 2026-03-09
- MDN Intl.DateTimeFormat – Accessed 2026-03-09
Use Case: Global Enterprise HR System#
Who Needs This#
An enterprise software team (10-50 developers) building or extending an HR/HRIS (Human Resource Information System) that manages employees across multiple countries with different calendar systems. The system handles hiring dates, contract periods, leave management, payroll cycles, and holiday calendars.
Why They Need It#
A global HR system must display dates in each employee’s local calendar system:
- Saudi Arabia office: Employee contracts specify start dates in Hijri. Leave balances accrue per Hijri year. National holidays follow the Hijri calendar (Eid al-Fitr, Eid al-Adha).
- Iran office: Employment records use Jalali dates. The Iranian work week runs Saturday through Wednesday (Thursday and Friday are the weekend).
- Thailand office: Official documents display Buddhist Era year (2569 BE, not 2026 CE). Thai national holidays use Gregorian dates but are displayed in Buddhist calendar format.
- Japan office: Some formal HR documents use Japanese Imperial era dates (Reiwa 8, not 2026).
- Ethiopia office: The Ethiopian calendar is 7-8 years behind Gregorian, with 13 months. Ethiopian public holidays follow the Ethiopian calendar.
When a headquarters-based HR manager views employee records across these offices, the system must coherently display and compute dates across all these calendar systems while maintaining a single internal representation.
Requirements#
Hard requirements:
- Display dates in each employee’s local calendar system
- Support for at least: Gregorian, Hijri (Umm al-Qura), Jalali, Buddhist, Japanese Imperial era
- Leave balance computation respecting local calendar (e.g., “X days per Hijri year”)
- Holiday calendar management per country (including non-Gregorian holiday dates)
- Cross-calendar date comparison (sorting employees by hire date regardless of calendar system)
- Report generation with dates in configurable calendar format
- Audit trail showing both Gregorian and local calendar dates
Soft preferences:
- Ethiopian calendar support
- Indian national calendar support
- Configurable week start per country
- Multi-calendar date picker in the admin interface
- Bulk import/export with calendar-aware date parsing
Constraints#
- Enterprise compliance requirements limit dependency choices
- System must be maintainable by a team that is not calendar-i18n specialists
- Performance: HR systems process thousands of employees; date conversions must not bottleneck
- Legacy database schema uses Gregorian DATE columns exclusively
- Multi-year contracts (employment dates spanning decades) must remain accurate
Why This Solution Fits#
Core Architecture: Gregorian Storage, Multi-Calendar Display#
The fundamental architectural decision is the same as every other use case in this survey: store Gregorian, convert at display time.
Every date in the database is a standard ISO 8601 Gregorian date. Calendar conversion happens in two places:
- Display layer: When showing dates to users (Intl.DateTimeFormat + per-calendar libraries as needed)
- Business logic layer: When computing calendar-specific periods (e.g., Hijri year leave accrual)
Technology Stack#
Server-side (Python/Java/Node.js):
For multi-calendar computation, the enterprise has two viable paths:
Path A: Per-calendar libraries
- hijri-converter for Saudi employees
- jdatetime for Iranian employees
- Intl (via Node.js) or ICU bindings for Buddhist/Japanese/Ethiopian
- Pro: Well-tested libraries, minimal dependencies per calendar
- Con: Multiple libraries to maintain and update
Path B: ICU4X
- Single library for all calendar systems
- Pro: Unified API, comprehensive coverage, maintained by Unicode Consortium
- Con: WASM integration complexity, smaller community for support
For most enterprise teams, Path A is more practical because:
- Each calendar library is small and focused
- Only install libraries for calendar systems actually in use
- Easier to audit and maintain individual dependencies
- Path B makes sense when supporting 5+ calendar systems
Client-side (JavaScript):
Intl.DateTimeFormat covers all display formatting needs:
- Each employee profile stores a
preferred_calendarsetting - The frontend passes this to Intl.DateTimeFormat as the
calendaroption - One line of code supports all calendar systems for display
Leave and Accrual Computation#
The trickiest business logic: computing leave balances per-calendar-year.
An employee in Saudi Arabia with “30 days per Hijri year” starts their leave year on 1 Muharram, not January 1. Computing the accrual period requires:
- Determine the current Hijri year (hijri-converter)
- Compute start and end of the Hijri year in Gregorian (for database queries)
- Count working days in the period (accounting for local holidays)
- Compare against the leave allowance
This computation must run per-employee, per-calendar. An employee in Iran has leave accruing from 1 Farvardin (Nowruz), while an employee in the US has leave from January 1.
Holiday Calendar Management#
National holidays in non-Gregorian calendar countries require annual computation:
- Saudi: Eid al-Fitr (1-3 Shawwal), Eid al-Adha (10-12 Dhul Hijjah) – Hijri dates that vary in Gregorian by ~11 days per year
- Iran: Nowruz (1 Farvardin), other national holidays on fixed Jalali dates
- Thailand: Most holidays on fixed Gregorian dates, some Buddhist holidays vary
- Japan: Golden Week, Coming of Age Day, etc. – fixed Gregorian or “nth Monday”
Recommended approach: A holiday configuration table that supports both:
- Fixed Gregorian dates (“January 1”)
- Calendar-system dates (“1 Muharram in Hijri” or “1 Farvardin in Jalali”)
A yearly batch job converts calendar-system holidays to Gregorian dates for the upcoming year, populating a materialized holiday table for fast lookup.
What This Solution Does NOT Cover#
- Payroll calculation: Calendar internationalization provides dates; payroll rules (tax, social security, overtime) are jurisdiction-specific business logic.
- Work schedule patterns: Different countries have different work weeks (5-day, 6-day, shifts). This is a scheduling concern, not a calendar concern.
- Time zone management: Covered in 1.224 Timezone Handling.
Risk Assessment#
Medium risk: The complexity comes from managing multiple calendar systems simultaneously, not from any single calendar library being unreliable. The key risk is:
- Maintenance burden: Each calendar library is a separate dependency to monitor. If one is abandoned, the enterprise team must find a replacement or fork.
- Edge cases: Cross-calendar comparisons (e.g., sorting employees by seniority across calendar systems) require careful conversion to a common base (Gregorian).
- Regulatory changes: Countries occasionally change holiday rules or calendar conventions. The system must support configuration updates without code changes.
Mitigation: Use Gregorian as the canonical internal representation. Calendar conversion at the display and business logic layers is always reversible and testable. Unit test all calendar conversions against known reference dates.
Sources#
- hijri-converter – Accessed 2026-03-09
- jdatetime – Accessed 2026-03-09
- ICU4X – Accessed 2026-03-09
- MDN Intl.DateTimeFormat – Accessed 2026-03-09
Use Case: Government/Civic Application#
Who Needs This#
A software contractor or government IT team building applications for a government that officially uses a non-Gregorian calendar system. Primary targets:
- Iran: All government systems use the Solar Hijri (Jalali) calendar
- Saudi Arabia: Government and civil systems use the Hijri calendar
- Thailand: Official documents use the Buddhist Era year
- Ethiopia: Government systems use the Ethiopian calendar
- Japan: Government forms use Japanese Imperial era dates
- Taiwan: Some official contexts use the ROC (Republic of China) era
Why They Need It#
Government applications are not choosing to support a non-Gregorian calendar – they are legally required to. The non-Gregorian calendar is the primary system, and Gregorian is secondary or absent.
Specific requirements by country:
Iran: National ID cards, tax forms, court documents, school calendars, and all government correspondence use Jalali dates. The fiscal year starts on 1 Farvardin (Nowruz, ~March 20). Government websites and e-services must display exclusively in Jalali.
Saudi Arabia: Government contracts, court judgments, national ID (Iqama) expiration dates, and Hajj/Umrah permits all use Hijri dates. The Saudi fiscal year historically followed Hijri, though it has transitioned to Gregorian for budgetary purposes (2016).
Thailand: National ID cards display Buddhist Era year (2569 BE). Government websites, official gazettes, and tax documents use the Buddhist calendar. The Thai government fiscal year runs October 1 to September 30 with Buddhist Era years.
Ethiopia: Government communications, fiscal year (starts 1 Meskerem, ~September 11), and official documents all use the Ethiopian calendar. The Ethiopian fiscal year and Gregorian fiscal year start at different times.
Japan: Formal government documents (passports, driver’s licenses, tax forms) display dates in Japanese Imperial era format (令和8年 for 2026). While Gregorian dates are increasingly accepted, era dates remain the formal standard.
Requirements#
Hard requirements:
- Primary calendar system as the default display throughout the application
- Calendar-specific date input (date pickers in the target calendar system)
- Calendar arithmetic for business logic (fiscal year computation, deadline calculation, age computation)
- Number system appropriate to the locale (Arabic-Indic for Arabic, Thai for Thai)
- Official formatting patterns per government standard
- Accessibility compliance (government applications often have strict accessibility requirements)
- Offline capability (for field workers, remote offices)
Soft preferences:
- Secondary Gregorian display (for international interoperability)
- Dual-calendar printing on official documents
- Integration with government databases (which may use either calendar system)
- Long-term archival date support (historical records spanning decades)
- Migration from legacy systems that may store dates in the local calendar
Constraints#
- Government procurement processes may restrict to approved technology stacks
- Security requirements may prohibit certain third-party dependencies
- Must support older browsers and devices used in government offices
- Data sovereignty requirements may prohibit cloud-based i18n services
- Must work in air-gapped environments (military, secure government networks)
- Long support lifetimes (government contracts often span 5-10+ years)
Why This Solution Fits#
Per-Country Recommendations#
Iran (Jalali):
The most straightforward case due to the maturity of Jalali libraries.
- Backend: jdatetime (Python) – drop-in datetime replacement, Django integration
- Frontend: jalaali-js + Intl.DateTimeFormat (calendar: ‘persian’)
- Date picker: Persian date picker components (react-multi-date-picker with Jalali, or custom built on jalaali-js)
The Iranian government’s digital services use these exact libraries in production. The ecosystem is proven.
Saudi Arabia (Hijri):
More complex due to the Hijri accuracy question.
- Backend: hijri-converter (Python) with Umm al-Qura – matches the Saudi government’s official calendar
- Frontend: Intl.DateTimeFormat (calendar: ‘islamic-umalqura’)
- Note: Government systems should explicitly state “Umm al-Qura” calendar on all interfaces for clarity
Thailand (Buddhist):
The simplest case – Buddhist Era is a 543-year offset from Gregorian.
- Backend: No library needed. Add 543 to the Gregorian year.
- Frontend: Intl.DateTimeFormat (calendar: ‘buddhist’, locale: ’th-TH’)
- Date picker: Any standard date picker with Buddhist Era year display
Ethiopia (Ethiopian):
The most challenging case due to poor library ecosystem.
- Backend: Custom conversion code (the algorithm is simple – 13 months, fixed lengths, known epoch) or ICU4X
- Frontend: Intl.DateTimeFormat (calendar: ’ethiopic')
- Date picker: Custom build required (no off-the-shelf Ethiopian date picker)
- Risk: No mature, production-grade Ethiopian calendar library exists. Government teams may need to implement and maintain their own.
Japan (Imperial Era):
Well-supported by Intl.DateTimeFormat.
- Backend: No library needed. Use standard datetime with Intl for formatting.
- Frontend: Intl.DateTimeFormat (calendar: ‘japanese’)
- Date picker: Standard date picker with era year display overlay
Architecture for Government Systems#
┌─────────────────────────────────┐
│ Application Layer │
│ │
│ ┌─────────────┐ ┌───────────┐ │
│ │ Business │ │ Display │ │
│ │ Logic │ │ Layer │ │
│ │ (calendar │ │ (Intl + │ │
│ │ arithmetic)│ │ calendar │ │
│ └──────┬──────┘ │ option) │ │
│ │ └─────┬─────┘ │
│ ┌──────▼──────────────▼─────┐ │
│ │ Calendar Configuration │ │
│ │ - primary_calendar │ │
│ │ - secondary_calendar │ │
│ │ - number_system │ │
│ │ - week_start │ │
│ │ - fiscal_year_start │ │
│ └──────┬────────────────────┘ │
│ │ │
│ ┌──────▼──────┐ │
│ │ Gregorian │ │
│ │ Database │ │
│ │ (ISO 8601) │ │
│ └─────────────┘ │
└─────────────────────────────────┘Key principle: The calendar system is a configuration parameter, not a code fork. The same codebase should support Iranian, Saudi, Thai, and Ethiopian deployments by changing configuration, not rewriting date handling code.
What This Solution Does NOT Cover#
- Government-specific workflows: Procurement, permitting, licensing – these are business logic built on top of the date infrastructure.
- Legacy data migration: Converting historical dates stored in local calendar formats to Gregorian. This requires per-system analysis.
- Identity document generation: Producing properly formatted national IDs, passports, or other documents with correct calendar formatting. This involves print layout, not calendar computation.
Risk Assessment#
Medium risk: The primary risks are:
- Ethiopian calendar gap: No production-grade library exists. Government teams must implement or maintain their own conversion code. This is a real risk for Ethiopian government IT projects.
- Long-term support: Government contracts span 5-10 years. Library abandonment (especially for smaller ecosystems like Ethiopian) is a real concern. Vendoring library source code is recommended.
- Hijri ambiguity: Saudi government may update the Umm al-Qura calendar for policy reasons. The application must be updateable when new Umm al-Qura tables are published.
- Era transitions: A new Japanese Imperial era could be declared during the application’s lifetime. Intl.DateTimeFormat handles this via browser updates, but offline/air-gapped systems need manual updates.
Sources#
- jdatetime – Accessed 2026-03-09
- hijri-converter – Accessed 2026-03-09
- ICU4X – Accessed 2026-03-09
- MDN Intl.DateTimeFormat – Accessed 2026-03-09
Use Case: Hebrew Religious Application#
Who Needs This#
A developer building a Jewish religious/liturgical application: synagogue management software, a daily prayer (tefillah) companion, a Jewish holiday calendar, or a Torah study tool. The user base spans observant Jewish communities worldwide – primarily in Israel, the United States, Canada, United Kingdom, France, and Argentina.
Why They Need It#
Jewish religious life is deeply intertwined with the Hebrew calendar. Unlike secular calendar needs where display formatting suffices, religious applications require precise computation of:
Holiday dates: Rosh Hashanah, Yom Kippur, Sukkot, Simchat Torah, Chanukah, Purim, Passover, Shavuot, and dozens of minor holidays, fast days, and commemorations. Each has specific rules for when it occurs in the Hebrew calendar, and some have different observance dates in Israel vs. the Diaspora.
Shabbat times: Candle-lighting time (typically 18 minutes before sunset on Friday) and Havdalah time (after three stars appear on Saturday night) vary by geographic location and time of year. These are not fixed times – they must be computed for each city.
Zmanim (halachic times): Prayer times defined by solar position: Alot Hashachar (dawn), Netz (sunrise), Sof Zman Shma (latest Shma), Sof Zman Tefillah (latest Amidah), Chatzot (midday), Mincha Gedolah (earliest afternoon prayer), Shkia (sunset), Tzeit Hakochavim (nightfall). These vary daily and by location.
Torah reading schedule: The weekly Torah portion (parashat hashavua) follows a fixed annual cycle with special readings on holidays. The schedule differs between Israel (where Simchat Torah is on Shmini Atzeret) and the Diaspora.
Omer counting: A 49-day count between Passover and Shavuot, each day with a specific liturgical designation.
Requirements#
Hard requirements:
- Hebrew-Gregorian bidirectional date conversion
- Hebrew calendar arithmetic (current Hebrew year, month, day)
- Holiday computation for all major and minor Jewish holidays
- Diaspora vs. Israel holiday observance rules
- Shabbat candle-lighting and Havdalah times per location
- Zmanim computation per location and date
- Hebrew date display in both Hebrew and transliterated English
- Torah reading schedule (parashat hashavua)
Soft preferences:
- Omer counting with liturgical designations
- Daf Yomi (daily Talmud study) tracking
- Yahrzeit (memorial anniversary) computation
- Molad (new moon) announcements
- Multi-location support (user travels between cities)
- Push notifications for candle-lighting times
Constraints#
- Precision matters: Shabbat times that are off by even a few minutes are religiously problematic for observant users
- Must handle the edge cases of the Hebrew calendar (variable month lengths, postponement rules, leap year with 13 months)
- Small development team (often 1-3 developers)
- Often volunteer/community projects with limited budget
- Must work offline (many observant users do not use phones on Shabbat but may check times beforehand)
Why This Solution Fits#
hebcal: The Complete Solution#
hebcal (@hebcal/core + @hebcal/hdate + @hebcal/leyning) is effectively the only serious option for this use case. No other library provides comparable coverage of Jewish liturgical calendar features.
What hebcal computes:
- All Hebrew calendar computations (date conversion, arithmetic, month lengths)
- Holiday dates for all major, minor, and modern Israeli holidays
- Diaspora vs. Israel observance differences (e.g., second day of festivals)
- Shabbat candle-lighting times for any latitude/longitude
- Havdalah times (configurable: 42 or 72 minutes, or three-star computation)
- Full zmanim suite (all halachic prayer times)
- Torah reading schedule with leyning (specific Torah portions to read)
- Omer count with sefira designations
- Daf Yomi page numbers
- Molad times
- Yahrzeit computation (accounting for leap years)
What hebcal does NOT do:
- Calendar UI rendering (pair with FullCalendar or a custom grid)
- Push notifications (application infrastructure concern)
- Halachic decision-making (the app computes times; the user consults their rabbi)
Architecture#
User App → hebcal (@hebcal/core)
├── Hebrew date conversion
├── Holiday computation
├── Shabbat/zmanim times (requires lat/lng)
└── Torah reading schedule
Display → Intl.DateTimeFormat (calendar: 'hebrew')
└── Hebrew date formatting in any localeFor a typical synagogue management application:
- User sets their location (latitude/longitude)
- hebcal computes Shabbat times, holiday dates, and Torah readings for the year
- The application caches these results and serves them to users
- Intl.DateTimeFormat handles display formatting
License Consideration#
hebcal’s core package uses GPL-2.0. For a community/synagogue application, this is typically fine – the application is not being sold. For a commercial product, the GPL requires that the entire work be distributed under GPL-compatible terms.
Options for commercial applications:
- Use hebcal under GPL and open-source your application
- Contact the hebcal maintainer about commercial licensing
- Use only
@hebcal/hdate(check its specific license) and implement holiday computation independently - Use Intl.DateTimeFormat for display + implement zmanim computation independently (published algorithms exist)
Zmanim Accuracy#
Zmanim computation requires:
- Solar position calculation (sunrise, sunset for a given date and location)
- Halachic opinion application (different rabbinical authorities define dawn and nightfall differently)
hebcal uses the NOAA solar position algorithm, which is accurate to within seconds. The halachic opinions (e.g., R’ Moshe Feinstein’s definition of Alot Hashachar vs. the Geonim’s definition) are configurable.
For location-dependent times, accuracy depends on the precision of the latitude/longitude input. A city-level approximation (to 2 decimal places) is sufficient for most purposes. Mountainous or coastal locations may need adjustment.
What This Solution Does NOT Cover#
- Kashrut (dietary law) calendars: Tracking which foods are permitted when (e.g., chametz before Passover) is a business logic concern.
- Multi-religion calendars: Supporting both Hebrew and Islamic calendars in one application requires separate library stacks.
- Calendar UI: hebcal computes dates; you still need a calendar UI library (see 1.221) for visual rendering.
Risk Assessment#
Low risk: hebcal has been maintained since 1994, making it one of the oldest continuously maintained open-source projects in the calendar space. Its computations are verified against published Hebrew calendar tables and used by millions of Jews worldwide through hebcal.com.
The GPL license is the primary risk for commercial applications. Evaluate carefully before integrating into proprietary software.
Sources#
- hebcal – Accessed 2026-03-09
- Hebcal.com – Accessed 2026-03-09
- NOAA Solar Calculator – Reference implementation
- Hebrew Calendar Wikipedia – Accessed 2026-03-09
Use Case: Iranian SaaS Developer#
Who Needs This#
A developer or small team (2-5 people) building a SaaS product for the Iranian market. Examples: project management tool, appointment booking system, HR platform, accounting software. The product’s primary audience speaks Persian and expects Jalali dates everywhere.
Why They Need It#
In Iran, the Solar Hijri (Jalali) calendar is not optional – it is the default. Every date in the application must display in Jalali format: today is 18 Esfand 1404, not March 9, 2026. Date pickers, calendars, reports, invoices, and notifications all use Jalali dates. An application that displays Gregorian dates is immediately perceived as foreign and unsuitable for business use.
Beyond display, the application needs Jalali date arithmetic: “show all tasks due this month” means Esfand 1404, not March 2026. “Send a reminder 3 days before the deadline” requires subtracting days in Jalali-aware context. Date ranges, filters, and reports must all operate in the Jalali calendar.
Requirements#
Hard requirements:
- All dates displayed in Jalali format (1404/12/18, not 2026/03/09)
- Jalali date picker for user input
- Jalali date arithmetic (add days/months, compute date ranges)
- Persian digit display (۱۴۰۴ not 1404) – configurable
- Persian month and weekday names
- Week starts on Saturday (Iranian convention)
- Works with standard databases (store Gregorian, display Jalali)
Soft preferences:
- Support for both Jalali and Gregorian display (for users who prefer Gregorian)
- Jalali-aware relative dates (“۲ روز پیش” / “2 days ago” in Persian)
- Integration with popular frameworks (Django, React, Vue)
- RTL text and layout support throughout
Constraints#
- Small team, limited time for i18n infrastructure
- Budget-conscious (preferring open-source)
- Need production-ready libraries, not experimental projects
- Must integrate with existing database schema (PostgreSQL DATE columns)
Why This Solution Fits#
Python Backend (Django)#
jdatetime is the definitive choice:
- Drop-in replacement for Python’s datetime module
- JalaliDateField and JalaliDateTimeField for Django models
- Stores Gregorian dates in the database (PostgreSQL-compatible)
- Displays Jalali in Django admin and forms automatically
- strftime/strptime with Persian month names
- Mature, production-proven in major Iranian applications
The architectural pattern: PostgreSQL stores DATE columns in Gregorian. Django
model fields use jdatetime’s JalaliDateField, which transparently converts between
Gregorian (storage) and Jalali (display). All date queries in the ORM use Gregorian
under the hood.
JavaScript Frontend#
jalaali-js for conversion + Intl.DateTimeFormat for formatting:
- jalaali-js converts dates for display and input processing (~2 KB)
- Intl with
calendar: 'persian'andnumberingSystem: 'arabext'for formatted output - Produces “۱۸ اسفند ۱۴۰۴” natively, no formatting library needed
date-fns-jalali as an alternative if the team already uses date-fns:
- Familiar date-fns API with Jalali calendar awareness
- Tree-shakeable, includes Jalali-aware
format(),addDays(),startOfMonth() - Slightly larger bundle but better developer experience
Date Picker#
Most Persian SaaS applications use either:
- A custom date picker built on jalaali-js (common in React apps)
- An existing Jalali date picker component (several exist in the React/Vue ecosystem)
- FullCalendar with Persian locale and
direction: 'rtl'for scheduling views
What This Solution Does NOT Cover#
- Hijri (Islamic lunar) calendar: Different from Jalali. If the application also serves Arabic-speaking users, a separate Hijri solution is needed.
- Prayer times or religious dates: Use dedicated libraries (not covered here).
- Full RTL layout: Beyond dates, the entire application needs RTL CSS. This is a broader i18n concern.
Risk Assessment#
Low risk: jdatetime and jalaali-js are the most mature non-Gregorian calendar libraries available. Both have years of production use in major Iranian applications. The Jalali algorithm is deterministic – no ambiguity, no accuracy concerns.
Migration path: If the TC39 Temporal proposal ships with calendar: 'persian'
support (expected), date-fns-jalali and jalaali-js can be gradually replaced with
native Temporal calls. jdatetime (Python) remains needed regardless.
Sources#
- jdatetime – Accessed 2026-03-09
- jalaali-js – Accessed 2026-03-09
- date-fns-jalali – Accessed 2026-03-09
Use Case: Islamic Finance Application#
Who Needs This#
A fintech team (5-15 developers) building Shariah-compliant financial products: Islamic banking, sukuk (Islamic bonds), takaful (Islamic insurance), or Islamic investment platforms. The team operates in or serves customers in Saudi Arabia, UAE, Malaysia, Indonesia, Turkey, or other Muslim-majority markets.
Why They Need It#
Islamic finance products are structured around the Hijri calendar. This is not a display preference – it is a legal and regulatory requirement:
- Murabaha contracts: Cost-plus financing where profit margins are calculated over Hijri month periods. A 12-month Murabaha means 12 Hijri months (approximately 354 days), not 12 Gregorian months (approximately 365 days).
- Zakat calculation: The annual wealth tax is due after one Hijri year of asset holding. Computing the Zakat due date requires Hijri date arithmetic.
- Ramadan-linked products: Special financing offers tied to Ramadan start and end dates require accurate Hijri-to-Gregorian conversion.
- Sukuk maturity dates: Bond-equivalent instruments may specify maturity in Hijri dates per the issuing authority’s calendar.
- Regulatory reporting: Some financial regulators in Muslim-majority countries require Hijri dates on official filings.
An 11-day discrepancy (the difference between 12 Hijri months and 12 Gregorian months) translates directly into financial calculation errors. Getting Hijri dates wrong is not a UX issue – it is a compliance violation.
Requirements#
Hard requirements:
- Accurate Hijri-Gregorian bidirectional conversion
- Hijri date arithmetic (add Hijri months, compute Hijri date ranges)
- Support for the specific Hijri calendar variant required by the target jurisdiction (Umm al-Qura for Saudi, potentially different for others)
- Auditability: ability to document which calendar method was used for any given computation
- Arabic numeral display (Arabic-Indic digits: ١٢٣٤٥)
- RTL layout for Arabic-language interfaces
Soft preferences:
- Multi-method support (allow switching between Umm al-Qura and local calendars)
- Holiday awareness (Eid al-Fitr, Eid al-Adha, Islamic New Year)
- Integration with existing financial calculation engines
- Compliance documentation for auditors
Constraints#
- Financial accuracy is non-negotiable – rounding errors and off-by-one issues have regulatory consequences
- May need to support multiple Hijri calendar methods for different jurisdictions
- Auditors will ask: “Which Hijri calendar method does your system use?”
- Cannot depend on browser-native Intl alone (server-side computation required)
- Security and compliance standards may restrict third-party dependencies
Why This Solution Fits#
Server-Side Computation (Python)#
hijri-converter is the foundation:
- Umm al-Qura calendar (Saudi official): covers 1356-1500 AH (1937-2076 CE)
- Hijri date arithmetic for contract period computation
- Validates Hijri dates (prevents impossible dates like Sha’ban 30 in a 29-day month)
- Pure Python, no external dependencies, easy to audit
Architectural pattern:
- Store all dates internally as Gregorian (ISO 8601) in the database
- Store the Hijri calendar method used alongside each date (e.g., “umm-al-qura”)
- Convert at the business logic layer for Hijri-based financial calculations
- Convert at the display layer for Hijri date presentation
- Log all conversions for audit trail
Multi-Jurisdiction Support#
The key architectural challenge: different countries use different Hijri calendars. A platform serving both Saudi and Indonesian customers must handle both Umm al-Qura and Indonesian Hijri dates.
Recommended approach:
- hijri-converter with Umm al-Qura as the default
- Configuration per jurisdiction or per user for alternative calendar methods
- Clear documentation in the UI: “Dates shown in Umm al-Qura calendar”
- For sighting-based jurisdictions: administrative override capability (a human marks the month transition after the official sighting announcement)
Frontend Display#
Intl.DateTimeFormat with calendar: 'islamic-umalqura':
- Formats Hijri dates in Arabic with Arabic-Indic numerals
- Zero bundle cost
- Combined with
numberingSystem: 'arab'for ١٤٤٧ format
For complex financial documents (PDFs, reports), server-side rendering with hijri-converter ensures consistency between displayed and computed dates.
What This Solution Does NOT Cover#
- Prayer times: Not relevant to financial products. Use a dedicated library if your platform also shows prayer times.
- Moon sighting integration: No library can automate sighting-based calendar determination. This requires a manual administrative process or API integration with a sighting authority (none of which have standardized APIs).
- Shariah compliance validation: This is a business logic and legal concern, not a calendar library concern. Libraries provide accurate dates; compliance teams determine what those dates mean for contracts.
Risk Assessment#
Medium risk: hijri-converter is well-tested and uses the Umm al-Qura calendar, which is the most widely accepted standard. However:
- The 1-2 day discrepancy between Umm al-Qura and other Hijri methods is a permanent source of complexity. Document your method choice.
- hijri-converter covers dates through 1500 AH (2076 CE). Financial instruments with maturity dates beyond 2076 would exceed the table range.
- The library is maintained by a single developer. For a financial application, evaluate forking or vendoring the source code (MIT licensed) to ensure long-term availability.
Mitigation: Vendor the hijri-converter source code into your codebase. The Umm al-Qura tables are published data, not proprietary algorithms. Even if the library is abandoned, the data remains valid and the code is auditable.
Sources#
- hijri-converter – Accessed 2026-03-09
- AAOIFI Shariah Standards – Islamic finance regulatory body
- Umm al-Qura Calendar – Saudi official calendar
- Islamic Financial Services Board – Regulatory standards
S4: Strategic
S4: Strategic Selection – Calendar Internationalization#
Methodology#
Long-term viability assessment of calendar internationalization approaches, evaluating:
- Standards alignment: How well does each approach align with evolving web standards (Temporal API, ICU4X, CLDR evolution)?
- Ecosystem momentum: Is the community growing, stable, or declining?
- Organizational backing: Who maintains this, and what is their incentive structure?
- Technology risk: Architecture choices, dependency health, sunset risks
- Strategic paths: Conservative, Forward-looking, and Portable approaches
Time Horizon#
Analysis considers a 3-5 year commitment window (2026-2031), appropriate for internationalization infrastructure that becomes embedded in an application’s core.
Sources#
- Unicode Consortium roadmaps and publications
- TC39 proposal status and meeting notes
- GitHub contributor and release data for all surveyed libraries
- npm and PyPI download trends
- Browser vendor i18n implementation plans
- CLDR release schedule and coverage plans
Calendar i18n Ecosystem Maturity Assessment#
Maturity Model#
Calendar internationalization libraries span a wide range of maturity. This assessment uses a five-level maturity model:
| Level | Description | Indicators |
|---|---|---|
| 5 - Standard | Platform-native or standard-body maintained | Intl, Temporal, ICU4X |
| 4 - Production | Widely used, well-tested, actively maintained | jdatetime, hebcal, Babel |
| 3 - Capable | Functional, moderate adoption, maintenance ongoing | hijri-converter, jalaali-js |
| 2 - Emerging | Works but limited adoption, uncertain maintenance | lunardate, chinese-lunar-calendar |
| 1 - Sparse | Minimal library support, gaps in coverage | Ethiopian, Indian (Saka), Coptic |
Per-Calendar-System Assessment#
Gregorian + Locale Formatting (Level 5)#
Status: Completely solved. Intl.DateTimeFormat, Babel, date-fns, and dozens of other libraries handle Gregorian date formatting with locale awareness. No gaps.
Ecosystem health: Maintained by browser vendors (Intl), the Pallets project (Babel), and large open-source communities (date-fns). No viability concerns.
Persian/Jalali (Level 4)#
Status: The gold standard for non-Gregorian calendar libraries. Production-grade options in both Python (jdatetime) and JavaScript (jalaali-js). Active maintenance, comprehensive test suites, real-world production usage at scale.
Ecosystem health: Driven by the Iranian tech community (~90 million users). Multiple redundant libraries in each ecosystem. Even if one library is abandoned, alternatives exist.
Gap: No unified full-stack solution (separate Python and JS libraries). Temporal will eventually unify the JS side.
Islamic/Hijri (Level 3)#
Status: Python ecosystem is solid (hijri-converter). JavaScript ecosystem is fragmented – no single authoritative library for Hijri arithmetic. Intl handles display formatting well.
Ecosystem health: hijri-converter is single-maintainer but well-coded and MIT licensed. JavaScript options are tied to deprecated ecosystems (Moment.js) or have minimal adoption.
Gap: No production-grade standalone JavaScript library for Hijri date arithmetic. This is the most significant gap in the calendar i18n ecosystem given the 1.8 billion potential users.
Outlook: Temporal will fill the JavaScript arithmetic gap when it ships. Until then, ICU4X WASM is the best option for JavaScript Hijri computation.
Hebrew (Level 4)#
Status: hebcal is comprehensive and uniquely capable. No other calendar library in any ecosystem matches its depth of domain-specific features (holidays, zmanim, Torah readings, Omer counting, Daf Yomi).
Ecosystem health: Maintained since 1994. Deep community investment. GPL license limits commercial adoption but the community nature of most Hebrew calendar applications makes this manageable.
Gap: Python ecosystem is weaker. pyluach provides basic functionality but lacks hebcal’s depth. Commercial applications face GPL licensing friction.
Chinese Lunisolar (Level 2)#
Status: Functional but static. Libraries use lookup tables that work correctly but receive minimal maintenance. No innovation or feature development.
Ecosystem health: Multiple redundant libraries, all doing the same thing (table-based conversion). Low maintenance activity across all of them. The tables work correctly for 1900-2100, so maintenance is less critical than for algorithmic libraries.
Gap: No solar term computation in mainstream libraries. No library planning for post-2100 dates. No high-quality JavaScript library with significant adoption.
Outlook: The static nature of lookup tables means current libraries will continue working correctly until 2100 without any updates. This is a form of accidental long-term viability.
Japanese Imperial Era (Level 5)#
Status: Completely solved by Intl.DateTimeFormat. No dedicated library needed. Browser vendors handle era transitions as part of their ICU/CLDR update process.
Ecosystem health: Maintained by browser vendors as part of the Intl specification. No viability concerns.
Risk: New Imperial era transitions require CLDR updates, which propagate through browser releases in 2-4 months. For applications that need immediate era name support, a small custom mapping table (era name + start date) provides a fast workaround.
Thai Buddhist (Level 5)#
Status: Completely solved by Intl.DateTimeFormat. The Buddhist calendar is a simple year offset from Gregorian, requiring no computation library.
Ecosystem health: No concerns. Browser-native.
Ethiopian (Level 1)#
Status: The weakest ecosystem in this survey. No production-grade library in any language. Intl.DateTimeFormat handles display formatting, but no library provides reliable Ethiopian calendar arithmetic with significant community adoption.
Ecosystem health: Sparse. The Ethiopian developer community is growing but has not yet produced a calendar library comparable to jdatetime or hebcal. Government and enterprise applications in Ethiopia likely use custom implementations.
Gap: Critical gap for Ethiopian government and enterprise applications. ICU4X supports Ethiopian arithmetic, providing one viable path.
Outlook: As Ethiopia’s tech sector grows, library maturity should improve. In the meantime, ICU4X or custom implementation are the recommended paths.
Indian National / Saka (Level 1)#
Status: Minimal library support despite India’s enormous developer population. Intl.DateTimeFormat handles display formatting. No computation library has significant adoption.
Ecosystem health: The Indian National Calendar is rarely used in software contexts. Most Indian applications use Gregorian with Hindi/regional locale formatting. Library demand is low, driving low supply.
Gap: Theoretical gap (1.4 billion people) but minimal practical impact (the calendar is not widely used in software).
Coptic (Level 1)#
Status: Structurally identical to Ethiopian (different era). Intl handles display. No dedicated library needed if Ethiopian conversion is available.
Cross-Ecosystem Patterns#
The Maturity Correlation#
Library maturity correlates directly with:
- Size of developer community using the calendar system daily
- Civil vs. religious usage: Civil calendars (Jalali, Buddhist) drive more library development than calendars used only for religious observances
- Economic development: Calendar communities in countries with large tech sectors (Iran, Israel, Japan) have better library ecosystems
The Intl Floor#
Intl.DateTimeFormat provides a minimum viable floor for all calendar systems. Even the weakest ecosystems (Ethiopian, Coptic, Indian) have reliable display formatting through Intl. The gaps are in computation and domain-specific features.
The Single-Maintainer Pattern#
Most non-Gregorian calendar libraries are maintained by a single dedicated individual:
- hijri-converter: @dralshehri
- jdatetime: @slashmili
- jalaali-js: @jalaali org (small team)
- hebcal: @mjradwin
This is a structural risk but also reflects the reality that calendar library maintenance is a niche specialty with a small pool of qualified contributors. MIT/BSD licensing mitigates the risk through fork potential.
Sources#
- GitHub contributor data for all surveyed libraries – Accessed 2026-03-09
- npm and PyPI download statistics – Accessed 2026-03-09
- Unicode CLDR coverage reports – Accessed 2026-03-09
- Community discussions on GitHub Issues across surveyed projects – Accessed 2026-03-09
S4 Recommendation: Calendar Internationalization#
Three Strategic Paths#
Path 1: Conservative (Minimize Risk)#
Strategy: Intl.DateTimeFormat for display + dedicated per-calendar libraries for computation. Add libraries only for calendar systems you actively need.
Recommended for: Most applications. Teams that want proven, production-grade solutions with minimal architectural risk.
Stack:
- Display: Intl.DateTimeFormat (all calendar systems, zero cost)
- Hijri computation: hijri-converter (Python)
- Jalali computation: jdatetime (Python) or jalaali-js (JS)
- Hebrew features: hebcal (JS)
- Chinese lunar: lunardate (Python) or chinese-lunar-calendar (JS)
- Other systems: Intl for display, custom code if arithmetic needed
Risk profile: Low. All recommended libraries are proven, well-tested, and MIT or similarly licensed (except hebcal’s GPL). The main risk is library abandonment, mitigated by MIT licensing (fork potential) and small codebases (easy to vendor).
3-year outlook: Stable. When Temporal ships, JavaScript arithmetic libraries can be gradually replaced. Python libraries remain needed regardless.
Path 2: Forward-Looking (Maximize Future-Proofing)#
Strategy: Build on Temporal (polyfill now, native later) + Intl.DateTimeFormat. Minimize calendar-specific library dependencies.
Recommended for: Greenfield JavaScript applications starting in 2026 that want to minimize future migration. Teams willing to use a polyfill today for a simpler architecture tomorrow.
Stack:
- Display: Intl.DateTimeFormat
- Arithmetic: @js-temporal/polyfill (today) -> native Temporal (tomorrow)
- Specialized: hebcal, hijri-converter only where Temporal cannot cover (holidays, prayer times, moon sighting)
Risk profile: Medium. Temporal is Stage 3 with browser implementations in progress, but polyfill adds ~40 KB and may have edge cases not matching the final specification. Risk decreases as Temporal reaches Stage 4.
3-year outlook: Temporal ships natively, polyfill is removed, and the application’s calendar code simplifies dramatically. The bet pays off.
Path 3: Portable (Maximize Cross-Platform Consistency)#
Strategy: ICU4X as the universal calendar engine across all platforms. Same library, same data, same results everywhere.
Recommended for: Applications that run in non-browser environments (edge computing, embedded, WASM runtimes, Rust servers) or multi-platform applications that need identical calendar behavior across platforms.
Stack:
- Everything: ICU4X (Rust native, WASM, or FFI bindings)
- Display: ICU4X formatting (or Intl in browsers)
- Arithmetic: ICU4X calendar types
- Data: ICU4X data providers (baked-in or dynamic)
Risk profile: Low-medium. ICU4X is backed by the Unicode Consortium with major corporate funding. The risk is in ecosystem maturity (documentation, community support) rather than organizational viability.
3-year outlook: ICU4X becomes the standard i18n library for non-browser environments. Firefox adoption validates the production readiness. Community grows as more platforms adopt it.
Unified Recommendation#
For the majority of development teams in 2026:
Always use Intl.DateTimeFormat for display formatting. This is non-negotiable. Zero cost, native support, 12+ calendar systems.
Add per-calendar computation libraries only where needed. If you need Jalali arithmetic, add jdatetime/jalaali-js. If you need Hebrew holidays, add hebcal. Do not pre-install libraries for calendar systems your users do not need.
Store dates as Gregorian/UTC internally. Convert at the display and business logic layers. This is the universal architectural pattern confirmed across all four passes.
Monitor the Temporal API. When it ships in browsers, migrate JavaScript calendar arithmetic from libraries to Temporal. This will simplify your dependency tree significantly.
Evaluate ICU4X for non-browser environments. If you need calendar i18n outside a browser (Rust, WASM, edge workers), ICU4X is the strategic choice.
Accept the Hijri accuracy question as a policy decision. Document which Hijri calendar method your application uses. Default to Umm al-Qura unless your users require a different method.
Final Assessment#
Calendar internationalization is a solved problem at the display layer (Intl.DateTimeFormat) and a well-served problem at the computation layer (dedicated libraries per calendar system). The remaining gaps are:
- Islamic calendar arithmetic in JavaScript (solved by Temporal, eventually)
- Ethiopian calendar libraries (solved by ICU4X or custom code)
- Solar term computation (niche, use astronomical libraries)
- Moon-sighting calendar automation (unsolvable by libraries – requires human input)
The ecosystem is mature enough for production use today, with a clear trajectory toward further simplification as Temporal and ICU4X reach broader adoption.
Standards Trajectory: Where Calendar i18n is Heading#
The Temporal API: The Biggest Change Coming#
The TC39 Temporal proposal (Stage 3 as of 2025) is the single most impactful change to calendar internationalization in the JavaScript ecosystem since Intl.DateTimeFormat was standardized in 2012.
What Temporal Adds#
Temporal introduces calendar-aware date types to JavaScript:
Temporal.PlainDatewith acalendarproperty that specifies the calendar system- Calendar-aware arithmetic: adding months to a Persian date gives a Persian result
- Calendar conversion: converting between calendar systems as a first-class operation
Temporal.Calendarobjects that encapsulate calendar system rules
This means JavaScript will natively support:
- Creating a date in any ICU-supported calendar system
- Adding/subtracting years, months, and days in that calendar system
- Comparing dates across calendar systems
- Formatting dates via Intl.DateTimeFormat (already supported)
Impact on Existing Libraries#
When Temporal ships in browsers, several library categories become less necessary:
| Library Category | Current Role | Post-Temporal Role |
|---|---|---|
| jalaali-js | Jalali conversion + arithmetic | Conversion only (arithmetic native) |
| hijri-converter | Hijri conversion + arithmetic | Still needed (Python, server-side) |
| date-fns-jalali | Jalali-aware date utilities | Reduced need (Temporal handles basics) |
| ICU4X (JS) | Universal calendar arithmetic | Reduced need (Temporal overlaps) |
| hebcal | Hebrew calendar + holidays + zmanim | Still needed (holidays/zmanim not in Temporal) |
| lunardate | Chinese lunar conversion | Still needed (Python, server-side) |
Key insight: Temporal reduces the need for calendar arithmetic libraries in JavaScript but does NOT replace:
- Server-side Python/Rust/Go calendar libraries
- Domain-specific features (holidays, prayer times, solar terms)
- Calendar display formatting (still Intl.DateTimeFormat)
Timeline#
- Stage 3: 2025 (current)
- Browser implementation: In progress (Chrome, Firefox, Safari all have experimental implementations)
- Expected broad availability: 2026-2027
- Polyfills available now: @js-temporal/polyfill (~40 KB)
Migration Path#
For applications currently using calendar-specific JS libraries:
- Today: Use Intl.DateTimeFormat (display) + dedicated libraries (arithmetic)
- When Temporal ships: Migrate arithmetic to Temporal, keep dedicated libraries for domain-specific features
- Long-term: Temporal + Intl handle all standard calendar operations; libraries only needed for holidays, prayer times, and other specialized features
ICU4X: The Portable Future#
ICU4X represents the Unicode Consortium’s strategic direction for i18n outside browser environments. Key strategic factors:
Organizational Backing#
ICU4X is funded and developed by the Unicode Consortium with financial support from Google, Amazon, and Mozilla. The same organization maintains:
- Unicode Standard
- CLDR (locale data)
- ICU (C/C++ implementation)
- ICU4J (Java implementation)
This is the strongest possible backing for an i18n library. ICU4X is not a community project that might be abandoned – it is a strategic initiative by the organization that defines internationalization standards.
Adoption Trajectory#
- Firefox: Already uses ICU4X for some Intl operations (replacing C++ ICU calls with Rust/WASM)
- Android: Evaluating ICU4X to reduce the size of its ICU installation
- Embedded/IoT: ICU4X’s small binary size makes it viable where legacy ICU is not
3-5 Year Outlook#
ICU4X will likely become:
- The standard i18n library for Rust applications
- The default i18n backend for WASM applications
- A viable alternative to platform ICU for mobile applications seeking smaller binaries
- The recommended path for server-side applications needing portable i18n
CLDR: The Data Foundation#
CLDR releases twice yearly (April and October). Strategic trends:
Coverage Expansion#
CLDR continues to add:
- New locale data for underserved languages
- Improved calendar system data (month names, formatting patterns)
- Additional calendar systems (though the current 20+ covers most needs)
Data Quality#
CLDR data quality varies by locale. Well-resourced locales (en, zh, ar, ja, ko, de, fr) have comprehensive, well-tested data. Smaller locales may have gaps or less-tested calendar formatting patterns.
Strategic implication: For major world languages, CLDR data (and therefore Intl and ICU4X) is highly reliable. For smaller languages, validate calendar formatting output against native speakers.
Consumption Patterns#
The trend is toward CLDR data being consumed via ICU4X rather than ICU (C++):
- ICU4X’s data-code separation allows selective data loading
- ICU4X’s compact binary format reduces data size
- ICU (C++) remains dominant but ICU4X is the future direction
Calendar-Specific Library Viability#
High Viability (3-5 Year Safe Bet)#
jdatetime (Python, Jalali): The Iranian developer community is large and active. jdatetime has years of production use and active maintenance. Even if the primary maintainer steps away, community forks would likely continue development.
jalaali-js (JavaScript, Jalali): Same community backing as jdatetime. Tiny, focused, well-tested. Low maintenance burden makes long-term viability likely even with minimal active development.
hebcal (JavaScript, Hebrew): Maintained since 1994 (32 years). The longest- running calendar library in this survey. Deep community investment from the Jewish tech community. Very high confidence in continued maintenance.
Babel (Python, locale formatting): Maintained by the Pallets project (same team as Flask). Large user base (~2M weekly PyPI downloads). Extremely high confidence.
Moderate Viability (Workable but Monitor)#
hijri-converter (Python, Hijri): Single maintainer. Good code quality and test coverage. MIT licensed, making community forks viable. The Umm al-Qura data is published and independent of the library. Moderate risk from bus factor.
lunardate (Python, Chinese lunar): Minimal maintenance. Lookup table-based design means it works correctly until 2100 without any maintenance. Low urgency but low investment in the project.
Lower Viability (Use with Caution)#
chinese-lunar-calendar (JS, Chinese lunar): Small community, minimal downloads. Consider vendoring the source code if you depend on it.
moment-hijri (JS, Hijri): Tied to deprecated Moment.js. Active migration away from Moment.js ecosystem. Not recommended for new projects.
Ethiopian calendar libraries: Sparse and immature across all ecosystems. Consider custom implementation or ICU4X.
Technology Risks#
Browser Engine Consolidation#
If browser diversity decreases (more Chromium-based browsers), Intl implementation quality becomes dependent on a single codebase (V8’s ICU integration). Currently, three independent Intl implementations (V8, SpiderMonkey, JavaScriptCore) provide redundancy.
CLDR Data Lag#
New calendar system needs (e.g., a country changing its official calendar, a new Japanese Imperial era) depend on CLDR updates, which propagate to browsers in 2-4 months. For applications requiring immediate updates, ICU4X with custom data providers offers a faster path.
Temporal Delay Risk#
If the Temporal proposal is delayed beyond 2027, the ecosystem remains fragmented across per-calendar libraries. This is a manageable risk – current libraries work well – but it means the hoped-for simplification is deferred.
Sources#
- TC39 Temporal Proposal – Accessed 2026-03-09
- TC39 Meeting Notes – Temporal status updates
- ICU4X Roadmap – Accessed 2026-03-09
- CLDR Release Schedule – Accessed 2026-03-09
- Firefox ICU4X Integration – Accessed 2026-03-09