Skip to main content

A highly accurate and modern Persian (Jalali) calendar library written in Rust and Python.

Reason this release was yanked:

For new version

Project description

🌟 Jamshid (جمشید) 🌟

Python Version Rust Engine License Author Version Persian English

The definitive, ultra-performant Persian (Jalali) calendar infrastructure for Python. Powered by a lightning-fast Rust core, featuring native Pandas integration, multi-regional holiday engines, and rich cultural diagnostics.


📖 Overview

Jamshid (imported as jamshid) is a production-grade, highly performant calendar library designed as a full-scale infrastructure for Jalali-Gregorian date processing in Python.

By combining the speed and type safety of Rust (via PyO3) with Python's standard datetime interfaces, Jamshid offers microsecond-level performance while remaining a drop-in replacement for standard calendar structures.

Whether you are building astronomical utilities, high-frequency financial platforms using Pandas, or localized web services, Jamshid provides the mathematical precision, localized text processors, and cultural database required for modern Persian software engineering.


🚀 Key Architectural Pillars in v0.3.0

1. High-Performance Rust Core (jamshid._core)

  • Compiled Mathematical Operations: Transformation algorithms (Jalali ↔ Gregorian), day-of-the-week determination, and leap-year verifications are processed entirely in natively compiled Rust binaries.
  • Astronomical Accuracy: Supports the highly accurate Borkowski 2820-year cycle algorithm alongside Jean Meeus astronomical formulas for approximating the vernal equinox, guaranteeing mathematical continuity from year -3000 to 3000.

2. Multi-Regional Cultural Engine (jamshid.core)

  • Multi-Country Support: Out-of-the-box holiday calendars for Iran, Afghanistan, and Tajikistan (customizable via region flags).
  • Categorized Events Database: Appropriate classification of events into official, cultural, historical, and religious categories, drawing from both solar and lunar calendars (with tabular fallback systems for distant years).

3. Native Data Science Toolchain (jamshid.pandas_ext)

  • JalaliIndex: A custom Pandas index subclassing the standard Pandas Index layer, permitting native slice filtering, year/month/day properties, and flawless conversions.
  • Custom Frequency Offsets: Native date offsets like JalaliMonthEnd (JME) and JalaliYearEnd (JYE) to streamline Jalali-based financial and accounting resamples.

4. Advanced Persian Linguistic Diagnostics

  • Iterative Digit Converters: Ultra-fast bidirectional converters supporting Persian, English, and Arabic digit scripts.
  • Iterative Num-To-Words: A highly optimized, non-recursive, memory-safe algorithm converting numbers up to Quadrillions into Persian text representation.
  • Text Normalizer: Clean Persian script layouts, fixing non-breaking spaces, semi-spaces (ZWNJs), and Arabic glyph issues.

⚙️ Installation

1. Standard Installation

pip install jamshid

2. Install with Scientific Extras (Pandas & Plotting)

pip install jamshid[pandas,matplotlib]

3. Compilation from Source

For custom optimizations or local contributions, compile directly using maturin:

git clone https://github.com/MRThugh/Jamshid.git
cd Jamshid
pip install maturin setuptools-rust
maturin develop --extras pandas,matplotlib

Requires Python 3.9+ and Rust compiler (M.S.R.V 1.65+).


🛠️ Global Configuration & Exceptions

Jamshid provides robust validation pipelines and descriptive, dual-language exception triggers to ensure validation issues are caught early in the development lifecycle.

import jamshid

# Custom exceptions tailored for Clean Architecture
try:
    # 1404 is not a leap year, so Esfand has 29 days
    invalid_date = jamshid.JalaliDate(1404, 12, 30)
except jamshid.JalaliRangeError as e:
    print(f"Validation failed: {e}")
    # Output: Validation failed: روز 30 برای ماه 12 در سال 1404 (غیرکبیسه) نامعتبر است.
    #         [Day 30 is invalid for month 12 in year 1404 (غیرکبیسه). Max allowed days: 29].

🚀 Quick Start Examples

from jamshid import JalaliDate, JalaliDateTime, TehranTz
import datetime

# 1. Base Instantiation & Standard Compatibility
d = JalaliDate(1405, 4, 14)  # 1405/04/14
dt = JalaliDateTime.now(TehranTz())

# 2. Seamless Gregorian Conversion
g_date = d.to_gregorian()    # Returns standard datetime.date(2026, 7, 5)
jd = JalaliDate.from_date(g_date)

# 3. Simple Spacing Arithmetic
tomorrow = d + datetime.timedelta(days=1)
days_between = JalaliDate(1405, 4, 20) - d  # Returns datetime.timedelta(days=6)

# 4. Humanized Interval Text
birth_date = JalaliDate(1375, 6, 15)
print(birth_date.humanize())  # Output: ۲۹ سال پیش (approx relative to 2026)

# 5. Fast Digit conversion & Formatting
print(d.strftime("امروز %A، %d %B سال %Y", locale='fa'))
# Output: امروز یک‌شنبه، ۱۴ تیر سال ۱۴۰۵

📖 Deep API Reference

1. JalaliDate & JalaliDateTime

