SkillAgentSearch skills...

Hebcal Es6

perpetual Jewish Calendar with holidays, Shabbat and holiday candle lighting and havdalah times, Torah readings, and more

Install / Use

npx skills add hebcal/hebcal-es6

Installs into whichever agent you are using.

README

@hebcal/core

Hebcal is a perpetual Jewish Calendar. This library converts between Hebrew and Gregorian dates, and generates lists of Jewish holidays for any year (past, present or future). Shabbat and holiday candle lighting and havdalah times are approximated based on location. Torah readings (Parashat HaShavua), Daf Yomi, and counting of the Omer can also be specified. Hebcal also includes algorithms to calculate yahrzeits, birthdays and anniversaries.

Build Status

@hebcal/core targets both browser-based JavaScript and server-side Node.js.

Most work starts with the calendar() function and the HDate class.

Nearly everything is available as a standalone function — calendar(), getHolidaysOnDate(), getSedra(), tachanun(), reformatTimeStr() — and the examples here use that form, since importing only what you need is what lets a bundler drop the rest. The same functions are also reachable as static methods on HebrewCalendar.

Yahrzeits and birthdays are standalone functions too, but they live in @hebcal/hdate rather than here — import yahrzeit() and birthdayOrAnniversary() from there directly. HebrewCalendar.getYahrzeit() and .getBirthdayOrAnniversary() are thin wrappers over them. A few odds and ends remain class-only: eruvTavshilin(), hallel() and getHolidaysForYear().

Installation

npm install @hebcal/core

Synopsis

import {calendar, Location} from '@hebcal/core';

const events = calendar({
  year: 1981,
  isHebrewYear: false,
  candlelighting: true,
  location: Location.lookup('San Francisco'),
  sedrot: true,
  omer: true,
});

for (const ev of events) {
  const hd = ev.getDate();
  const date = hd.greg();
  console.log(date.toLocaleDateString(), ev.render('en'), hd.toString());
}

Events and flags

Everything calendar() returns is an Event: a Hebrew date, a description, a flags bitmask, and optional extras. Subclasses add detail — HolidayEvent, ParshaEvent, OmerEvent, CandleLightingEvent and HavdalahEvent (both TimedEvents, carrying an eventTime), MoladEvent, HebrewDateEvent, and others.

Rather than testing instanceof, classify events with flags:

import {calendar, flags} from '@hebcal/core';

const events = calendar({year: 5784, isHebrewYear: true});

for (const ev of events) {
  if (ev.getFlags() & flags.MAJOR_FAST) {
    console.log('fast day:', ev.render('en'));
  }
}

You can also push the filter down into generation, which is cheaper than filtering afterwards, via options.mask:

const roshChodesh = calendar({
  year: 5784,
  isHebrewYear: true,
  mask: flags.ROSH_CHODESH,
});

Event.getCategories() gives a coarser, string-based classification (['holiday', 'major', 'fast']) that is handy for CSS classes or grouping. See the flags API docs for the full list.

Looking up a single date

calendar() is built for generating a range. When you only need to know what falls on one day, getHolidaysOnDate() is much more direct — it reads from an internally cached per-year map instead of running the full generator:

import {getHolidaysOnDate, HDate, months} from '@hebcal/core';

const events = getHolidaysOnDate(new HDate(15, months.NISAN, 5784), false);
console.log(events?.map(ev => ev.getDesc())); // ['Pesach I']

Three things to know:

  • It returns undefined — not an empty array — when nothing falls on that date, so use events?.map(...) or check before indexing.
  • The il argument is optional, and omitting it is not the same as passing false. With il omitted you get both the Israel and Diaspora events for that date, unfiltered; pass true or false to get one schedule.
  • It accepts an HDate, a Date, or an absolute R.D. day number.

It returns only holidays. Candle-lighting times, Torah readings and Omer days come from calendar(), which is what options.candlelighting, options.sedrot and options.omer drive.

Daily learning (Daf Yomi and friends)

@hebcal/core ships no learning schedules itself. DailyLearning is a plug-in registry; the schedules live in the separate @hebcal/learning package, which registers them by calling DailyLearning.addCalendar() when you import it. This keeps the daily-study tables — which are large and grow as new cycles are added — out of the core bundle for the many users who don't need them.

Import @hebcal/learning once for its side effects, then request calendars through options.dailyLearning:

import '@hebcal/learning';
import {calendar, flags} from '@hebcal/core';

const events = calendar({
  year: 5784,
  isHebrewYear: true,
  noHolidays: true,
  dailyLearning: {dafYomi: true},
});

for (const ev of events) {
  if (ev.getFlags() & flags.DAF_YOMI) {
    console.log(ev.getDate().toString(), ev.render('en'));
  }
}

