diff --git a/README.md b/README.md index 34829a59..9a580383 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,17 @@ Adds a custom time when the sun reaches the given angle to results returned by ` `SunCalc.times` property contains all currently defined times. +```javascript +SunCalc.getRiseAndSetAtSolarAngle(/*Date*/ timeAndDate, /*Number*/ angle, /*Number*/ latitude, /*Number*/ longitude, /*Number (default=0)*/ elevation) +``` + +Returns an object containing the times at which the sun will reach the given angle at the given +location and elevation. The object contains the following properties (each is a `Date` object): + +| Property | Description | +| --------------- | ------------------------------------------------------------------------ | +| `rise` | The time at which the sun will reach the given angle when it is rising | +| `set` | The time at which the sun will reach the given angle when it is setting | ### Sun position diff --git a/suncalc.js b/suncalc.js index c9ca56d2..868664f0 100644 --- a/suncalc.js +++ b/suncalc.js @@ -180,6 +180,46 @@ SunCalc.getTimes = function (date, lat, lng, height) { return result; }; +/** + * Get the time at which the sun will have a given apparent angle when rising and when setting. + * + * @param {Date} date The date to get the times for. Only the date part is important. + * @param {number} angle The angle of the sun relative to the Earth's horizon. + * @param {number} lat The latitude. + * @param {number} lng The longitude. + * @param {number} [elevation=0] The elevation of the observer in meters. + * @return {{set: Date, rise: Date}} + */ +SunCalc.getRiseAndSetAtSolarAngle = function (date, angle, lat, lng, elevation) { + + elevation = elevation || 0; + angle = angle - astroRefraction(angle) * 100; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(elevation), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + h0 = (angle + dh) * rad, + + Jset = getSetJ(h0, lw, phi, dec, n, M, L), + Jrise = Jnoon - (Jset - Jnoon); + + return { + rise: fromJulian(Jrise), + set: fromJulian(Jset), + }; +}; + // moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas diff --git a/test.js b/test.js index 37ac4674..e9bc44de 100644 --- a/test.js +++ b/test.js @@ -61,6 +61,23 @@ t.test('getTimes adjusts sun phases when additionally given the observer height' t.end(); }); +t.test('getRiseAndSetAtSolarAngle returns the correct time for the given date and location', function (t) { + var times = SunCalc.getRiseAndSetAtSolarAngle(date, 0, lat, lng); + + t.equal(new Date(times.rise).toString(), new Date(testTimes.sunrise).toString()); + t.equal(times.set.toString(), new Date(testTimes.sunset).toString()); + t.end(); +}); + +t.test('getRiseAndSetAtAngle adjusts sun phases when additionally given the observer\'s elevation', function (t) { + var times = SunCalc.getRiseAndSetAtSolarAngle(date, 0, lat, lng, height); + + t.equal(new Date(heightTestTimes.sunrise).toUTCString(), times.rise.toUTCString()); + t.equal(new Date(heightTestTimes.sunset).toUTCString(), times.set.toUTCString()); + + t.end(); +}); + t.test('getMoonPosition returns moon position data given time and location', function (t) { var moonPos = SunCalc.getMoonPosition(date, lat, lng);