Skip to content

Commit

Permalink
Allow candle-lighting offset of 0 minutes from sundown per hebcal/heb…
Browse files Browse the repository at this point in the history
…cal#279

Generate correct YomKippurKatan URLs even when candle-lighting times are enabled
  • Loading branch information
mjradwin committed Dec 23, 2024
1 parent 9b2d69b commit 41717d8
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 16 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@hebcal/core",
"version": "5.8.6",
"version": "5.8.7",
"author": "Michael J. Radwin (https://github.com/mjradwin)",
"contributors": [
"Eyal Schachter (https://github.com/Scimonster)",
Expand Down
5 changes: 3 additions & 2 deletions src/calendar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -411,14 +411,15 @@ function checkCandleOptions(options: CalOptions) {
);
}

let min = Number(options.candleLightingMins) || 18;
const min0 = options.candleLightingMins;
let min = typeof min0 === 'number' && !isNaN(min0) ? Math.trunc(min0) : 18;
if (location.getIsrael() && Math.abs(min) === 18) {
min = overrideIsraelCandleMins(location, min);
}
options.candleLightingMins = -1 * Math.abs(min);

if (typeof options.havdalahMins === 'number') {
options.havdalahMins = Math.abs(options.havdalahMins);
options.havdalahMins = Math.trunc(Math.abs(options.havdalahMins));
} else if (typeof options.havdalahDeg === 'number') {
options.havdalahDeg = Math.abs(options.havdalahDeg);
} else {
Expand Down
27 changes: 15 additions & 12 deletions src/candles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,17 @@ export function makeCandleEvent(
havdalahTitle = true;
mask = LIGHT_CANDLES_TZEIS;
}
// if offset is 0 or undefined, we'll use tzeit time
// if Havdalah offset is 0 or undefined, we'll use tzeit time
const offset = useHavdalahOffset
? options.havdalahMins
: options.candleLightingMins;
? Number(options.havdalahMins)
: Number(options.candleLightingMins);
const location = options.location as Location;
const useElevation = Boolean(options.useElevation);
const zmanim = new Zmanim(location, hd, useElevation);
const time = offset
? zmanim.sunsetOffset(offset, true)
: zmanim.tzeit(options.havdalahDeg);
const time =
useHavdalahOffset && !offset
? zmanim.tzeit(options.havdalahDeg)
: zmanim.sunsetOffset(offset, true);
if (isNaN(time.getTime())) {
return undefined; // no sunset
}
Expand Down Expand Up @@ -93,6 +94,12 @@ export class FastDayEvent extends HolidayEvent {
}
return super.urlDateSuffix();
}
url(): string | undefined {
if (this.getFlags() & flags.YOM_KIPPUR_KATAN) {
return undefined;
}
return super.url();
}
}

