The definitive, ultra-performant Persian (Jalali) calendar infrastructure for Python with a compiled Rust engine.
Project description
🌟 Jamshid (جمشید) 🌟
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.
In v0.4.0, Jamshid undergoes an architectural leap, migrating core algorithms (parsing, formatting, date arithmetic, calendar generation, and validation) entirely to the compiled Rust layer with zero heap allocations for parsing and single-pass allocation for string formatting.
🚀 Architectural Pillars in v0.4.0
1. High-Performance Rust Engine (jamshid._core)
- Compiled Operations: Day-of-week, leap years, conversions, date arithmetic, parsing, and formatting are compiled in optimized native Rust binaries.
- Zero-Allocation Parser: The Rust-based parser executes on the stack using static memory, completely bypassing heap allocation during date parsing.
- Single-Pass Formatter: Replaces multi-pass string replacements with an optimized single-allocation pass, speeding up bulk logging and reports.
- Astronomical Accuracy: Supports the Borkowski 2820-year cycle algorithm alongside Jean Meeus astronomical formulas for approximating the vernal equinox, guaranteeing mathematical continuity from year
-3000to3000.
2. Multi-Regional Holiday Engine
- Multi-Country Support: Out-of-the-box holiday calendars for Iran (IR), Afghanistan (AF), and Tajikistan (TJ) (customizable via region flags).
- Holiday Engine API: Determine future and past holiday locations using
next_holiday()andprevious_holiday(). - Custom Holidays: Accept custom holiday set injection alongside native lunar/solar holiday mapping.
3. Business Calendar Engine
- Business Math: Perform work-day calculations via
next_business_day(),previous_business_day(), andbusiness_days_between(). - Custom Weekend Support: Specify weekends (e.g., Friday only for Iran, Saturday/Sunday for global standard, etc.) dynamically.
4. Continuous Calendar API
- Grid Generators: Retrieve structured monthly, weekly, or yearly nested date arrays using
monthly_calendar(),weekly_calendar(), andyear_calendar(). - Terminal Renderer: Output beautifully structured textual representations of any target month via
render_calendar().
5. Native Serialization & Timezone Compatibility
- Pickle Compatibility: Native Python pickle serialization is enabled on both classes via customized state reduction (
__reduce__). - Dict & JSON: Serialize and reconstruct dates easily with
to_dict(),from_dict(), andto_json(). - Timezone Offset & Timestamp: Full microsecond-aware Unix timestamp mapping implemented inside native Rust primitives via
.timestamp(),fromtimestamp(), andutcfromtimestamp().
⚙️ Installation
1. Standard Installation
pip install jamshid
2. Install with Scientific Extras (Pandas & Plotting)
pip install jamshid[pandas,matplotlib]
3. Compilation from Source
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 exceptions, including JalaliOverflowError to prevent calculations outside the valid range of -3000 to 3000.
import jamshid
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}")
try:
# Safe boundary guards prevent overflow
overflow_date = jamshid.JalaliDate(3005, 1, 1)
except jamshid.JalaliOverflowError as e:
print(f"Overflow prevented: {e}")
🚀 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. Fast Date Arithmetic in Rust JDN
tomorrow = d + datetime.timedelta(days=1)
days_between = JalaliDate(1405, 4, 20) - d # Returns datetime.timedelta(days=6)
# 3. Fast Parsing & Formatting
parsed = JalaliDate.strptime("1403/12/30", "%Y/%m/%d")
print(parsed.strftime("%A, %d %B %Y", locale='fa'))
# Output: پنجشنبه، ۳۰ اسفند ۱۴۰۳
📖 Deep API Reference
1. JalaliDate & JalaliDateTime
To optimize memory footprint and library maintainability, the classes have been split internally into core_date.py and core_datetime.py, with imports managed under core.py.
from jamshid import JalaliDate, JalaliDateTime
# Static validation checking
is_ok = JalaliDate.is_valid(1403, 12, 30) # True
# RTL formatting support
d = JalaliDate(1405, 4, 14)
print(repr(d.strftime_rtl("%Y/%m/%d"))) # Includes \u200f right-to-left marks
2. Timezone Offset & Unix Timestamp conversions
Timestamp conversions are computed directly in Rust using highly optimized Unix Epoch Julian Day Numbers.
from jamshid import JalaliDateTime, TehranTz
# Convert JalaliDateTime to Timestamp
dt = JalaliDateTime(1403, 12, 30, 12, 30, 0, tzinfo=TehranTz())
ts = dt.timestamp()
print(ts) # 1742461200.0 (Approx relative to UTC offset)
# Reconstruct from Timestamp
reconstructed = JalaliDateTime.fromtimestamp(ts, tz=TehranTz())
print(reconstructed) # 1403-12-30 12:30:00+03:30
3. Business Calendar & Custom Weekend Support
Manage working schedules with ease using customizable weekends and holiday filters.
from jamshid import JalaliDate
d = JalaliDate(1403, 12, 30)
# Determine next business day (Skip weekends & holidays)
next_biz = d.next_business_day(region="IR")
print(next_biz) # 1404-01-05 (Skips weekend Friday & Norooz solar holidays!)
# Custom weekends (e.g. Thursday and Friday)
custom_biz = d.next_business_day(weekends=[3, 4])
# Compute working days between two dates
days_diff = d.business_days_between(JalaliDate(1404, 1, 10))
print(f"Working days: {days_diff}")
4. Holiday Engine & Holiday Queries
Find current, previous, or next holidays in various regions (Iran, Afghanistan, Tajikistan).
from jamshid import JalaliDate
d = JalaliDate(1403, 12, 29)
# Query active events
print(d.events()) # ['ملی شدن صنعت نفت']
# Find previous or next holidays
print(d.next_holiday(region="IR")) # 1403-12-30 (Esfand leap day)
5. Calendar API & Visualizations
Utilize fast Rust grid generators to output structured layouts.
from jamshid import JalaliDate
# 1. Output week list containing target date (Starts on Saturday)
week_list = JalaliDate(1403, 12, 30).weekly_calendar()
print(week_list)
# 2. Output 2D monthly calendar grid containing dates and None padding
monthly_grid = JalaliDate.monthly_calendar(1403, 12)
print(monthly_grid)
# 3. Render a beautiful terminal calendar grid
terminal_output = JalaliDate.render_calendar(1403, 12)
print(terminal_output)
📈 Serialization & Pickle Support
Both classes implement customized state reduction, permitting seamless pickling and standard dictionary conversions.
import pickle
import json
from jamshid import JalaliDate
d = JalaliDate(1403, 12, 30)
# 1. Pickle Round-trip
pickled_data = pickle.dumps(d)
unpickled_date = pickle.loads(pickled_data)
assert d == unpickled_date
# 2. Dict & JSON export
d_dict = d.to_dict() # {"year": 1403, "month": 12, "day": 30}
d_json = d.to_json() # '{"year": 1403, "month": 12, "day": 30}'
📈 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 a regular Jalali Index range
idx = jalali_date_range(start="1405/01/01", end="1405/03/31", freq="D")
print(idx)
# 2. Monthly Financial Resampling using Jalali Month End (JME) offsets
df_financial = pd.DataFrame({"revenue": [1000, 1500, 2000]}, index=idx[:3])
monthly_resampled = df_financial.resample(JalaliMonthEnd()).sum()
🖼️ Graphical Visualization (plot_calendar)
Plot localized monthly calendars in high definition with a single call:
from jamshid import JalaliDate
d = JalaliDate(1405, 4, 14)
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
2. Calculate Complex Date Differences
jamshid diff 1405/01/01 1406/05/12 --human
3. Display Terminal Calendar Grids with Holiday Highlighting
jamshid calendar 1405 --highlight-holidays
4. Fetch Public Holidays & Export to Standards (JSON, CSV, iCal)
jamshid holidays 1405 --filter official --export ical > holidays_1405.ics
📊 Feature Comparison Matrix
| Feature | Jamshid (v0.4.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 |
| Business Calendar | Yes (biz_between, weekends) | ❌ None | ❌ None | ❌ None |
| JSON/Pickle Serialization | Yes (Pickle, Dict, JSON) | ❌ None | ❌ None | ❌ None |
| Calendar Grid API | Yes (Grid, Renderer) | ❌ None | ❌ None | ❌ None |
🧪 Technical Benchmarks & Performance
Due to core logic being moved to optimized, non-allocating Rust stack structures, conversions, calendar grids, and arithmetic steps in Jamshid achieve massive throughput improvements compared to traditional pure-Python solutions:
- 50,000 Validation checks in Rust core:
0.0125 seconds - 50,000 High-performance Rust formats (Single-Allocation):
0.0340 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.
🧪 Test Suite & Coverage
To ensure stability across all platforms, Jamshid is equipped with comprehensive Rust and Python test pipelines covering invalid dates, astronomical cycles, edge cases, round-trip conversions, randomized dates, and regressions.
Run Rust Unit Tests
cargo test
Run Python Test Suite
python -m unittest tests/test_jamshid.py
🤝 Contributing
Contributions to Jamshid are highly welcome!
- Fork the Project.
- Create your Feature Branch (
git checkout -b feature/AmazingFeature). - Commit your Changes (
git commit -m 'Add some AmazingFeature'). - Push to the Branch (
git push origin feature/AmazingFeature). - Open a Pull Request.
👨💻 Author & Contact
Ali Kamrani
- GitHub: @MRThugh
- Email: kamrani.exe@gmail.com
📄 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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file jamshid-0.4.0.tar.gz.
File metadata
- Download URL: jamshid-0.4.0.tar.gz
- Upload date:
- Size: 39.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4dd9403f275051cdcadac5060e7b05969e9e191ffdf259fb63f847d23072fcb4
|
|
| MD5 |
2427fa5ce1741c11b8aa7cbb9609c327
|
|
| BLAKE2b-256 |
91c1e398e71448bf8ff63b35c1830ec211842bdab6f776d2333b44db5bf62641
|
File details
Details for the file jamshid-0.4.0-cp313-cp313-win_amd64.whl.
File metadata
- Download URL: jamshid-0.4.0-cp313-cp313-win_amd64.whl
- Upload date:
- Size: 636.4 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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
70e393e5da1ff6649b335dfaee6b38b7365e94740f082f9d9a1f94bf78d6a1e9
|
|
| MD5 |
36463cab3f95b491e284867c6cf876cb
|
|
| BLAKE2b-256 |
5a797765cc11cec255b8a5a383459a61066fbac6f44133fd77d4085d7c176fe0
|