hebcal / hebcal-es6

perpetual Jewish Calendar with holidays, Shabbat and holiday candle lighting and havdalah times, Torah readings, and more
https://hebcal.github.io/api/core/
GNU General Public License v2.0
98 stars 14 forks source link

Calculating Hebrew Date After Nightfall #450

Open asharonbaltazar opened 4 weeks ago

asharonbaltazar commented 4 weeks ago

First off, some words of encouragement: this is a great library, and I'm grateful you have made it possible. Second, I'd like to know whether there's an easy way to generate the correct Hebrew date after nightfall. We pass a civil date as an argument to HDate, but it doesn't return the next Hebrew date if the time is after shkiyah/tzeit. Is there a flag I'm missing?

Appreciate it!

Edit: Reading the docs revealed that HDate ignores the time. That's probably why it doesn't work. So perhaps there's a different class/method I should be calling?

P.S. GH has a Discussions tab that will probably reduce the amount of issue noise.

mjradwin commented 4 weeks ago

Thanks so much for your kind words and for using the Hebcal JavaScript library.

An instance of HDate encapsulates a date in the Hebrew calendar system. It consists of a year, month, and day, without any associated time or location data. The API is intentionally designed to keep the HDate class simple. It is a deliberate choice for HDate to store only a day, month and year and not have any complexity of time of day or location.

You can get the current Hebrew date relative to sunset using a few lines of code like the ones described in #383.

Here is a similar example:

const {GeoLocation, Zmanim, HDate} = require('@hebcal/core');
const latitude = 41.822232;
const longitude = -71.448292;
const tzid = 'America/New_York';
const now = new Date();
const gloc = new GeoLocation(null, latitude, longitude, 0, tzid);
const zmanim = new Zmanim(gloc, now, false);
const sunset = zmanim.sunset();
let hd = new HDate(now);
if (now >= sunset) {
  hd = hd.next();
}

We will consider adding this code example to the HDate documentation to save others the effort from having to struggle through this example.

YizYah commented 3 weeks ago

@mjradwin I do have a thought about this. I do not think you should compromise on the simplicity of HDate, and it should not be connected with a location. But, as a practical matter, if an HDate is needed for a known location and time, then I think it would be nice to construct an accurate one rather than incrementing it.

So how about an optional gloc param in the constructor? If gloc is not set, then the HDate is set as before. [Note: this is not a breaking change!] But if there is a gloc, then the constructor checks the time of sunset before setting the HDate and will choose between the two dates based upon whether now is before sunset. So the resulting HDate is as simple as before. (The location will NOT be retained in any way).

mjradwin commented 3 weeks ago

A good suggestion! But would this would introduce a large code dependency? The Zmanim class, which internally uses the NOAACalculator and GeoLocation, is the code that determines when sunset is for a location. The JavaScript bundle size would grow significantly if HDate included this code, and many applications which are sensitive to the size of the libraries they use don't need this capability.

YizYah commented 3 weeks ago

Got it...

In that case, perhaps a "preferred" way to create an HDate for a known location should be via a new method in GeoLocation:

const {GeoLocation, Zmanim, HDate} = require('@hebcal/core');
const latitude = 41.822232;
const longitude = -71.448292;
const tzid = 'America/New_York';
const gloc = new GeoLocation(null, latitude, longitude, 0, tzid);
const now = new Date();
const hd = gloc.createHDate(now);

The issue to me is an abstraction layer. It is true that a Hebrew date is not inferable with just a secular date (even with a time) without a location. So if someone wants to "convert", they should ideally do so in a way that is complete from the start rather than doing lower level logic. I also think that currently this is a "gotcha" for hebcal, because its easy to think you converted a date when in reality you did not.