"""A small command-line interface for hebrewcal.
Exposed as the ``hebrewcal`` console script and via ``python -m hebrewcal``.
Uses only the standard library (argparse).
"""
from __future__ import annotations
import argparse
from collections.abc import Sequence
from hebrewcal import GregorianDate, to_hebrew, to_julian, weekday
from hebrewcal.astro.location import Location
from hebrewcal.conversion import to_gregorian
from hebrewcal.formatting.dates import format_hebrew
from hebrewcal.names import hebrew_month_name, weekday_name
from hebrewcal.parsing.dates import parse_gregorian
from hebrewcal.religious.holidays import holidays
from hebrewcal.religious.shabbat import candle_lighting, havdalah
from hebrewcal.religious.torah import parasha
from hebrewcal.religious.zmanim import Zmanim
def _hebrew_label(g: GregorianDate) -> str:
h = to_hebrew(g)
name = hebrew_month_name(h.year, h.month)
return f"{h.day} {name} {h.year} ({weekday_name(weekday(g))})"
def _build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(prog="hebrewcal", description="Hebrew calendar tools.")
sub = parser.add_subparsers(dest="command", required=True)
convert = sub.add_parser("convert", help="Convert a Gregorian date.")
convert.add_argument("date", help="Gregorian date (ISO 8601, DIN 5008 or slash form).")
convert.add_argument("--to", choices=("hebrew", "julian"), default="hebrew")
convert.add_argument(
"--hebrew", action="store_true", help="Output the Hebrew date in Hebrew script."
)
hol = sub.add_parser("holidays", help="List the holidays of a Hebrew year.")
hol.add_argument("year", type=int, help="Hebrew (Anno Mundi) year.")
hol.add_argument("--israel", action="store_true", help="Use the Israeli schedule.")
par = sub.add_parser("parasha", help="Weekly Torah portion for a Shabbat.")
par.add_argument("date", help="Gregorian date of the Shabbat.")
par.add_argument("--israel", action="store_true")
location_commands = (
("shabbat", "Candle lighting and Havdalah."),
("zmanim", "Halachic times."),
)
for name, helptext in location_commands:
loc = sub.add_parser(name, help=helptext)
loc.add_argument("date", help="Gregorian date.")
loc.add_argument("--lat", type=float, required=True, help="Latitude (degrees north).")
loc.add_argument("--lon", type=float, required=True, help="Longitude (degrees east).")
loc.add_argument("--tz", default="UTC", help="IANA time-zone name.")
return parser
def _fmt(value: object) -> str:
return value.strftime("%H:%M") if hasattr(value, "strftime") else "n/a (no event)"
[docs]
def main(argv: Sequence[str] | None = None) -> int:
"""Run the command-line interface. Returns a process exit code."""
parser = _build_parser()
args = parser.parse_args(argv)
try:
if args.command == "convert":
g = parse_gregorian(args.date)
if args.to == "julian":
j = to_julian(g)
print(f"{j.year}-{j.month:02d}-{j.day:02d} (Julian)")
elif args.hebrew:
date = format_hebrew(to_hebrew(g), style="hebrew")
day = weekday_name(weekday(g), hebrew=True)
print(f"{date} ({day})")
else:
print(_hebrew_label(g))
elif args.command == "holidays":
for h in holidays(args.year, diaspora=not args.israel):
g = to_gregorian(h.date)
print(f"{g.year}-{g.month:02d}-{g.day:02d} {h.name} [{h.category.value}]")
elif args.command == "parasha":
g = parse_gregorian(args.date)
name = parasha(to_hebrew(g), israel=args.israel)
print(name if name is not None else "(no weekly parasha on this date)")
elif args.command == "shabbat":
g = parse_gregorian(args.date)
loc = Location(args.lat, args.lon, timezone=args.tz)
print(f"Candle lighting: {_fmt(candle_lighting(g, loc))}")
print(f"Havdalah: {_fmt(havdalah(g, loc))}")
elif args.command == "zmanim":
g = parse_gregorian(args.date)
z = Zmanim(g, Location(args.lat, args.lon, timezone=args.tz))
print(f"Sunrise: {_fmt(z.sunrise())}")
print(f"Sof zman Shma (GRA): {_fmt(z.sof_zman_shma_gra())}")
print(f"Chatzot: {_fmt(z.chatzot())}")
print(f"Sunset: {_fmt(z.sunset())}")
print(f"Tzeit: {_fmt(z.tzeit_hakochavim())}")
except ValueError as exc:
print(f"error: {exc}")
return 2
return 0