/**
Expand Down Expand Up @@ -141,12 +148,8 @@ export function makeFastStartEnd(
}
}
const ev2 = new FastDayEvent(hd, desc, ev.getFlags(), startEvent, endEvent);
for (const property in ev) {
// eslint-disable-next-line no-prototype-builtins
if (ev.hasOwnProperty(property)) {
Object.defineProperty(ev2, property, {value: (ev as any)[property]});
}
}
// copy properties such as memo or emoji
Object.assign(ev2, ev);
return ev2;
}

Expand Down
46 changes: 45 additions & 1 deletion test/candles.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
makeCandleEvent, makeFastStartEnd,
FastDayEvent,
} from '../src/candles';
import {TimedEvent} from '../src/TimedEvent';
import {CandleLightingEvent, TimedEvent} from '../src/TimedEvent';
import {CalOptions} from '../src/CalOptions';
import {Event, flags} from '../src/event';
import {HDate, isoDateString} from '@hebcal/hdate';
Expand Down Expand Up @@ -271,6 +271,50 @@ test('candleLightingMins', () => {
expect(events18).toEqual(expected18);
});

test('candleLightingMins truncates decimals', () => {
const dt = new Date(2020, 4, 15);
const options: CalOptions = {
start: dt,
end: dt,
noHolidays: true,
location: Location.lookup('Tel Aviv'),
candlelighting: true,
useElevation: true,
};
let ev = HebrewCalendar.calendar({...options, candleLightingMins: 2.75})[0];
expect((ev as CandleLightingEvent).eventTimeStr).toBe('19:30');
ev = HebrewCalendar.calendar({...options, candleLightingMins: 2})[0];
expect((ev as CandleLightingEvent).eventTimeStr).toBe('19:30');
ev = HebrewCalendar.calendar({...options, candleLightingMins: -2})[0];
expect((ev as CandleLightingEvent).eventTimeStr).toBe('19:30');
ev = HebrewCalendar.calendar({...options, candleLightingMins: -2.99})[0];
expect((ev as CandleLightingEvent).eventTimeStr).toBe('19:30');
});

test('candleLightingMins-0', () => {
const dt = new Date(2020, 4, 15);
const options: CalOptions = {
start: dt,
end: dt,
noHolidays: true,
location: Location.lookup('Tel Aviv'),
candlelighting: true,
useElevation: true,
};
let ev = HebrewCalendar.calendar(options)[0];
expect((ev as CandleLightingEvent).eventTimeStr).toBe('19:14');
ev = HebrewCalendar.calendar({...options, candleLightingMins: 18})[0];
expect((ev as CandleLightingEvent).eventTimeStr).toBe('19:14');
ev = HebrewCalendar.calendar({...options, candleLightingMins: 17})[0];
expect((ev as CandleLightingEvent).eventTimeStr).toBe('19:15');
ev = HebrewCalendar.calendar({...options, candleLightingMins: 2})[0];
expect((ev as CandleLightingEvent).eventTimeStr).toBe('19:30');
ev = HebrewCalendar.calendar({...options, candleLightingMins: 1})[0];
expect((ev as CandleLightingEvent).eventTimeStr).toBe('19:31');
ev = HebrewCalendar.calendar({...options, candleLightingMins: 0})[0];
expect((ev as CandleLightingEvent).eventTimeStr).toBe('19:32');
});

const jerusalemSeaLevel = new Location(31.76904, 35.21633, true, 'Asia/Jerusalem',
'Jerusalem, Israel', 'IL', undefined, 0);

Expand Down
29 changes: 29 additions & 0 deletions test/hebcal.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {HebrewCalendar} from '../src/hebcal';
import {Event, flags} from '../src/event';
import {Location} from '../src/location';
import { OmerEvent } from '../src/omer';
import { YomKippurKatanEvent } from '../src/YomKippurKatanEvent';
import { FastDayEvent } from '../src/candles';

function gregDtString(ev: Event): string {
return ev.getDate().greg().toLocaleDateString('en-US');
Expand Down Expand Up @@ -585,6 +587,33 @@ test('ykk-only', () => {
isHebrewYear: true,
});
expect(events.length).toBe(9);
const ev = events[0];
expect(ev).toBeInstanceOf(YomKippurKatanEvent);
expect(ev.url()).toBeUndefined();
expect(ev.memo).toBe('Minor Day of Atonement on the day preceeding Rosh Chodesh Kislev');
});

test('ykk with location copies attributes from src', () => {
const dt = new Date(2025, 1, 27);
const events = HebrewCalendar.calendar({
start: dt,
end: dt,
yomKippurKatan: true,
noHolidays: true,
location: Location.lookup('Providence'),
candlelighting: true,
});
const actual = events.map(eventISODateDesc);
const expected = [
{ date: '2025-02-27', desc: 'Fast begins' },
{ date: '2025-02-27', desc: 'Yom Kippur Katan Adar' },
{ date: '2025-02-27', desc: 'Fast ends' }
];
expect(actual).toEqual(expected);
const ev = events[1];
expect(ev).toBeInstanceOf(FastDayEvent);
expect(ev.url()).toBeUndefined();
expect(ev.memo).toBe('Minor Day of Atonement on the day preceeding Rosh Chodesh Adar');
});

test('hallel', () => {
Expand Down

0 comments on commit 41717d8

Please sign in to comment.