Open In Colab

abf577d43aed46c2ad55eab84b5bbebc

Egyptian civil calendar: historical cross-checks

This notebook compares the Egyptian civil (sothic) dates computed by MontuPython with the civil dates recorded in Egyptology and astronomy literature for a set of well-known historical events.

The event catalogue is shipped with the package (montu/data/historical_dates.json) and is the same one used in MontuPython Desktop (Calendar Calculator → Historical dates).

If you are running this script in Google Colab you need first to install the package.

[1]:
try:
    from google.colab import drive
    %pip install -Uq montu
except ImportError:
    print("Not running in Colab, skipping installation")
    import plotly.io as pio
    pio.renderers.default = "notebook_connected"
    %load_ext autoreload
    %autoreload 2
# Create folders for figures and temporal files
!mkdir -p ./gallery/ ./montu_dem/
Not running in Colab, skipping installation
[2]:
import pandas as pd

%matplotlib inline
import montu as mn

MontuPython version 0.50.0. 𓇍𓇋𓇋𓏏𓅓𓊵 𓎛𓎡𓄿𓀭𓎛𓈖𓂝𓎡 (ii-ti m Htp, HkAx Hn'-k)

Load historical dates

[3]:
historical_dates = mn.load_historical_dates()
len(historical_dates)
[3]:
10

Two illustrative examples

We start with two anchor events from the catalogue: the first apokatastasis (the sothic epoch) and an inscription from the Ptolemaic temple of Edfu documenting the 25-year lunar cycle.

[4]:
def show_comparison(date_key: str) -> None:
    entry = historical_dates[date_key]
    mtime = mn.Time(date_key, calendar="mixed")
    known = entry["egyptian_date"]
    computed = mtime.readable.datesot
    print(entry["label"])
    print(f"  Julian/Gregorian (mixed): {date_key}")
    print(f"  Known civil (literature): {known}")
    print(f"  Computed civil (MontuPython): {computed}")
    print()


show_comparison("bce 2782-07-20")   # First Apokatastasis
show_comparison("bce 237-08-23")   # Edfu Temple inscription
BCE 2782-07-20 — First Apokatastasis
  Julian/Gregorian (mixed): bce 2782-07-20
  Known civil (literature): I akhet 1
  Computed civil (MontuPython): [hrw 0] I akhet 1

BCE 237-08-23 — Edfu Temple Inscription (25-yr lunar cycle)
  Julian/Gregorian (mixed): bce 237-08-23
  Known civil (literature): III shemu 7
  Computed civil (MontuPython): [hrw 2546] III shemu 7

Full comparison

The table below includes only events whose catalogue entry provides a known Egyptian civil date (egyptian_date is not null). When the source gives only month–season–day (without Horus year), the comparison checks that triplet; the Horus year comes from MontuPython’s sothic conversion.

[5]:
import re


def month_season_day(civil: str) -> str:
    """Return MONTH SEASON DAY, dropping an optional [hrw YEAR] prefix."""
    text = civil.strip()
    match = re.match(r"^\[hrw\s+-?\d+\]\s+(.+)$", text, re.IGNORECASE)
    if match:
        text = match.group(1)
    if "-" in text and " " not in text:
        month, season, day = text.split("-", 2)
        return f"{month} {season.lower()} {day}"
    parts = text.split()
    if len(parts) == 3:
        return f"{parts[0]} {parts[1].lower()} {parts[2]}"
    return text


def compare_event(date_key: str, entry: dict) -> dict | None:
    known = entry.get("egyptian_date")
    if known is None:
        return None

    mtime = mn.Time(date_key, calendar="mixed")
    computed = mtime.readable.datesot
    known_msd = month_season_day(known)
    computed_msd = month_season_day(computed)
    match = "✓" if known_msd == computed_msd else "✗"

    return {
        "Event": entry.get("label", date_key),
        "Julian/Gregorian (mixed)": date_key,
        "Known civil (literature)": known,
        "Computed civil (MontuPython)": computed,
        "Month–season–day match": match,
        "Source": entry.get("source", ""),
    }


rows = [
    row
    for date_key, entry in sorted(historical_dates.items())
    if (row := compare_event(date_key, entry)) is not None
]
comparison = pd.DataFrame(rows)
comparison
[5]:
Event Julian/Gregorian (mixed) Known civil (literature) Computed civil (MontuPython) Month–season–day match Source
0 CE 139-07-20 — Third Apokatastasis 139-07-20 I akhet 1 [hrw 2922] I akhet 1 ✓ Lull, J. (2020). La astronomía en el antiguo E...
1 CE 384-07-23 — Theon's Heliacal Rise 384-07-23 I akhet 1 [hrw 3167] III akhet 6 ✗ Lull, J. (2020). La astronomía en el antiguo E...
2 BCE 1322-07-20 — Second Apokatastasis bce 1322-07-20 I akhet 1 [hrw 1461] I akhet 1 ✓ Lull, J. (2020). La astronomía en el antiguo E...
3 BCE 212-08-17 — Edfu Temple Inscription II bce 212-08-17 III shemu 7 [hrw 2571] III shemu 7 ✓ Lull, J. (2020). La astronomía en el antiguo E...
4 BCE 237-08-23 — Edfu Temple Inscription (25-yr... bce 237-08-23 III shemu 7 [hrw 2546] III shemu 7 ✓ Lull, J. (2020). La astronomía en el antiguo E...
5 BCE 238-03-07 — Canopus Decree bce 238-03-07 I peret 17 [hrw 2545] I peret 17 ✓ Lull, J. (2020). La astronomía en el antiguo E...
6 BCE 2782-07-20 — First Apokatastasis bce 2782-07-20 I akhet 1 [hrw 0] I akhet 1 ✓ Lull, J. (2020). La astronomía en el antiguo E...
7 BCE 559-10-19 — Papyrus Louvre 7848 bce 559-10-19 III shemu 13 [hrw 2224] II shemu 13 ✗ Lull, J. (2020). La astronomía en el antiguo E...
8 BCE 688-06-11 — Papyrus Louvre E3228d bce 688-06-11 I peret 10 [hrw 2095] I peret 1 ✗ Lull, J. (2020). La astronomía en el antiguo E...

Summary

[6]:
n_match = (comparison["Month–season–day match"] == "✓").sum()
n_total = len(comparison)
print(f"Month–season–day agreement: {n_match} / {n_total}")

if (comparison["Month–season–day match"] == "✗").any():
    print("\nEvents with a reported discrepancy:")
    display(comparison[comparison["Month–season–day match"] == "✗"])
Month–season–day agreement: 6 / 9

Events with a reported discrepancy:
Event Julian/Gregorian (mixed) Known civil (literature) Computed civil (MontuPython) Month–season–day match Source
1 CE 384-07-23 — Theon's Heliacal Rise 384-07-23 I akhet 1 [hrw 3167] III akhet 6 ✗ Lull, J. (2020). La astronomía en el antiguo E...
7 BCE 559-10-19 — Papyrus Louvre 7848 bce 559-10-19 III shemu 13 [hrw 2224] II shemu 13 ✗ Lull, J. (2020). La astronomía en el antiguo E...
8 BCE 688-06-11 — Papyrus Louvre E3228d bce 688-06-11 I peret 10 [hrw 2095] I peret 1 ✗ Lull, J. (2020). La astronomía en el antiguo E...

Note. Discrepancies may reflect uncertainties in the historical Julian/Gregorian date, in the reading of the ancient civil date, or in the long-range \(\Delta T\) model used by MontuPython for ancient epochs. The apokatastasis anchors and several Ptolemaic documents agree exactly; other entries are included precisely because they provide independent checks from the literature.


Powered by MontuPython. For more examples see MontuPython GitHub repo.

Jorge I. Zuluaga © 2023-present