From 5be213169750868f5bde6332556139861ad56601 Mon Sep 17 00:00:00 2001 From: Matthias Kunnen Date: Wed, 26 Jun 2019 02:21:14 +0000 Subject: [PATCH 1/6] Added the getTimesAtAltitude method --- README.md | 11 +++++++++++ suncalc.js | 24 ++++++++++++++++++++++++ test.js | 7 +++++++ 3 files changed, 42 insertions(+) diff --git a/README.md b/README.md index 34829a59..3406efe0 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.getTimesAtAltitude(/*Date*/ timeAndDate, /*Number*/ angleInDegrees, /*Number*/ latitude, /*Number*/ longitude) +``` + +Returns an object containing the times at which the sun will reach the given altitude at the given +location. The object contains the following properties (each is a `Date` object): + +| Property | Description | +| --------------- | ------------------------------------------------------------------------ | +| `rise` | The time at which the sun will reach the altitude when it is rising | +| `set` | The time at which the sun will reach the altitude when it is setting | ### Sun position diff --git a/suncalc.js b/suncalc.js index c9ca56d2..d60df8ec 100644 --- a/suncalc.js +++ b/suncalc.js @@ -180,6 +180,30 @@ SunCalc.getTimes = function (date, lat, lng, height) { return result; }; +SunCalc.getTimesAtAltitude = function (date, altitude, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + + 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), + + Jset = getSetJ(altitude * rad, 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..66274a99 100644 --- a/test.js +++ b/test.js @@ -61,6 +61,13 @@ t.test('getTimes adjusts sun phases when additionally given the observer height' t.end(); }); +t.test('getTimesAtAltitude returns the correct time for the given date and location', function (t) { + var times = SunCalc.getTimesAtAltitude(date, -6, lat, lng); + + t.equal(new Date(testTimes.dawn).toUTCString(), times.rise.toUTCString()); + t.end(); +}); + t.test('getMoonPosition returns moon position data given time and location', function (t) { var moonPos = SunCalc.getMoonPosition(date, lat, lng); From 780b44620feed15f7ebbd7bf36ebf2e41b6c9905 Mon Sep 17 00:00:00 2001 From: Matthias Kunnen Date: Fri, 7 Feb 2020 23:07:12 +0000 Subject: [PATCH 2/6] Account for atmospheric refraction in getTimesAtAltitude --- suncalc.js | 2 +- test.js | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/suncalc.js b/suncalc.js index d60df8ec..af62ecda 100644 --- a/suncalc.js +++ b/suncalc.js @@ -195,7 +195,7 @@ SunCalc.getTimesAtAltitude = function (date, altitude, lat, lng) { Jnoon = solarTransitJ(ds, M, L), - Jset = getSetJ(altitude * rad, lw, phi, dec, n, M, L), + Jset = getSetJ((altitude - 0.833) * rad, lw, phi, dec, n, M, L), Jrise = Jnoon - (Jset - Jnoon); return { diff --git a/test.js b/test.js index 66274a99..885e28a2 100644 --- a/test.js +++ b/test.js @@ -62,9 +62,10 @@ t.test('getTimes adjusts sun phases when additionally given the observer height' }); t.test('getTimesAtAltitude returns the correct time for the given date and location', function (t) { - var times = SunCalc.getTimesAtAltitude(date, -6, lat, lng); + var times = SunCalc.getTimesAtAltitude(date, 0, lat, lng); - t.equal(new Date(testTimes.dawn).toUTCString(), times.rise.toUTCString()); + t.equal(new Date(times.rise).toString(), new Date(testTimes.sunrise).toString()); + t.equal(times.set.toString(), new Date(testTimes.sunset).toString()); t.end(); }); From f98b50dbf62b7fa5da5a795ffef472b2c272ee0f Mon Sep 17 00:00:00 2001 From: Matthias Kunnen Date: Fri, 7 Feb 2020 21:29:36 +0000 Subject: [PATCH 3/6] Rename getTimesAtAltitude -> getRiseAndSetAtSolarAngle --- README.md | 8 ++++---- suncalc.js | 4 ++-- test.js | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 3406efe0..a10ace4f 100644 --- a/README.md +++ b/README.md @@ -80,16 +80,16 @@ 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.getTimesAtAltitude(/*Date*/ timeAndDate, /*Number*/ angleInDegrees, /*Number*/ latitude, /*Number*/ longitude) +SunCalc.getRiseAndSetAtSolarAngle(/*Date*/ timeAndDate, /*Number*/ angle, /*Number*/ latitude, /*Number*/ longitude) ``` -Returns an object containing the times at which the sun will reach the given altitude at the given +Returns an object containing the times at which the sun will reach the given angle at the given location. The object contains the following properties (each is a `Date` object): | Property | Description | | --------------- | ------------------------------------------------------------------------ | -| `rise` | The time at which the sun will reach the altitude when it is rising | -| `set` | The time at which the sun will reach the altitude when it is setting | +| `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 af62ecda..538c9537 100644 --- a/suncalc.js +++ b/suncalc.js @@ -180,7 +180,7 @@ SunCalc.getTimes = function (date, lat, lng, height) { return result; }; -SunCalc.getTimesAtAltitude = function (date, altitude, lat, lng) { +SunCalc.getRiseAndSetAtSolarAngle = function (date, angle, lat, lng) { var lw = rad * -lng, phi = rad * lat, @@ -195,7 +195,7 @@ SunCalc.getTimesAtAltitude = function (date, altitude, lat, lng) { Jnoon = solarTransitJ(ds, M, L), - Jset = getSetJ((altitude - 0.833) * rad, lw, phi, dec, n, M, L), + Jset = getSetJ((angle - 0.833) * rad, lw, phi, dec, n, M, L), Jrise = Jnoon - (Jset - Jnoon); return { diff --git a/test.js b/test.js index 885e28a2..e46c20df 100644 --- a/test.js +++ b/test.js @@ -61,8 +61,8 @@ t.test('getTimes adjusts sun phases when additionally given the observer height' t.end(); }); -t.test('getTimesAtAltitude returns the correct time for the given date and location', function (t) { - var times = SunCalc.getTimesAtAltitude(date, 0, lat, lng); +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()); From f400527fe70861731da7e17ed34a6c8249133609 Mon Sep 17 00:00:00 2001 From: Matthias Kunnen Date: Fri, 7 Feb 2020 21:38:14 +0000 Subject: [PATCH 4/6] Add elevation parameter to getRiseAndSetAtAngle --- README.md | 4 ++-- suncalc.js | 9 +++++++-- test.js | 9 +++++++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a10ace4f..9a580383 100644 --- a/README.md +++ b/README.md @@ -80,11 +80,11 @@ 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) +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. The object contains the following properties (each is a `Date` object): +location and elevation. The object contains the following properties (each is a `Date` object): | Property | Description | | --------------- | ------------------------------------------------------------------------ | diff --git a/suncalc.js b/suncalc.js index 538c9537..407a8c82 100644 --- a/suncalc.js +++ b/suncalc.js @@ -180,11 +180,15 @@ SunCalc.getTimes = function (date, lat, lng, height) { return result; }; -SunCalc.getRiseAndSetAtSolarAngle = function (date, angle, lat, lng) { +SunCalc.getRiseAndSetAtSolarAngle = function (date, angle, lat, lng, elevation) { + + elevation = elevation || 0; var lw = rad * -lng, phi = rad * lat, + dh = observerAngle(elevation), + d = toDays(date), n = julianCycle(d, lw), ds = approxTransit(0, lw, n), @@ -194,8 +198,9 @@ SunCalc.getRiseAndSetAtSolarAngle = function (date, angle, lat, lng) { dec = declination(L, 0), Jnoon = solarTransitJ(ds, M, L), + h0 = (angle - 0.833 + dh) * rad, - Jset = getSetJ((angle - 0.833) * rad, lw, phi, dec, n, M, L), + Jset = getSetJ(h0, lw, phi, dec, n, M, L), Jrise = Jnoon - (Jset - Jnoon); return { diff --git a/test.js b/test.js index e46c20df..e9bc44de 100644 --- a/test.js +++ b/test.js @@ -69,6 +69,15 @@ t.test('getRiseAndSetAtSolarAngle returns the correct time for the given date an 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); From bd73c8e0a668861a09cc30c39ee55a938d90d1b3 Mon Sep 17 00:00:00 2001 From: Matthias Kunnen Date: Sat, 8 Feb 2020 03:30:37 +0000 Subject: [PATCH 5/6] Add jsdoc to getRiseAndSetAtSolarAngle --- suncalc.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/suncalc.js b/suncalc.js index 407a8c82..3b37df68 100644 --- a/suncalc.js +++ b/suncalc.js @@ -180,6 +180,16 @@ 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; From b7a464608af5bb4cbb5de70da127bc6d21122eb0 Mon Sep 17 00:00:00 2001 From: Matthias Kunnen Date: Sat, 8 Feb 2020 04:04:22 +0000 Subject: [PATCH 6/6] Use astroRefraction method in getRiseAndSetAtSolarAngle --- suncalc.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/suncalc.js b/suncalc.js index 3b37df68..868664f0 100644 --- a/suncalc.js +++ b/suncalc.js @@ -193,6 +193,7 @@ SunCalc.getTimes = function (date, lat, lng, height) { SunCalc.getRiseAndSetAtSolarAngle = function (date, angle, lat, lng, elevation) { elevation = elevation || 0; + angle = angle - astroRefraction(angle) * 100; var lw = rad * -lng, phi = rad * lat, @@ -208,7 +209,7 @@ SunCalc.getRiseAndSetAtSolarAngle = function (date, angle, lat, lng, elevation) dec = declination(L, 0), Jnoon = solarTransitJ(ds, M, L), - h0 = (angle - 0.833 + dh) * rad, + h0 = (angle + dh) * rad, Jset = getSetJ(h0, lw, phi, dec, n, M, L), Jrise = Jnoon - (Jset - Jnoon);