Skip to main content

Jalali date and datetime with other tools

Project description

PersianTools

PyPI test workflow codecov PyPI - Python Version PyPI - License

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


Download files

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

Source Distribution

persiantools-6.0.0.tar.gz (46.0 kB view details)

Uploaded Source

Built Distribution

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

persiantools-6.0.0-py3-none-any.whl (26.8 kB view details)

Uploaded Python 3

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

Hashes for persiantools-6.0.0.tar.gz
Algorithm Hash digest
SHA256 355f7d7dd2c186886a2fe279ed0e608631577e2624093fdb0989ea0e1d013b6e
MD5 21b66f442b300aa4d85ba158de19f1a5
BLAKE2b-256 66e10718182955b56e8cf8f233db58ad0b9c1ba2b3ae7f7bb6b8f9570d04b519

See more details on using hashes here.

Provenance

The following attestation bundles were made for persiantools-6.0.0.tar.gz:

Publisher: ci.yml on majiidd/persiantools

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for persiantools-6.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 30604edbfec83809f237a47607fa2720ef73227f9d807481835afca05406282a
MD5 753a30439a5b1639a893fea17b01f66f
BLAKE2b-256 1b49a0722d79df8c1423048f35c8733dcc9a582e52e259444579a0eeaa4c9431

See more details on using hashes here.

Provenance

The following attestation bundles were made for persiantools-6.0.0-py3-none-any.whl:

Publisher: ci.yml on majiidd/persiantools

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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