
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