Calendars and conversion

hebrewcal ships three calendars, each an immutable dataclass with year, month and day fields, a to_rd() method and a from_rd() classmethod.

Calendar

Type

Module

Gregorian (proleptic)

GregorianDate

hebrewcal.calendars.gregorian

Julian (proleptic)

JulianDate

hebrewcal.calendars.julian

Hebrew

HebrewDate

hebrewcal.calendars.hebrew

All three are re-exported from the package root.

Gregorian

The proleptic Gregorian calendar is valid for every year, including years ≤ 0.

>>> from hebrewcal import GregorianDate
>>> GregorianDate(2026, 6, 26).to_rd()
739793
>>> GregorianDate.from_rd(739793)
GregorianDate(year=2026, month=6, day=26)
>>> from hebrewcal.calendars.gregorian import is_leap_year
>>> is_leap_year(2000), is_leap_year(1900), is_leap_year(2024)
(True, False, True)

Dates are validated on construction:

>>> GregorianDate(2026, 2, 30)
Traceback (most recent call last):
    ...
ValueError: day out of range: 30

Julian

The proleptic Julian calendar uses the simple “every fourth year” leap rule. There is no year 0; year −1 precedes year 1.

>>> from hebrewcal import JulianDate
>>> from hebrewcal.calendars.julian import is_leap_year
>>> is_leap_year(1900)   # leap in the Julian calendar
True
>>> JulianDate(2026, 6, 13).to_rd()
739793

The Julian/Gregorian reform

The 1582 reform skipped from Julian Thursday 4 October 1582 straight to Gregorian Friday 15 October 1582. hebrewcal never performs this jump silently — it computes everything through RD and exposes the cutover explicitly:

>>> from hebrewcal import JulianDate, GregorianDate
>>> JulianDate(1582, 10, 4).to_rd()
577735
>>> GregorianDate(1582, 10, 15).to_rd()
577736
>>> # The two are consecutive days: no gap in the RD timeline.
>>> from hebrewcal.calendars.julian import last_gregorian_before_reform
>>> last_gregorian_before_reform()
GregorianDate(year=1582, month=10, day=4)

Regional adoption

The 1582 cutover is the papal one. Many countries adopted the Gregorian calendar much later (Britain in 1752, Russia in 1918, …). hebrewcal gives you exact RD values for both calendars; choosing which calendar a historical date was written in is your decision, not a silent default.

Hebrew

The Hebrew date type wires the arithmetic engine (see Hebrew calendar internals) into the calendar contract.

>>> from hebrewcal import HebrewDate, to_gregorian
>>> HebrewDate(5785, 7, 1)               # 1 Tishri 5785
HebrewDate(year=5785, month=7, day=1)
>>> to_gregorian(HebrewDate(5785, 7, 1))
GregorianDate(year=2024, month=10, day=3)

Leap years contain a 13th month (Adar II); month 12 becomes Adar I:

>>> HebrewDate(5784, 13, 1).to_rd() > HebrewDate(5784, 12, 1).to_rd()
True

Converting between calendars

The high-level helpers all route through RD:

>>> from hebrewcal import GregorianDate, to_hebrew, to_julian
>>> to_hebrew(GregorianDate(1867, 10, 31))
HebrewDate(year=5628, month=8, day=2)
>>> to_julian(GregorianDate(1867, 10, 31))
JulianDate(year=1867, month=10, day=19)

A worked answer to the classic question — “What Hebrew date and weekday corresponds to 31 October 1867?”:

>>> from hebrewcal import GregorianDate, to_hebrew, weekday
>>> g = GregorianDate(1867, 10, 31)
>>> h = to_hebrew(g)
>>> f"{h.day} Marheshvan {h.year}, {weekday(g).name.title()}"
'2 Marheshvan 5628, Thursday'