Skip to content

Commit

Permalink
Correct sofZmanShma to respect the useElevation parameter (#419)
Browse files Browse the repository at this point in the history
Add new function `sofZmanShmaMGA19Point8` to enable better consistency with Itim Levina
  • Loading branch information
mjradwin committed May 8, 2024
1 parent 9ce2e4b commit 1407a6e
Show file tree
Hide file tree
Showing 5 changed files with 207 additions and 33 deletions.
124 changes: 103 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,19 @@ we omit the thousands (which is presently 5 [ה]).</p>
Ignores final Hebrew letters such as <code>ך</code> (kaf sofit) or <code>ם</code> (mem sofit)
and vowels (nekudot).</p>
</dd>
<dt><a href="#omerSefira">omerSefira(omerDay, lang)</a> ⇒</dt>
<dd><p>Returns the sefira. For example, on day 8
חֶֽסֶד שֶׁבִּגְבוּרָה
Chesed shebiGevurah
Lovingkindness within Might</p>
</dd>
<dt><a href="#omerTodayIs">omerTodayIs(omerDay, lang)</a> ⇒</dt>
<dd><p>Returns a sentence with that evening&#39;s omer count</p>
</dd>
<dt><a href="#omerEmoji">omerEmoji(omerDay)</a> ⇒</dt>
<dd><p>Returns an emoji number symbol with a circle, for example <code>㊲</code>
from the “Enclosed CJK Letters and Months” block of the Unicode standard</p>
</dd>
</dl>

## Typedefs
Expand Down Expand Up @@ -1234,9 +1247,6 @@ href="http://en.wikipedia.org/wiki/Sunrise_equation">Wikipedia Sunrise Equation<
* [NOAACalculator](#NOAACalculator)
* [new NOAACalculator(geoLocation, date)](#new_NOAACalculator_new)
* _instance_
* [.CIVIL_ZENITH](#NOAACalculator+CIVIL_ZENITH)
* [.NAUTICAL_ZENITH](#NOAACalculator+NAUTICAL_ZENITH)
* [.ASTRONOMICAL_ZENITH](#NOAACalculator+ASTRONOMICAL_ZENITH)
* [.getSunrise()](#NOAACalculator+getSunrise) ⇒ <code>Temporal.ZonedDateTime</code> \| <code>null</code>
* [.getSeaLevelSunrise()](#NOAACalculator+getSeaLevelSunrise) ⇒ <code>Temporal.ZonedDateTime</code> \| <code>null</code>
* [.getBeginCivilTwilight()](#NOAACalculator+getBeginCivilTwilight) ⇒ <code>Temporal.ZonedDateTime</code> \| <code>null</code>
Expand All @@ -1261,6 +1271,9 @@ href="http://en.wikipedia.org/wiki/Sunrise_equation">Wikipedia Sunrise Equation<
* [.getSunTransit(startOfDay, endOfDay)](#NOAACalculator+getSunTransit) ⇒ <code>Temporal.ZonedDateTime</code> \| <code>null</code>
* [.getDateFromTime(time, isSunrise)](#NOAACalculator+getDateFromTime) ⇒ <code>Temporal.ZonedDateTime</code> \| <code>null</code>
* _static_
* [.CIVIL_ZENITH](#NOAACalculator.CIVIL_ZENITH)
* [.NAUTICAL_ZENITH](#NOAACalculator.NAUTICAL_ZENITH)
* [.ASTRONOMICAL_ZENITH](#NOAACalculator.ASTRONOMICAL_ZENITH)
* [.getTimeOffset(time, offset)](#NOAACalculator.getTimeOffset) ⇒ <code>Temporal.ZonedDateTime</code> \| <code>null</code>
* [.getSolarElevation(date, lat, lon)](#NOAACalculator.getSolarElevation) ⇒ <code>number</code>
* [.getSolarAzimuth(date, latitude, lon)](#NOAACalculator.getSolarAzimuth) ⇒ <code>number</code>
Expand All @@ -1277,24 +1290,6 @@ parameter.
| geoLocation | [<code>GeoLocation</code>](#GeoLocation) | The location information used for calculating astronomical sun times. |
| date | <code>Temporal.PlainDate</code> | |

<a name="NOAACalculator+CIVIL_ZENITH"></a>

### noaaCalculator.CIVIL\_ZENITH
Sun's zenith at civil twilight (96&deg;).

**Kind**: instance property of [<code>NOAACalculator</code>](#NOAACalculator)
<a name="NOAACalculator+NAUTICAL_ZENITH"></a>

### noaaCalculator.NAUTICAL\_ZENITH
Sun's zenith at nautical twilight (102&deg;).

**Kind**: instance property of [<code>NOAACalculator</code>](#NOAACalculator)
<a name="NOAACalculator+ASTRONOMICAL_ZENITH"></a>

### noaaCalculator.ASTRONOMICAL\_ZENITH
Sun's zenith at astronomical twilight (108&deg;).

**Kind**: instance property of [<code>NOAACalculator</code>](#NOAACalculator)
<a name="NOAACalculator+getSunrise"></a>

### noaaCalculator.getSunrise() ⇒ <code>Temporal.ZonedDateTime</code> \| <code>null</code>
Expand Down Expand Up @@ -1686,6 +1681,24 @@ A method that returns a `Date` from the time passed in as a parameter.
| time | <code>number</code> | The time to be set as the time for the `Date`. The time expected is in the format: 18.75 for 6:45:00 PM. |
| isSunrise | <code>boolean</code> | true if the time is sunrise, and false if it is sunset |

<a name="NOAACalculator.CIVIL_ZENITH"></a>

### NOAACalculator.CIVIL\_ZENITH
Sun's zenith at civil twilight (96&deg;).

**Kind**: static property of [<code>NOAACalculator</code>](#NOAACalculator)
<a name="NOAACalculator.NAUTICAL_ZENITH"></a>

### NOAACalculator.NAUTICAL\_ZENITH
Sun's zenith at nautical twilight (102&deg;).

**Kind**: static property of [<code>NOAACalculator</code>](#NOAACalculator)
<a name="NOAACalculator.ASTRONOMICAL_ZENITH"></a>

### NOAACalculator.ASTRONOMICAL\_ZENITH
Sun's zenith at astronomical twilight (108&deg;).

**Kind**: static property of [<code>NOAACalculator</code>](#NOAACalculator)
<a name="NOAACalculator.getTimeOffset"></a>

### NOAACalculator.getTimeOffset(time, offset) ⇒ <code>Temporal.ZonedDateTime</code> \| <code>null</code>
Expand Down Expand Up @@ -1917,8 +1930,10 @@ https://gml.noaa.gov/grad/solcalc/calcdetails.html
* [.sofZmanTfilla()](#Zmanim+sofZmanTfilla) ⇒ <code>Date</code>
* [.sofZmanShmaMGA()](#Zmanim+sofZmanShmaMGA) ⇒ <code>Date</code>
* [.sofZmanShmaMGA16Point1()](#Zmanim+sofZmanShmaMGA16Point1) ⇒ <code>Date</code>
* [.sofZmanShmaMGA19Point8()](#Zmanim+sofZmanShmaMGA19Point8) ⇒ <code>Date</code>
* [.sofZmanTfillaMGA()](#Zmanim+sofZmanTfillaMGA) ⇒ <code>Date</code>
* [.sofZmanTfillaMGA16Point1()](#Zmanim+sofZmanTfillaMGA16Point1) ⇒ <code>Date</code>
* [.sofZmanTfillaMGA19Point8()](#Zmanim+sofZmanTfillaMGA19Point8) ⇒ <code>Date</code>
* [.minchaGedola()](#Zmanim+minchaGedola) ⇒ <code>Date</code>
* [.minchaKetana()](#Zmanim+minchaKetana) ⇒ <code>Date</code>
* [.plagHaMincha()](#Zmanim+plagHaMincha) ⇒ <code>Date</code>
Expand Down Expand Up @@ -2069,6 +2084,18 @@ Latest Shema (MGA); Sunrise plus 3 halachic hours, according to Magen Avraham.
Based on the opinion of the MGA that the day is calculated from
dawn to nightfall with both being 16.1° below the horizon.

**Kind**: instance method of [<code>Zmanim</code>](#Zmanim)
<a name="Zmanim+sofZmanShmaMGA19Point8"></a>

### zmanim.sofZmanShmaMGA19Point8() ⇒ <code>Date</code>
Latest Shema (MGA); Sunrise plus 3 halachic hours, according to Magen Avraham.
Based on the opinion of the MGA that the day is calculated from
dawn to nightfall with both being 19.8° below the horizon.

This calculation is based on the position of the sun 90 minutes after sunset in Jerusalem
around the equinox / equilux which calculates to 19.8° below geometric zenith.
https://kosherjava.com/2022/01/12/equinox-vs-equilux-zmanim-calculations/

**Kind**: instance method of [<code>Zmanim</code>](#Zmanim)
<a name="Zmanim+sofZmanTfillaMGA"></a>

Expand All @@ -2083,6 +2110,18 @@ Latest Shacharit (MGA); Sunrise plus 4 halachic hours, according to Magen Avraha
Based on the opinion of the MGA that the day is calculated from
dawn to nightfall with both being 16.1° below the horizon.

**Kind**: instance method of [<code>Zmanim</code>](#Zmanim)
<a name="Zmanim+sofZmanTfillaMGA19Point8"></a>

### zmanim.sofZmanTfillaMGA19Point8() ⇒ <code>Date</code>
Latest Shacharit (MGA); Sunrise plus 4 halachic hours, according to Magen Avraham.
Based on the opinion of the MGA that the day is calculated from
dawn to nightfall with both being 19.8° below the horizon.

This calculation is based on the position of the sun 90 minutes after sunset in Jerusalem
around the equinox / equilux which calculates to 19.8° below geometric zenith.
https://kosherjava.com/2022/01/12/equinox-vs-equilux-zmanim-calculations/

**Kind**: instance method of [<code>Zmanim</code>](#Zmanim)
<a name="Zmanim+minchaGedola"></a>

Expand Down Expand Up @@ -3453,6 +3492,49 @@ and vowels (nekudot).
| --- | --- |
| str | <code>string</code> |

<a name="omerSefira"></a>

## omerSefira(omerDay, lang) ⇒
Returns the sefira. For example, on day 8
חֶֽסֶד שֶׁבִּגְבוּרָה
Chesed shebiGevurah
Lovingkindness within Might

**Kind**: global function
**Returns**: a string such as `Lovingkindness within Might` or `חֶֽסֶד שֶׁבִּגְבוּרָה`

| Param | Description |
| --- | --- |
| omerDay | the day of the omer, 1-49 inclusive |
| lang | `en` (English), `he` (Hebrew with nikud), or `translit` (Hebrew in Sephardic transliteration) |

<a name="omerTodayIs"></a>

## omerTodayIs(omerDay, lang) ⇒
Returns a sentence with that evening's omer count

**Kind**: global function
**Returns**: a string such as `Today is 10 days, which is 1 week and 3 days of the Omer`
or `הַיוֹם עֲשָׂרָה יָמִים, שְׁהֵם שָׁבוּעַ אֶחָד וְשְׁלוֹשָׁה יָמִים לָעוֹמֶר`

| Param | Description |
| --- | --- |
| omerDay | the day of the omer, 1-49 inclusive |
| lang | `en` (English), `he` (Hebrew with nikud) |

<a name="omerEmoji"></a>

## omerEmoji(omerDay) ⇒
Returns an emoji number symbol with a circle, for example ``
from the “Enclosed CJK Letters and Months” block of the Unicode standard

**Kind**: global function
**Returns**: a single Unicode character from `` through ``

| Param | Description |
| --- | --- |
| omerDay | the day of the omer, 1-49 inclusive |

<a name="SedraResult"></a>

## SedraResult : <code>Object</code>
Expand Down
22 changes: 21 additions & 1 deletion hebcal.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -484,15 +484,35 @@ declare module '@hebcal/core' {
* dawn to nightfall with both being 16.1° below the horizon.
*/
sofZmanShmaMGA16Point1(): Date;
/**
* Latest Shema (MGA); Sunrise plus 3 halachic hours, according to Magen Avraham.
* Based on the opinion of the MGA that the day is calculated from
* dawn to nightfall with both being 19.8° below the horizon.
*
* This calculation is based on the position of the sun 90 minutes after sunset in Jerusalem
* around the equinox / equilux which calculates to 19.8° below geometric zenith.
* https://kosherjava.com/2022/01/12/equinox-vs-equilux-zmanim-calculations/
*/
sofZmanShmaMGA19Point8(): Date;
/** Latest Shacharit (MGA); Sunrise plus 4 halachic hours, according to Magen Avraham */
sofZmanTfillaMGA(): Date;
/** Earliest Mincha – Mincha Gedola; Sunrise plus 6.5 halachic hours */
/**
* Latest Shacharit (MGA); Sunrise plus 4 halachic hours, according to Magen Avraham.
* Based on the opinion of the MGA that the day is calculated from
* dawn to nightfall with both being 16.1° below the horizon.
*/
sofZmanTfillaMGA16Point1(): Date;
/**
* Latest Shacharit (MGA); Sunrise plus 4 halachic hours, according to Magen Avraham.
* Based on the opinion of the MGA that the day is calculated from
* dawn to nightfall with both being 19.8° below the horizon.
*
* This calculation is based on the position of the sun 90 minutes after sunset in Jerusalem
* around the equinox / equilux which calculates to 19.8° below geometric zenith.
* https://kosherjava.com/2022/01/12/equinox-vs-equilux-zmanim-calculations/
*/
sofZmanTfillaMGA19Point8(): Date;
/** Earliest Mincha – Mincha Gedola; Sunrise plus 6.5 halachic hours */
minchaGedola(): Date;
/** Preferable earliest time to recite Minchah – Mincha Ketana; Sunrise plus 9.5 halachic hours */
minchaKetana(): Date;
Expand Down
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.3.6",
"version": "5.3.7",
"author": "Michael J. Radwin (https://github.com/mjradwin)",
"contributors": [
"Eyal Schachter (https://github.com/Scimonster)",
Expand Down
47 changes: 38 additions & 9 deletions src/zmanim.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,8 @@ export class Zmanim {
* @return {Date}
*/
getShaahZmanisBasedZman(hours) {
const startOfDay = this.noaa.getSunrise();
const endOfDay = this.noaa.getSunset();
const startOfDay = this.useElevation ? this.noaa.getSunrise() : this.noaa.getSeaLevelSunrise();
const endOfDay = this.useElevation ? this.noaa.getSunset() : this.noaa.getSeaLevelSunset();
const temporalHour = this.noaa.getTemporalHour(startOfDay, endOfDay);
const offset = Math.round(temporalHour * hours);
const zdt = NOAACalculator.getTimeOffset(startOfDay, offset);
Expand Down Expand Up @@ -235,13 +235,14 @@ export class Zmanim {
/**
* Returns an array with alot (Date) and ms in hour (number)
* @private
* @param {number} angle
* @return {any[]}
*/
getTemporalHour16Point1() {
const alot16one = this.alotHaShachar();
const tzeit16one = this.tzeit(16.1);
const temporalHour = (tzeit16one - alot16one) / 12;
return [alot16one, temporalHour];
getTemporalHourByDeg(angle) {
const alot = this.timeAtAngle(angle, true);
const tzeit = this.timeAtAngle(angle, false);
const temporalHour = (tzeit - alot) / 12;
return [alot, temporalHour];
}
/**
* Latest Shema (MGA); Sunrise plus 3 halachic hours, according to Magen Avraham.
Expand All @@ -261,7 +262,21 @@ export class Zmanim {
* @return {Date}
*/
sofZmanShmaMGA16Point1() {
const [alot, temporalHour] = this.getTemporalHour16Point1();
const [alot, temporalHour] = this.getTemporalHourByDeg(16.1);
return new Date(alot.getTime() + (3 * temporalHour));
}
/**
* Latest Shema (MGA); Sunrise plus 3 halachic hours, according to Magen Avraham.
* Based on the opinion of the MGA that the day is calculated from
* dawn to nightfall with both being 19.8° below the horizon.
*
* This calculation is based on the position of the sun 90 minutes after sunset in Jerusalem
* around the equinox / equilux which calculates to 19.8° below geometric zenith.
* https://kosherjava.com/2022/01/12/equinox-vs-equilux-zmanim-calculations/
* @return {Date}
*/
sofZmanShmaMGA19Point8() {
const [alot, temporalHour] = this.getTemporalHourByDeg(19.8);
return new Date(alot.getTime() + (3 * temporalHour));
}
/**
Expand All @@ -279,7 +294,21 @@ export class Zmanim {
* @return {Date}
*/
sofZmanTfillaMGA16Point1() {
const [alot, temporalHour] = this.getTemporalHour16Point1();
const [alot, temporalHour] = this.getTemporalHourByDeg(16.1);
return new Date(alot.getTime() + (4 * temporalHour));
}
/**
* Latest Shacharit (MGA); Sunrise plus 4 halachic hours, according to Magen Avraham.
* Based on the opinion of the MGA that the day is calculated from
* dawn to nightfall with both being 19.8° below the horizon.
*
* This calculation is based on the position of the sun 90 minutes after sunset in Jerusalem
* around the equinox / equilux which calculates to 19.8° below geometric zenith.
* https://kosherjava.com/2022/01/12/equinox-vs-equilux-zmanim-calculations/
* @return {Date}
*/
sofZmanTfillaMGA19Point8() {
const [alot, temporalHour] = this.getTemporalHourByDeg(19.8);
return new Date(alot.getTime() + (4 * temporalHour));
}
/**
Expand Down
45 changes: 44 additions & 1 deletion src/zmanim.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,13 @@ test('zmanim', (t) => {
dawn: '04:42',
sunrise: '05:16',
neitzHaChama: '05:16',
sofZmanShma: '09:02',
sofZmanShmaMGA19Point8: '07:49',
sofZmanShmaMGA16Point1: '08:07',
sofZmanShmaMGA: '08:26',
sofZmanShma: '09:02',
sofZmanTfilla: '10:18',
sofZmanTfillaMGA19Point8: '09:29',
sofZmanTfillaMGA16Point1: '09:41',
sofZmanTfillaMGA: '09:54',
chatzot: '12:49',
minchaGedola: '13:27',
Expand Down Expand Up @@ -163,9 +167,13 @@ test('zmanim-denver', (t) => {
// "SeaLevelSunrise": "2020-06-05T05:32:26-06:00",
seaLevelSunrise: '06/05/2020, 05:32:26',
neitzHaChama: '06/05/2020, 05:24:30',
sofZmanShmaMGA19Point8: '06/05/2020, 08:07:51',
sofZmanShmaMGA16Point1: '06/05/2020, 08:23:44',
sofZmanShma: '06/05/2020, 09:11:37',
sofZmanShmaMGA: '06/05/2020, 08:39:34', // 08:35:37 AM
sofZmanTfilla: '06/05/2020, 10:27:19', // 10:03:19 AM
sofZmanTfillaMGA19Point8: '06/05/2020, 09:44:53',
sofZmanTfillaMGA16Point1: '06/05/2020, 09:55:26',
// "SofZmanTfilaMGA": "2020-06-05T10:05:57-06:00",
sofZmanTfillaMGA: '06/05/2020, 10:05:57',
// "Chatzos": "2020-06-05T12:58:43-06:00",
Expand Down Expand Up @@ -482,9 +490,11 @@ test('zmanim-UTC', (t) => {
seaLevelSunrise: '05:54:56',
sofZmanShma: '08:56:27',
sofZmanShmaMGA: '08:20:45',
sofZmanShmaMGA19Point8: '08:15:32',
sofZmanShmaMGA16Point1: '08:23:36',
sofZmanTfilla: '09:57:10',
sofZmanTfillaMGA: '09:33:22',
sofZmanTfillaMGA19Point8: '09:29:53',
sofZmanTfillaMGA16Point1: '09:35:16',
chatzot: '11:58:36',
minchaGedola: '12:28:57',
Expand All @@ -507,3 +517,36 @@ test('zmanim-UTC', (t) => {
t.is(f.format(zman.sunsetOffset(72, false, false)), '19:14:53');
t.is(f.format(zman.sunsetOffset(72, false, true)), '19:14:15');
});

test('zmanim-Beitar Ilit', (t) => {
const latitude = 31.693;
const longitude = 35.108;
const elevation = 659.7;
const tzid = 'Asia/Jerusalem';
const gloc = new GeoLocation('Betar', latitude, longitude, elevation, tzid);
const zman = new Zmanim(gloc, new Date(2024, 3, 23), false);
const f = new Intl.DateTimeFormat('en-US', {
timeZone: tzid,
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false,
});

const expected = {
sofZmanShmaMGA19Point8: '04/23/2024, 08:31:46',
sofZmanShmaMGA16Point1: '04/23/2024, 08:41:36',
sofZmanShmaMGA: '04/23/2024, 08:43:57',
sofZmanShma: '04/23/2024, 09:19:58',
};

const actual = {};
for (const func of Object.keys(expected)) {
const dt = zman[func]();
actual[func] = f.format(dt);
}
t.deepEqual(actual, expected);
});

0 comments on commit 1407a6e

Please sign in to comment.