Jalali date and datetime with other tools
Project description
PersianTools
PersianTools provides Jalali (Shamsi) dates and datetimes that work just like Python's datetime — plus handy tools for Persian text: digit conversion between Persian, Arabic, and English, character normalization, and numbers to Persian words.
If you know datetime.date and datetime.datetime, you already know JalaliDate and JalaliDateTime. They support the same operations: comparison, arithmetic with timedelta, timezones, strftime/strptime and formatting, hashing, and pickling.
Installation
pip install persiantools
Requires Python 3.9 or newer. No dependencies, except tzdata on Windows for timezone data.
Quick start
>>> from persiantools.jdatetime import JalaliDate, JalaliDateTime
>>> import datetime
>>> JalaliDate.today()
JalaliDate(1405, 4, 12, Jomeh)
>>> JalaliDate(datetime.date(1988, 5, 4)) # Gregorian → Jalali
JalaliDate(1367, 2, 14, Chaharshanbeh)
>>> JalaliDate(1367, 2, 14).to_gregorian() # Jalali → Gregorian
datetime.date(1988, 5, 4)
>>> JalaliDateTime.now().strftime("%A %d %B %Y, %H:%M")
'Jomeh 12 Tir 1405, 14:30'
Dates
Create a JalaliDate from Jalali values, a Gregorian date, an ISO string, or a timestamp:
>>> from persiantools.jdatetime import JalaliDate
>>> import datetime
>>> JalaliDate(1367, 2, 14)
JalaliDate(1367, 2, 14, Chaharshanbeh)
>>> JalaliDate.to_jalali(2013, 9, 16)
JalaliDate(1392, 6, 25, Doshanbeh)
>>> JalaliDate.fromisoformat("1404-01-01")
JalaliDate(1404, 1, 1, Jomeh)
>>> JalaliDate.fromtimestamp(578707200)
JalaliDate(1367, 2, 14, Chaharshanbeh)
>>> JalaliDate(1400, 1, 1).replace(month=2, day=10)
JalaliDate(1400, 2, 10, Jomeh)
The week starts on Shanbeh (Saturday). weekday() counts from 0 (Shanbeh) to 6 (Jomeh), and isoweekday() from 1 to 7:
>>> d = JalaliDate(1367, 2, 14) # a Chaharshanbeh (Wednesday)
>>> d.weekday()
4
>>> d.isoweekday()
5
>>> d.isocalendar()
IsoCalendarDate(year=1367, week=7, weekday=5)
>>> d.isoformat()
'1367-02-14'
Datetimes
JalaliDateTime adds time and timezone support on top of JalaliDate:
>>> from persiantools.jdatetime import JalaliDateTime
>>> from zoneinfo import ZoneInfo
>>> import datetime
>>> JalaliDateTime.now(ZoneInfo("Asia/Tehran"))
JalaliDateTime(1405, 4, 12, 14, 30, 7, 907909, tzinfo=zoneinfo.ZoneInfo(key='Asia/Tehran'))
>>> JalaliDateTime(datetime.datetime(1988, 5, 4, 14, 30, 15))
JalaliDateTime(1367, 2, 14, 14, 30, 15)
>>> JalaliDateTime(1367, 2, 14, 14, 30, 15).to_gregorian()
datetime.datetime(1988, 5, 4, 14, 30, 15)
>>> JalaliDateTime(1367, 2, 14, 14, 30, tzinfo=datetime.timezone.utc).isoformat(timespec="minutes")
'1367-02-14T14:30+00:00'
Formatting and parsing
Both classes support strftime and strptime with the familiar directives, in English or Persian:
>>> from persiantools.jdatetime import JalaliDate, JalaliDateTime
>>> JalaliDate(1367, 2, 14).strftime("%A %d %B %Y")
'Chaharshanbeh 14 Ordibehesht 1367'
>>> JalaliDateTime(1367, 2, 14, 14, 30).strftime("%c", locale="fa")
'چهارشنبه ۱۴ اردیبهشت ۱۳۶۷ ۱۴:۳۰:۰۰'
>>> JalaliDate.strptime("1367-02-14", "%Y-%m-%d")
JalaliDate(1367, 2, 14, Chaharshanbeh)
>>> JalaliDateTime.strptime("1367/02/14 14:30", "%Y/%m/%d %H:%M")
JalaliDateTime(1367, 2, 14, 14, 30)
A date created with locale="fa" renders itself with Persian digits and names everywhere:
>>> JalaliDate(1367, 2, 14, locale="fa").isoformat()
'۱۳۶۷-۰۲-۱۴'
Comparison and arithmetic
Jalali objects compare and do arithmetic with each other, with timedelta, and directly with their Gregorian counterparts:
>>> from persiantools.jdatetime import JalaliDate, JalaliDateTime
>>> import datetime
>>> JalaliDate(1367, 2, 14) == datetime.date(1988, 5, 4)
True
>>> JalaliDate(1395, 2, 14) + datetime.timedelta(days=38)
JalaliDate(1395, 3, 21, Jomeh)
>>> JalaliDateTime(1395, 12, 30) - JalaliDateTime(1395, 1, 1)
datetime.timedelta(days=365)
>>> JalaliDate(1399, 12, 30) > JalaliDate(1399, 12, 29) # leap-year Esfand 30
True
They are also hashable (usable as dict keys) and picklable, like the standard library types.
Digits
Convert digits between English, Persian, and Arabic:
>>> from persiantools import digits
>>> digits.en_to_fa("0987654321")
'۰۹۸۷۶۵۴۳۲۱'
>>> digits.ar_to_fa("٠٩٨٧٦٥٤٣٢١")
'۰۹۸۷۶۵۴۳۲۱'
>>> digits.fa_to_en("۰۹۸۷۶۵۴۳۲۱")
'0987654321'
>>> digits.fa_to_ar("۰۹۸۷۶۵۴۳۲۱")
'٠٩٨٧٦٥٤٣٢١'
And spell numbers out in Persian — integers, floats, and negatives:
>>> digits.to_word(9512026)
'نه میلیون و پانصد و دوازده هزار و بیست و شش'
>>> digits.to_word(15.007)
'پانزده و هفت هزارم'
>>> digits.to_word(-123.45)
'منفی یکصد و بیست و سه و چهل و پنج صدم'
Characters
Arabic and Persian share letters that look alike but have different Unicode code points (ك vs ک, ي vs ی) — a common source of failed string matching and broken search. Normalize them in either direction:
>>> from persiantools import characters
>>> characters.ar_to_fa("كيك")
'کیک'
>>> characters.fa_to_ar("کیک")
'كيك'
Support this project
If persiantools saves you time, you can support its development with a donation:
| Coin | Address |
|---|---|
| Bitcoin (BTC) | bc1qg5rp7ymznc98wmhltzvpwl2dvfuvjr33m4hy77 |
| Ethereum (ETH) | 0xC7D6bf306E456632764D0aD111C8dBBb43a3B9ad |
| Tron (TRX) | TDd63bVWZDBHmwVNFgJ6T2WdWmk9z7PBLg |
| Stellar (XLM) | GDSFPPLY34QSAOTOP4DQDXAI2YDRNRIADZHTN3HCGMQXRLIGPYOEH7L5 |
| USDT (BSC) | 0xC7D6bf306E456632764D0aD111C8dBBb43a3B9ad |
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 persiantools-6.0.0.tar.gz.
File metadata
- Download URL: persiantools-6.0.0.tar.gz
- Upload date:
- Size: 46.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
355f7d7dd2c186886a2fe279ed0e608631577e2624093fdb0989ea0e1d013b6e
|
|
| MD5 |
21b66f442b300aa4d85ba158de19f1a5
|
|
| BLAKE2b-256 |
66e10718182955b56e8cf8f233db58ad0b9c1ba2b3ae7f7bb6b8f9570d04b519
|
Provenance
The following attestation bundles were made for persiantools-6.0.0.tar.gz:
Publisher:
ci.yml on majiidd/persiantools
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
persiantools-6.0.0.tar.gz -
Subject digest:
355f7d7dd2c186886a2fe279ed0e608631577e2624093fdb0989ea0e1d013b6e - Sigstore transparency entry: 2063908241
- Sigstore integration time:
-
Permalink:
majiidd/persiantools@2bf7d68e29e41c37b0af8137302ce17519ce2118 -
Branch / Tag:
refs/tags/6.0.0 - Owner: https://github.com/majiidd
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@2bf7d68e29e41c37b0af8137302ce17519ce2118 -
Trigger Event:
push
-
Statement type:
File details
Details for the file persiantools-6.0.0-py3-none-any.whl.
File metadata
- Download URL: persiantools-6.0.0-py3-none-any.whl
- Upload date:
- Size: 26.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
30604edbfec83809f237a47607fa2720ef73227f9d807481835afca05406282a
|
|
| MD5 |
753a30439a5b1639a893fea17b01f66f
|
|
| BLAKE2b-256 |
1b49a0722d79df8c1423048f35c8733dcc9a582e52e259444579a0eeaa4c9431
|
Provenance
The following attestation bundles were made for persiantools-6.0.0-py3-none-any.whl:
Publisher:
ci.yml on majiidd/persiantools
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
persiantools-6.0.0-py3-none-any.whl -
Subject digest:
30604edbfec83809f237a47607fa2720ef73227f9d807481835afca05406282a - Sigstore transparency entry: 2063908264
- Sigstore integration time:
-
Permalink:
majiidd/persiantools@2bf7d68e29e41c37b0af8137302ce17519ce2118 -
Branch / Tag:
refs/tags/6.0.0 - Owner: https://github.com/majiidd
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@2bf7d68e29e41c37b0af8137302ce17519ce2118 -
Trigger Event:
push
-
Statement type: