Skip to content

Commit

Permalink
Make more zmanim concur with KosherJava
Browse files Browse the repository at this point in the history
  • Loading branch information
mjradwin committed Nov 21, 2023
1 parent f42215f commit b62ceff
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 122 deletions.
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
"@babel/core": "^7.23.3",
"@babel/preset-env": "^7.23.3",
"@babel/register": "^7.22.15",
"@hebcal/noaa": "^0.8.1",
"@hebcal/noaa": "^0.8.2",
"@hebcal/solar-calc": "^1.1.2",
"@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-commonjs": "^25.0.7",
Expand Down
70 changes: 35 additions & 35 deletions src/candles.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ test('makeCandleEvent-nosunset', (t) => {
}
const result = events.map(eventDateDesc);
const expected = [
{date: '2020-05-15', desc: 'Candle lighting: 21:38'},
{date: '2020-05-15', desc: 'Candle lighting: 21:36'},
{date: '2020-05-16', desc: 'Havdalah: 23:49'},
{date: '2020-05-22', desc: 'Candle lighting: 21:54'},
{date: '2020-05-22', desc: 'Candle lighting: 21:52'},
{date: '2020-05-23', desc: 'Havdalah: 00:31'},
{date: '2020-05-29', desc: 'Candle lighting: 22:08'},
{date: '2020-05-29', desc: 'Candle lighting: 22:06'},
null, // no tzeit
{date: '2020-06-05', desc: 'Candle lighting: 22:20'},
{date: '2020-06-05', desc: 'Candle lighting: 22:18'},
null, // no tzeit
];
t.deepEqual(result, expected);
Expand All @@ -60,14 +60,14 @@ test('makeCandleEvent-nosunset', (t) => {
}
const result2 = events2.map(eventDateDesc);
const expected2 = [
{date: '2020-05-15', desc: 'Candle lighting: 21:38'},
{date: '2020-05-16', desc: 'Havdalah (72 min): 23:11'},
{date: '2020-05-22', desc: 'Candle lighting: 21:54'},
{date: '2020-05-23', desc: 'Havdalah (72 min): 23:26'},
{date: '2020-05-29', desc: 'Candle lighting: 22:08'},
{date: '2020-05-30', desc: 'Havdalah (72 min): 23:41'},
{date: '2020-06-05', desc: 'Candle lighting: 22:20'},
{date: '2020-06-06', desc: 'Havdalah (72 min): 23:52'},
{date: '2020-05-15', desc: 'Candle lighting: 21:36'},
{date: '2020-05-16', desc: 'Havdalah (72 min): 23:09'},
{date: '2020-05-22', desc: 'Candle lighting: 21:52'},
{date: '2020-05-23', desc: 'Havdalah (72 min): 23:25'},
{date: '2020-05-29', desc: 'Candle lighting: 22:06'},
{date: '2020-05-30', desc: 'Havdalah (72 min): 23:39'},
{date: '2020-06-05', desc: 'Candle lighting: 22:18'},
{date: '2020-06-06', desc: 'Havdalah (72 min): 23:50'},
];
t.deepEqual(result2, expected2);
});
Expand All @@ -84,9 +84,9 @@ test('candles-only-diaspora', (t) => {
t.is(events.length, 132);
const ev0 = events[0];
t.is(Boolean(ev0.getFlags() & flags.LIGHT_CANDLES), true);
t.is(ev0.render('en'), 'Candle lighting: 16:16');
t.is(ev0.render('en'), 'Candle lighting: 16:13');
t.is(ev0.getDesc(), 'Candle lighting');
t.is(ev0.eventTimeStr, '16:16');
t.is(ev0.eventTimeStr, '16:13');
const ev1 = events[1];
t.is(Boolean(ev1.getFlags() & flags.LIGHT_CANDLES_TZEIS), true);
t.is(ev1.render('en'), 'Havdalah: 17:18');
Expand Down Expand Up @@ -230,23 +230,23 @@ test('candleLightingMins', (t) => {
};
const events30 = HebrewCalendar.calendar(options).map(eventTitleDateTime);
const expected30 = [
{dt: '2020-05-01T18:52:00+03:00', desc: 'Candle lighting'},
{dt: '2020-05-08T18:57:00+03:00', desc: 'Candle lighting'},
{dt: '2020-05-15T19:02:00+03:00', desc: 'Candle lighting'},
{dt: '2020-05-22T19:07:00+03:00', desc: 'Candle lighting'},
{dt: '2020-05-01T18:51:00+03:00', desc: 'Candle lighting'},
{dt: '2020-05-08T18:56:00+03:00', desc: 'Candle lighting'},
{dt: '2020-05-15T19:01:00+03:00', desc: 'Candle lighting'},
{dt: '2020-05-22T19:06:00+03:00', desc: 'Candle lighting'},
{dt: '2020-05-28T19:10:00+03:00', desc: 'Candle lighting'},
{dt: '2020-05-29T19:11:00+03:00', desc: 'Candle lighting'},
{dt: '2020-05-29T19:10:00+03:00', desc: 'Candle lighting'},
];
t.deepEqual(events30, expected30);
delete options.candleLightingMins;
const events18 = HebrewCalendar.calendar(options).map(eventTitleDateTime);
const expected18 = [
{dt: '2020-05-01T19:04:00+03:00', desc: 'Candle lighting'},
{dt: '2020-05-08T19:09:00+03:00', desc: 'Candle lighting'},
{dt: '2020-05-15T19:14:00+03:00', desc: 'Candle lighting'},
{dt: '2020-05-22T19:19:00+03:00', desc: 'Candle lighting'},
{dt: '2020-05-01T19:03:00+03:00', desc: 'Candle lighting'},
{dt: '2020-05-08T19:08:00+03:00', desc: 'Candle lighting'},
{dt: '2020-05-15T19:13:00+03:00', desc: 'Candle lighting'},
{dt: '2020-05-22T19:18:00+03:00', desc: 'Candle lighting'},
{dt: '2020-05-28T19:22:00+03:00', desc: 'Candle lighting'},
{dt: '2020-05-29T19:23:00+03:00', desc: 'Candle lighting'},
{dt: '2020-05-29T19:22:00+03:00', desc: 'Candle lighting'},
];
t.deepEqual(events18, expected18);
});
Expand All @@ -267,16 +267,16 @@ test('jerusalem40', (t) => {
const items = candleEvents.map(eventTitleDateTime);
const expected = [
{dt: '2020-01-03T16:07:00+02:00', desc: 'Candle lighting'},
{dt: '2020-01-10T16:13:00+02:00', desc: 'Candle lighting'},
{dt: '2020-01-10T16:12:00+02:00', desc: 'Candle lighting'},
{dt: '2020-01-17T16:19:00+02:00', desc: 'Candle lighting'},
{dt: '2020-01-24T16:25:00+02:00', desc: 'Candle lighting'},
{dt: '2020-01-31T16:32:00+02:00', desc: 'Candle lighting'},
{dt: '2020-01-31T16:31:00+02:00', desc: 'Candle lighting'},
{dt: '2020-02-07T16:38:00+02:00', desc: 'Candle lighting'},
{dt: '2020-02-14T16:44:00+02:00', desc: 'Candle lighting'},
{dt: '2020-02-21T16:50:00+02:00', desc: 'Candle lighting'},
{dt: '2020-02-28T16:55:00+02:00', desc: 'Candle lighting'},
{dt: '2020-03-06T17:01:00+02:00', desc: 'Candle lighting'},
{dt: '2020-03-13T17:06:00+02:00', desc: 'Candle lighting'},
{dt: '2020-03-06T17:00:00+02:00', desc: 'Candle lighting'},
{dt: '2020-03-13T17:05:00+02:00', desc: 'Candle lighting'},
{dt: '2020-03-20T17:10:00+02:00', desc: 'Candle lighting'},
{dt: '2020-03-27T18:15:00+03:00', desc: 'Candle lighting'},
];
Expand All @@ -295,8 +295,8 @@ test('jerusalem31', (t) => {
const candleEvents = events.filter((ev) => ev.getDesc() === 'Candle lighting');
const items = candleEvents.map(eventTitleDateTime);
const expected = [
{dt: '2020-03-06T17:10:00+02:00', desc: 'Candle lighting'},
{dt: '2020-03-13T17:15:00+02:00', desc: 'Candle lighting'},
{dt: '2020-03-06T17:09:00+02:00', desc: 'Candle lighting'},
{dt: '2020-03-13T17:14:00+02:00', desc: 'Candle lighting'},
{dt: '2020-03-20T17:19:00+02:00', desc: 'Candle lighting'},
{dt: '2020-03-27T18:24:00+03:00', desc: 'Candle lighting'},
];
Expand All @@ -315,8 +315,8 @@ test('jerusalem18-forced-to-40', (t) => {
const candleEvents = events.filter((ev) => ev.getDesc() === 'Candle lighting');
const items = candleEvents.map(eventTitleDateTime);
const expected = [
{dt: '2020-03-06T17:01:00+02:00', desc: 'Candle lighting'},
{dt: '2020-03-13T17:06:00+02:00', desc: 'Candle lighting'},
{dt: '2020-03-06T17:00:00+02:00', desc: 'Candle lighting'},
{dt: '2020-03-13T17:05:00+02:00', desc: 'Candle lighting'},
{dt: '2020-03-20T17:10:00+02:00', desc: 'Candle lighting'},
{dt: '2020-03-27T18:15:00+03:00', desc: 'Candle lighting'},
];
Expand Down Expand Up @@ -455,9 +455,9 @@ test('no-chanukah-candles-when-noHolidays', (t) => {
};
const events = HebrewCalendar.calendar(options);
const expected = [
{dt: '2020-12-11T16:01:00-08:00', desc: 'Candle lighting'},
{dt: '2020-12-11T15:59:00-08:00', desc: 'Candle lighting'},
{dt: '2020-12-12T17:10:00-08:00', desc: 'Havdalah'},
{dt: '2020-12-18T16:02:00-08:00', desc: 'Candle lighting'},
{dt: '2020-12-18T16:01:00-08:00', desc: 'Candle lighting'},
{dt: '2020-12-19T17:12:00-08:00', desc: 'Havdalah'},
];
const actual = events.map(eventTitleDateTime);
Expand Down Expand Up @@ -585,7 +585,7 @@ test('yk-candles-only', (t) => {
});
const actual = events.map(eventTitleDateTime);
const expected = [
{dt: '2022-10-04T18:03:00-04:00', desc: 'Candle lighting'},
{dt: '2022-10-04T18:02:00-04:00', desc: 'Candle lighting'},
{dt: '2022-10-05T19:00:00-04:00', desc: 'Havdalah'},
];
t.deepEqual(actual, expected);
Expand Down
108 changes: 76 additions & 32 deletions src/zmanim.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,20 @@ function pad2(number) {
return String(number);
}

/**
* @private
* @param {Temporal.ZonedDateTime} zdt
* @return {Date}
*/
function zdtToDate(zdt) {
if (zdt === null) {
return new Date(NaN);
}
const res = new Date(zdt.epochMilliseconds);
res.setMilliseconds(0);
return res;
}

/**
* @typedef {Object} ZmanimTimesResult
* @property {Date} dawn
Expand Down Expand Up @@ -140,12 +154,7 @@ export class Zmanim {
const offsetZenith = 90 + angle;
const zdt = rising ? this.noaa.getSunriseOffsetByDegrees(offsetZenith) :
this.noaa.getSunsetOffsetByDegrees(offsetZenith);
if (zdt === null) {
return new Date(NaN);
}
const res = new Date(zdt.epochMilliseconds);
res.setMilliseconds(0);
return res;
return zdtToDate(zdt);
}
return this.sun.timeAtAngle(angle, rising);
}
Expand All @@ -156,12 +165,18 @@ export class Zmanim {
sunrise() {
if (this.noaa) {
const zdt = this.noaa.getSunrise();
if (zdt === null) {
return new Date(NaN);
}
const res = new Date(zdt.epochMilliseconds);
res.setMilliseconds(0);
return res;
return zdtToDate(zdt);
}
return this.sun.timeAtAngle(0.833333, true);
}
/**
* Upper edge of the Sun appears over the eastern horizon in the morning (0.833° above horizon)
* @return {Date}
*/
seaLevelSunrise() {
if (this.noaa) {
const zdt = this.noaa.getSeaLevelSunrise();
return zdtToDate(zdt);
}
return this.sun.timeAtAngle(0.833333, true);
}
Expand All @@ -172,12 +187,18 @@ export class Zmanim {
sunset() {
if (this.noaa) {
const zdt = this.noaa.getSunset();
if (zdt === null) {
return new Date(NaN);
}
const res = new Date(zdt.epochMilliseconds);
res.setMilliseconds(0);
return res;
return zdtToDate(zdt);
}
return this.sun.timeAtAngle(0.833333, false);
}
/**
* When the upper edge of the Sun disappears below the horizon (0.833° below horizon)
* @return {Date}
*/
seaLevelSunset() {
if (this.noaa) {
const zdt = this.noaa.getSeaLevelSunset();
return zdtToDate(zdt);
}
return this.sun.timeAtAngle(0.833333, false);
}
Expand All @@ -188,12 +209,7 @@ export class Zmanim {
dawn() {
if (this.noaa) {
const zdt = this.noaa.getBeginCivilTwilight();
if (zdt === null) {
return new Date(NaN);
}
const res = new Date(zdt.epochMilliseconds);
res.setMilliseconds(0);
return res;
return zdtToDate(zdt);
}
return this.sun.timeAtAngle(6, true);
}
Expand All @@ -204,12 +220,7 @@ export class Zmanim {
dusk() {
if (this.noaa) {
const zdt = this.noaa.getEndCivilTwilight();
if (zdt === null) {
return new Date(NaN);
}
const res = new Date(zdt.epochMilliseconds);
res.setMilliseconds(0);
return res;
return zdtToDate(zdt);
}
return this.sun.timeAtAngle(6, false);
}
Expand Down Expand Up @@ -250,6 +261,10 @@ export class Zmanim {
* @return {Date}
*/
chatzot() {
if (this.noaa) {
const zdt = this.noaa.getSunTransit();
return zdtToDate(zdt);
}
return this.hourOffset(6);
}
/**
Expand Down Expand Up @@ -280,18 +295,38 @@ export class Zmanim {
misheyakirMachmir() {
return this.timeAtAngle(10.2, true);
}
/**
* Utility method for using elevation-aware sunrise/sunset
* @private
* @param {number} hours
* @return {Date}
*/
getShaahZmanisBasedZman(hours) {
const startOfDay = this.noaa.getSunrise();
const endOfDay = this.noaa.getSunset();
const temporalHour = this.noaa.getTemporalHour(startOfDay, endOfDay);
const offset = Math.round(temporalHour * hours);
const zdt = NOAACalculator.getTimeOffset(startOfDay, offset);
return zdtToDate(zdt);
}
/**
* Latest Shema (Gra); Sunrise plus 3 halachic hours, according to the Gra
* @return {Date}
*/
sofZmanShma() { // Gra
if (this.noaa) {
return this.getShaahZmanisBasedZman(3);
}
return this.hourOffset(3);
}
/**
* Latest Shacharit (Gra); Sunrise plus 4 halachic hours, according to the Gra
* @return {Date}
*/
sofZmanTfilla() { // Gra
if (this.noaa) {
return this.getShaahZmanisBasedZman(4);
}
return this.hourOffset(4);
}
/**
Expand Down Expand Up @@ -319,20 +354,29 @@ export class Zmanim {
* @return {Date}
*/
minchaGedola() {
if (this.noaa) {
return this.getShaahZmanisBasedZman(6.5);
}
return this.hourOffset(6.5);
}
/**
* Preferable earliest time to recite Minchah – Mincha Ketana; Sunrise plus 9.5 halachic hours
* @return {Date}
*/
minchaKetana() {
if (this.noaa) {
return this.getShaahZmanisBasedZman(9.5);
}
return this.hourOffset(9.5);
}
/**
* Plag haMincha; Sunrise plus 10.75 halachic hours
* @return {Date}
*/
plagHaMincha() {
if (this.noaa) {
return this.getShaahZmanisBasedZman(10.75);
}
return this.hourOffset(10.75);
}
/**
Expand Down Expand Up @@ -428,7 +472,7 @@ export class Zmanim {
* @return {Date}
*/
sunriseOffset(offset, roundMinute=true) {
const sunrise = this.sunrise();
const sunrise = this.seaLevelSunrise();
if (isNaN(sunrise.getTime())) {
return sunrise;
}
Expand All @@ -449,7 +493,7 @@ export class Zmanim {
* @return {Date}
*/
sunsetOffset(offset, roundMinute=true) {
const sunset = this.sunset();
const sunset = this.seaLevelSunset();
if (isNaN(sunset.getTime())) {
return sunset;
}
Expand Down
Loading

0 comments on commit b62ceff

Please sign in to comment.