Skip to main content

Waxt

PyPI version Python versions License Code style: Black Typed

Waxt is a dependency-free Python library for working with Gregorian, Jalali (Persian/Solar), and civil Hijri (Islamic/tabular) dates through one immutable, datetime-like API.

from waxt import DateTime

jalali = DateTime(1404, 3, 25, 14, 30, calendar="jalali")

jalali.to_datetime()                 # datetime.datetime(2025, 6, 15, 14, 30)
jalali.to_calendar("hijri")          # same value, displayed as a Hijri date
jalali.strftime("%d %B %Y, %H:%M")  # "25 Khordad 1404, 14:30"
  • Familiar API modeled on datetime.datetime
  • Calendar conversion without changing the represented value
  • Calendar-aware parsing, formatting, and month arithmetic
  • Standard tzinfo and zoneinfo interoperability
  • Full type hints and no third-party runtime dependencies

Installation

python -m pip install waxt

Waxt requires Python 3.10 or newer.

Quick start

Create and convert dates

The calendar argument controls how the constructor interprets year, month, and day. It accepts "gregorian" (the default), "jalali", or "hijri".

from waxt import DateTime

jalali = DateTime(1404, 3, 25, 14, 30, calendar="jalali")
gregorian = jalali.to_calendar("gregorian")
hijri = jalali.to_calendar("hijri")

(jalali.year, jalali.month, jalali.day)        # (1404, 3, 25)
(gregorian.year, gregorian.month, gregorian.day)  # (2025, 6, 15)
jalali == gregorian == hijri                   # True

to_calendar() changes the calendar representation only. It does not change the underlying wall time, timezone, or represented instant.

Interoperate with the standard library

from datetime import datetime
from waxt import DateTime

standard = datetime(2025, 6, 15, 14, 30)
jalali = DateTime.from_datetime(standard, calendar="jalali")

jalali.isoformat()   # "1404-03-25T14:30:00"
jalali.to_datetime() # datetime.datetime(2025, 6, 15, 14, 30)

to_datetime() always returns the equivalent Gregorian datetime.datetime. Waxt values can also be compared with standard-library datetime values when Python's usual naive/aware comparison rules permit it.

Get the current date and time

from datetime import timezone
from zoneinfo import ZoneInfo
from waxt import DateTime

tehran_now = DateTime.now(ZoneInfo("Asia/Tehran"), calendar="jalali")
utc_now = DateTime.now(timezone.utc, calendar="gregorian")
today = DateTime.today(calendar="hijri")

Parse and format

from waxt import DateTime

value = DateTime.strptime(
    "1404-03-25 14:30 +0330",
    "%Y-%m-%d %H:%M %z",
    calendar="jalali",
)

value.strftime("%Y/%m/%d %H:%M") # "1404/03/25 14:30"
value.strftime("%d %B %Y")       # "25 Khordad 1404"
value.isoformat(timespec="minutes") # "1404-03-25T14:30+03:30"

For Jalali and Hijri values, calendar-aware formatting includes %Y, %y, %m, %d, %j, %b, and %B. Other directives, including time and timezone directives, follow the standard library's strftime() behavior.

Perform date arithmetic

from datetime import timedelta
from waxt import DateTime

value = DateTime(1404, 6, 31, calendar="jalali")

value + timedelta(days=1) # 1404-07-01
value.add_days(1)         # 1404-07-01
value.add_months(1)       # 1404-07-30 (clamped to the target month)

timedelta arithmetic operates on the underlying Gregorian datetime and keeps the selected calendar for the result. add_months() advances calendar months and clamps the day when the target month is shorter.

Work with timezones

Waxt accepts any standard tzinfo implementation, including zoneinfo.ZoneInfo. Its country-based tzinfo() helper also uses IANA rules, including daylight-saving and historical changes.

from datetime import timezone
from zoneinfo import ZoneInfo
from waxt import DateTime