Daf Yomi (Babylonian Talmud) is by far the most widely used. @hebcal/learning also provides Yerushalmi Yomi, Mishna Yomi, Nach Yomi, Daf Weekly, Chofetz Chaim, Rambam, 929 and more. Most take true; yerushalmi takes a number selecting the edition (1 for Vilna, 2 for Schottenstein):

dailyLearning: {dafYomi: true, mishnaYomi: true, yerushalmi: 1}

To query a single day without generating a calendar, use DailyLearning.lookup():

import '@hebcal/learning';
import {DailyLearning, HDate, months} from '@hebcal/core';

const ev = DailyLearning.lookup(
  'dafYomi',
  new HDate(15, months.CHESHVAN, 5784),
  false
);
console.log(ev?.render('en')); // 'Daf Yomi: Kiddushin 78'

DailyLearning.getCalendars() returns the authoritative list of what the installed version of @hebcal/learning actually registered; has() and getStartDate() report whether a given calendar is available and from what date. You can register your own schedule with addCalendar() — the same entry point @hebcal/learning uses.

Candle lighting, Havdalah, and fast times

Set options.candlelighting = true and supply an options.location to get timed events. Times are computed from latitude and longitude via NOAA solar equations. If you ever have any doubts about Hebcal's times, consult your local halachic authority — and note that coordinates above the Arctic or below the Antarctic circle are guaranteed to be wrong.

import {calendar, Location, flags} from '@hebcal/core';

const events = calendar({
  year: 2024,
  candlelighting: true,
  location: Location.lookup('Jerusalem'),
});

for (const ev of events) {
  if (ev.getFlags() & flags.LIGHT_CANDLES) {
    console.log(ev.getDate().toString(), ev.eventTimeStr); // '24 Tevet 5784' '16:08'
  }
}

Candle lighting defaults to 18 minutes before sunset in the Diaspora and 20 minutes in Israel, with 40 minutes for Jerusalem and 30 for Haifa and Zikhron Ya'akov. Override with options.candleLightingMins.

Havdalah defaults to Tzeit Hakochavim — nightfall, when 3 small stars are visible — calculated at 8.5° of solar depression. Two mutually exclusive overrides:

  • options.havdalahDeg — a different solar depression angle (7.083° is the common alternative, for 3 medium-sized stars). Set to 0 to suppress Havdalah times.
  • options.havdalahMins — a fixed number of minutes after sunset instead (42, 50 and 72 are typical). Set to 0 to suppress Havdalah times.

Minor fasts begin at Alot HaShachar (16.1° in the morning). They end at 7.083° in the Diaspora, or 15 minutes after sunset in Israel (Rabbi Deblitzky's practice). Override with options.fastEndDeg or options.fastEndMins — again mutually exclusive. When a minor fast falls on a Friday, the end time is suppressed, because Shabbat begins before nightfall.

Tish'a B'Av does not follow those rules: it begins at sunset the previous day and always ends at 6.45° (Rabbi Yechiel Michel Tucazinsky), ignoring fastEndDeg and fastEndMins.

Chanukah candle-lighting, also generated when candlelighting and location are set, is at Bein HaShmashos (13.5 minutes before 7.083°) on weekdays, regular candle-lighting time on Friday, and regular Havdalah time on Saturday night.

Set options.useElevation = true to factor a location's elevation into sunrise and sunset. Note that degree-based zmanim estimate the amount of light in the sky and so are unaffected by elevation by design; chatzot is also always computed at sea level.

For zmanim outside the calendar-generation flow, use the Zmanim class directly.

Yahrzeits, birthdays, and anniversaries

These are two different calculations, not one function with a flag, because the customs genuinely differ. Both follow "Calendrical Calculations" by Reingold and Dershowitz.

Both live in @hebcal/hdate; HebrewCalendar exposes them as wrappers for convenience.

import {birthdayOrAnniversary, yahrzeit} from '@hebcal/hdate';

const dt = new Date(2014, 2, 2); // 30 Adar I 5774

birthdayOrAnniversary(5785, dt)?.toString(); // '1 Nisan 5785'
yahrzeit(5785, dt)?.toString(); // '30 Sh'vat 5785'

The short version: a birthday moves forward, a yahrzeit moves back. When the original day doesn't exist in the target year, a birthday is postponed to the first of the following month, whereas a yahrzeit is observed on the day before that — so in the example above the two land a month apart.

A yahrzeit has one more wrinkle: for a death on 30 Marcheshvan or 30 Kislev, the date in later years

Related Skills

View on GitHub
GitHub Stars133
CategoryDevelopment
Updated6d ago
Forks32

Languages

TypeScript

Security Score

100/100

Audited on Aug 2, 2026

No findings