calendars — Historical eras and calendar conversions

kanon.calendars Package

The calendars package provides everything you need to manipulate historical dates with ancient calendars. All calculations on dates are based on Julian Day Numbers, starting the 1st January 4713 B.C. at 12:00. This module already has a few of the major historical calendars subclassed (see calendars). Once subclassed, a Calendar is created with an Era to define its beginning.

You can find all the calendars already instantiated in the Calendar.registry :






Civil Hijra




Yazdigird Andarjah at the end

Astronomical Hijra


A.D. Leap December

Yazdigird Andarjah after Ābān

A.D. First month March

Julian Era

You can easily convert dates between all kinds of calendars. For this we use Date objects. To start, let’s try to build a Date of the 10th March 1324 from the Julian A.D. calendar :

>>> julian_ad = Calendar.registry["Julian A.D."]
>>> date = Date(julian_ad, (1324, 3, 10))
>>> str(date)
'10 Martius 1324 A.D. in Julian 12:00'
>>> date.jdn

Then we can convert this date in the Arabic Civil Hijra calendar :

>>> arabic_civil_hijra = Calendar.registry["Arabic Civil Hijra"]
>>> arabic_date = date.to_calendar(arabic_civil_hijra)
>>> str(arabic_date)
'13 Rabīʿ al-awwal 724 Civil Hijra in Arabic 12:00'
>>> arabic_date.jdn

We have succesfully converted a date expressed in one calendar into another. And we see that its absolute date value (expressed in Julian Day Numbers) stays the same.


Calendar(era[, variant, months_mutation])

This abstract class defines calendar behaviors.

Date(calendar, ymd, int, int], hours, ...)

Dataclass defining a date.

Class Inheritance Diagram

Inheritance diagram of kanon.calendars.calendars.Calendar, kanon.calendars.calendars.Date

kanon.calendars.calendars Module

To create a new Calendar you need to subclass it, then instanciate it with an Era. A Calendar subclass has to have a name, a list of Month and an intercalation method to be valid.

>>> class NewCal(Calendar):
...     _name = "My New Calendar"
...     _months = [Month(31, 32, "FirstMonth"),
...                Month(20, 22, "SecondMonth"),
...                Month(50, name="ThirdMonth")]
...     def intercalation(self, year: int) -> bool:
...         return year % 7 == 0
>>> my_era = Era("MyEra", 1234)
>>> my_calendar = NewCal(my_era)
>>> my_date = Date(my_calendar, (26, 3, 42), 13.5)
>>> str(my_date)
'42 ThirdMonth 26 MyEra in My New Calendar 13:30'
>>> my_date.jdn


Julian(era[, variant, months_mutation])

Defines the Julian Calendar.

Byzantine(era[, variant, months_mutation])

Defines the Byzantine Calendar.

Arabic(era[, variant, months_mutation])

Defines the Arabic Calendar.

Persian(era[, variant, months_mutation])

Defines the Persian Calendar.

Egyptian(era[, variant, months_mutation])

Defines the Egyptian Calendar.

Month(days_cy[, days_ly, name, variant])

Dataclass defining a Calendar's month.

Era(name, epoch)

Dataclass defining an era.

Class Inheritance Diagram

Inheritance diagram of kanon.calendars.calendars.Julian, kanon.calendars.calendars.Byzantine, kanon.calendars.calendars.Arabic, kanon.calendars.calendars.Persian, kanon.calendars.calendars.Egyptian, kanon.calendars.calendars.Month, kanon.calendars.calendars.Era