utc_value = DateTime(2025, 6, 15, 10, tzinfo=timezone.utc)
tehran_value = utc_value.astimezone(ZoneInfo("Asia/Tehran"))

tehran_value.to_datetime().isoformat() # "2025-06-15T13:30:00+03:30"

Waxt also bundles basic metadata for ISO 3166-1 alpha-2 country codes:

from waxt import country, tzinfo

iran = country("IR")
iran.name       # "Iran, Islamic Republic of"
iran.timezone   # "Asia/Tehran"
iran.calendar   # "persian"
iran.rtl        # True

tehran = tzinfo("IR")
tehran.utcoffset(None) # datetime.timedelta(seconds=12600)

The object returned by Waxt's tzinfo() helper applies daylight-saving transitions and historical offset changes from the representative IANA timezone listed for the country. For countries spanning multiple timezones, use ZoneInfo directly to select a more specific zone.

Important calendar semantics

Waxt stores every value internally as a Gregorian datetime, while the calendar property controls the exposed date fields and calendar-aware output. As a result:

  • year, month, day, isoformat(), and calendar-aware strftime() output use the selected calendar.
  • to_datetime() and date() return standard-library Gregorian values.
  • POSIX timestamps, ordinals, ISO week dates, timezone behavior, and comparisons retain standard Python semantics.
  • Hijri conversion uses the arithmetic civil/tabular calendar. It may differ from observational, regional, or Umm al-Qura calendars by one or more days.

API overview

DateTime is available from waxt and waxt.datetime. A lowercase datetime alias is also available from waxt.datetime.

API Purpose
DateTime(...) Construct a value using Gregorian, Jalali, or Hijri fields
now(), today() Create the current local value in a selected calendar
from_datetime(), to_datetime() Convert to and from datetime.datetime
fromisoformat(), strptime() Parse calendar date fields
to_calendar() Return the same value in another calendar representation
isoformat(), strftime() Format using the selected calendar
astimezone() Convert an aware value to another timezone
add_days(), add_months() Apply calendar-preserving arithmetic
replace() Return a value with selected fields changed
country() Look up bundled country metadata
tzinfo() Return a country timezone with IANA transition rules

Calendar constants are available as DateTime.CALENDAR_GREGORIAN, DateTime.CALENDAR_JALALI, and DateTime.CALENDAR_HIJRI.

Development

Clone the repository and install the development and test dependencies:

git clone https://github.com/kak-smko/waxt.git
cd waxt
python -m venv .venv
source .venv/bin/activate
python -m pip install -e ".[dev,test]"

Run the test suite:

pytest

Run formatting, linting, and type checks:

black --check waxt tests
isort --check-only waxt tests
flake8 waxt tests
mypy waxt

Contributing

Bug reports and pull requests are welcome on GitHub. When changing behavior, include or update tests that cover the affected calendar and boundary cases.

License

Waxt is distributed under the BSD 3-Clause License.

Metadata

Release files for waxt 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for waxt 0.2.0
File Size Uploaded
waxt-0.2.0.tar.gz 49.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for waxt 0.2.0
File Interpreter ABI Platform
waxt-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 69.1 kB

Release files / waxt-0.2.0.tar.gz

Download URL waxt-0.2.0.tar.gz
Size 49.6 kB
Tags Source
SHA-256 checksum
How to use checksums
e82294f4c40e1d98bce1aa515d307f2bdb3dfdefc08c17974cacfff9dd4a566d
BLAKE2b-256 checksum
How to use checksums
f8c93a523eda96c910aa671a41569236ab7566a180b5db7719306172dd149856
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release files / waxt-0.2.0-py3-none-any.whl

Download URL waxt-0.2.0-py3-none-any.whl
Size 19.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
233185bdf2c559e8c0175e871c931030a141f52bb1fba7fec3e3bc1e69795721
BLAKE2b-256 checksum
How to use checksums
fd976b0d274c6c654e29711a66ed4466370e804ab9bb7f825cfb8b329fa7596b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page