Inheriting directly from datetime.date and datetime.datetime respectively, these classes act as drop-in replacements with overridden date properties.

from jamshid import JalaliDate, JalaliDateTime

# Static validation checking
is_ok = JalaliDate.is_valid(1404, 12, 30)  # False

# RTL formatting support (Prevents crooked outputs in mixed LTR/RTL terminals)
d = JalaliDate(1405, 4, 14)
print(repr(d.strftime_rtl("%Y/%m/%d")))  # Includes \u200f right-to-left marks

# Exact Moon Phase Calculations
phase_name, illumination = d.get_moon_phase()
print(f"Moon Phase: {phase_name} | Illumination: {illumination:.2f}%")
# Output: Moon Phase: هلال کاهنده (Waning Crescent) | Illumination: 78.43%

2. Timezones & Tehran Historical DST (TehranTz)

The official Iranian Daylight Saving Time (DST) was legally abolished from 1402 خورشیدی (2023 CE). Jamshid's TehranTz implements correct historical DST offsets (24:00 of 1 Farvardin to 24:00 of 30 Shahrivar) up to 1401 and shuts off DST dynamically starting from 1402.

from jamshid import JalaliDateTime, TehranTz

tz = TehranTz()
# Before 1402 (DST Applied)
dt_1400 = JalaliDateTime(1400, 2, 15, 12, 0, tzinfo=tz)
print(dt_1400.tzname())  # IRDT (+04:30)

# After 1402 (DST Abolished)
dt_1405 = JalaliDateTime(1405, 2, 15, 12, 0, tzinfo=tz)
print(dt_1405.tzname())  # IRST (+03:30)

3. Highly Advanced Age Inquiries (SolarAge)

Computes astronomical age based on actual orbital movement, providing the result in days, months, years, exact fraction decimals, and formatted Persian text.

from jamshid import JalaliDate

birth = JalaliDate(1375, 6, 15)
ref_date = JalaliDate(1405, 4, 14)

age = birth.age_to(ref_date)
print(age.years, "Years,", age.months, "Months,", age.days, "Days")
# Output: 29 Years, 9 Months, 29 Days

print(f"Decimal Solar Age: {age.fraction:.4f}")
# Output: Decimal Solar Age: 29.8282

print(age.to_persian())
# Output: ۲۹ سال و ۹ ماه و ۲۹ روز

4. Continuous Date Interval Containers (JalaliPeriod)

from jamshid import JalaliDate, JalaliPeriod

start = JalaliDate(1405, 1, 1)
end = JalaliDate(1405, 1, 31)
period = JalaliPeriod(start, end)

print(JalaliDate(1405, 1, 15) in period)  # True
print(period.days)  # 30

5. Persian Linguistic Utilities

import jamshid.core as j_utils

# Bidirectional Converters
print(j_utils.to_persian_digits("Calling 09123456789"))  # Calling ۰۹۱۲۳۴۵۶۷۸۹
print(j_utils.to_english_digits("تلفن: ۰۹۱۲۳۴۵۶۷۸۹"))      # تلفن: 09123456789

# Non-Recursive Number-To-Words (Capable of handling huge integers)
print(j_utils.num_to_words(1405623910))
# Output: یک میلیارد و چهارصد و پنج میلیون و ششصد و بیست و سه هزار و نهصد و ده

# Standardize Mixed Spacing & Unicode Glyphs
dirty = "كتاب‌ ها  ميباشد‌"
print(j_utils.normalize_persian(dirty))  # کتاب‌ها میباشد

📈 Pandas & Data Science Suite

Jamshid provides robust structures to carry out analytics, resamples, and aggregations using Jalali dates natively inside Pandas.

import pandas as pd
import jamshid
from jamshid.pandas_ext import JalaliIndex, jalali_date_range, JalaliMonthEnd, JalaliYearEnd

# 1. Generate an regular Jalali Index range
idx = jalali_date_range(start="1405/01/01", end="1405/03/31", freq="D")
print(idx)
# Output: JalaliIndex([1405/01/01, 1405/01/02, ..., 1405/03/31], dtype='object')

# Extract custom properties
print(idx.year)   # pd.Index([1405, 1405, ...])
print(idx.month)  # pd.Index([1, 1, 1, ...])

# 2. DataFrame Integration & Series Accessor
df = pd.DataFrame({
    "g_date": pd.date_range("2026-03-21", "2026-06-21", freq="D")
})

# Convert Gregorian column to JalaliDate objects using accessor
df["j_date"] = df["g_date"].jalali.to_jalali()

# Map properties directly through Series Accessor
df["is_holiday"] = df["j_date"].jalali.is_holiday
df["daily_events"] = df["j_date"].jalali.events

# 3. Monthly Financial Resampling using Jalali Month End (JME) offsets
df_financial = pd.DataFrame({"revenue": [1000, 1500, 2000]}, index=idx[:3])
# Resample on custom monthly boundaries
monthly_resampled = df_financial.resample(JalaliMonthEnd()).sum()

🖼️ Graphical Visualization (plot_calendar)

For reporting, UI rendering, or data notebooks, plot localized monthly calendars in high definition with a single call:

from jamshid import JalaliDate

# Select any day inside the target month
d = JalaliDate(1405, 4, 14)
# Plots Farvardin 1405 grid with today highlighted
fig = d.plot_calendar()
fig.savefig("calendar_july_2026.png")

💻 Professional CLI Reference

Jamshid comes equipped with a comprehensive terminal user interface featuring ANSI colors, export options, and localized reporting.

1. Show Today's Detailed Diagnostics

jamshid today

Outputs current Jalali date, Gregorian representation, localized week name, time, and active holidays.

2. Calculate Complex Date Differences

jamshid diff 1405/01/01 1406/05/12 --human

Prints: Difference: ۱ سال و ۵ ماه و ۱۱ روز بعد

3. Display Terminal Calendar Grids with Holiday Highlighting

jamshid calendar 1405 --highlight-holidays

Outputs the complete grid of 1405 with holidays colored in red.

4. Fetch Public Holidays & Export to Standards (JSON, CSV, iCal)

# Export official holidays to iCal format for Google Calendar/Outlook import
jamshid holidays 1405 --filter official --export ical > holidays_1405.ics

# Export to JSON
jamshid holidays 1405 --filter cultural --export json

📊 Feature Comparison Matrix

Feature Jamshid (v0.3.0) jdatetime persiantools khayyam
Engine Language Rust (compiled PyO3) Pure Python Pure Python Pure Python
Performance Ultra-Fast (Microseconds) Baseline Baseline Moderate
Pandas Support Full (JalaliIndex + Offsets) ❌ None ❌ None ❌ None
Historical Precision Borkowski 2820-yr cycle Arithmetic 33-yr cycle Basic Cycle Arithmetic
Year Range Support -3000 to 3000 1 to 9999 1 to 9999 1 to 9999
Tehran DST Historical Active (Auto-abolished 1402) Constant Offset ❌ None Constant Offset
Multi-Region Holidays Iran, Afghanistan, Tajikistan ❌ None ❌ None ❌ None
Graphical Plotting Matplotlib Integration ❌ None ❌ None ❌ None
Linguistic Utilities Words, Digits, Normalize ❌ None Moderate ❌ None
Interactive CLI Comprehensive JSON/ICS ❌ None ❌ None ❌ None

🧪 Technical Benchmarks & Performance

Due to calculations being processed natively on the Rust stack, conversions, indexing, and arithmetic steps in Jamshid achieve massive throughput improvements compared to traditional pure-Python solutions:

# Simple Benchmark comparison test (Converting 100,000 Dates)
import time
import jdatetime
import jamshid

# jdatetime baseline
t0 = time.time()
for _ in range(100000):
    _ = jdatetime.date.fromgregorian(day=5, month=7, year=2026)
print(f"jdatetime: {time.time() - t0:.4f} seconds")

# Jamshid (Rust PyO3 engine)
t0 = time.time()
for _ in range(100000):
    _ = jamshid.JalaliDate.from_gregorian(2026, 7, 5)
print(f"Jamshid: {time.time() - t0:.4f} seconds")

On modern benchmark hardware, Jamshid operates 4x to 8x faster during batch transformations, making it the premier choice for large-scale databases and data analysis.


🤝 Contributing

Contributions to Jamshid are highly welcome!

  1. Fork the Project.
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature).
  3. Commit your Changes (git commit -m 'Add some AmazingFeature').
  4. Push to the Branch (git push origin feature/AmazingFeature).
  5. Open a Pull Request.

Make sure to run the unit tests prior to opening requests:

python -m unittest discover -s tests

👨‍💻 Author & Contact

Ali Kamrani


📄 License

This software infrastructure is distributed under the MIT License. Feel free to use, adapt, and build upon it in commercial and open-source applications alike.


Jamshid — Redefining Persian Calendar Computing. 🚀

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

jamshid-0.3.1.tar.gz (32.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

jamshid-0.3.1-cp313-cp313-win_amd64.whl (616.6 kB view details)

Uploaded CPython 3.13Windows x86-64

File details

Details for the file jamshid-0.3.1.tar.gz.

File metadata

  • Download URL: jamshid-0.3.1.tar.gz
  • Upload date:
  • Size: 32.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.3

File hashes

Hashes for jamshid-0.3.1.tar.gz
Algorithm Hash digest
SHA256 759db4bf2787a344e07708c6cb7ec896a739a1ea03a4d549b2b5a6dfb7cb422b
MD5 89af37f221a25dd261bb34193bfc46a9
BLAKE2b-256 0f0c87a69c86aa2fb5c9b209654a8be8134511387b03e5967c77424d01cc17c2

See more details on using hashes here.

File details

Details for the file jamshid-0.3.1-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: jamshid-0.3.1-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 616.6 kB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.3

File hashes

Hashes for jamshid-0.3.1-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 fa9fcad0fe43f85c85eab879c0beec338af2d0739a523f8297fb446331e44d50
MD5 85ee82121e35e6602db188ccd7ebb930
BLAKE2b-256 99df4aa4a66cc7031053f5b5a883f3bbbf5276eb68a6b0978e79c531a63652d6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page