index.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. /**
  4. * Sunrise/sunset script. By Matt Kane. Adopted for NPM use by Alexey Udivankin.
  5. *
  6. * Based loosely and indirectly on Kevin Boone's SunTimes Java implementation
  7. * of the US Naval Observatory's algorithm.
  8. *
  9. * Copyright © 2012 Triggertrap Ltd. All rights reserved.
  10. *
  11. * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General
  12. * Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option)
  13. * any later version.
  14. *
  15. * This library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied
  16. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
  17. * details.
  18. * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to
  19. * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA,
  20. * or connect to: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
  21. */
  22. /**
  23. * Default zenith
  24. */
  25. const DEFAULT_ZENITH = 90.8333;
  26. /**
  27. * Degrees per hour
  28. */
  29. const DEGREES_PER_HOUR = 360 / 24;
  30. /**
  31. * Msec in hour
  32. */
  33. const MSEC_IN_HOUR = 60 * 60 * 1000;
  34. /**
  35. * Get day of year
  36. */
  37. function getDayOfYear(date) {
  38. return Math.ceil((date.getTime() - new Date(date.getFullYear(), 0, 1).getTime()) / 8.64e7);
  39. }
  40. /**
  41. * Get sin of value in deg
  42. */
  43. function sinDeg(deg) {
  44. return Math.sin(deg * 2.0 * Math.PI / 360.0);
  45. }
  46. /**
  47. * Get acos of value in deg
  48. */
  49. function acosDeg(x) {
  50. return Math.acos(x) * 360.0 / (2 * Math.PI);
  51. }
  52. /**
  53. * Get asin of value in deg
  54. */
  55. function asinDeg(x) {
  56. return Math.asin(x) * 360.0 / (2 * Math.PI);
  57. }
  58. /**
  59. * Get tan of value in deg
  60. */
  61. function tanDeg(deg) {
  62. return Math.tan(deg * 2.0 * Math.PI / 360.0);
  63. }
  64. /**
  65. * Get cos of value in deg
  66. */
  67. function cosDeg(deg) {
  68. return Math.cos(deg * 2.0 * Math.PI / 360.0);
  69. }
  70. /**
  71. * Get ramainder
  72. */
  73. function mod(a, b) {
  74. const result = a % b;
  75. return result < 0
  76. ? result + b
  77. : result;
  78. }
  79. /**
  80. * Calculate Date for either sunrise or sunset
  81. */
  82. function calculate(latitude, longitude, isSunrise, zenith, date) {
  83. const dayOfYear = getDayOfYear(date);
  84. const hoursFromMeridian = longitude / DEGREES_PER_HOUR;
  85. const approxTimeOfEventInDays = isSunrise
  86. ? dayOfYear + ((6 - hoursFromMeridian) / 24)
  87. : dayOfYear + ((18.0 - hoursFromMeridian) / 24);
  88. const sunMeanAnomaly = (0.9856 * approxTimeOfEventInDays) - 3.289;
  89. const sunTrueLongitude = mod(sunMeanAnomaly + (1.916 * sinDeg(sunMeanAnomaly)) + (0.020 * sinDeg(2 * sunMeanAnomaly)) + 282.634, 360);
  90. const ascension = 0.91764 * tanDeg(sunTrueLongitude);
  91. let rightAscension;
  92. rightAscension = 360 / (2 * Math.PI) * Math.atan(ascension);
  93. rightAscension = mod(rightAscension, 360);
  94. const lQuadrant = Math.floor(sunTrueLongitude / 90) * 90;
  95. const raQuadrant = Math.floor(rightAscension / 90) * 90;
  96. rightAscension = rightAscension + (lQuadrant - raQuadrant);
  97. rightAscension /= DEGREES_PER_HOUR;
  98. const sinDec = 0.39782 * sinDeg(sunTrueLongitude);
  99. const cosDec = cosDeg(asinDeg(sinDec));
  100. const cosLocalHourAngle = ((cosDeg(zenith)) - (sinDec * (sinDeg(latitude)))) / (cosDec * (cosDeg(latitude)));
  101. const localHourAngle = isSunrise
  102. ? 360 - acosDeg(cosLocalHourAngle)
  103. : acosDeg(cosLocalHourAngle);
  104. const localHour = localHourAngle / DEGREES_PER_HOUR;
  105. const localMeanTime = localHour + rightAscension - (0.06571 * approxTimeOfEventInDays) - 6.622;
  106. const time = mod(localMeanTime - (longitude / DEGREES_PER_HOUR), 24);
  107. const utcMidnight = Date.UTC(date.getFullYear(), date.getMonth(), date.getDate());
  108. // Created date will be set to local (system) time zone.
  109. return new Date(utcMidnight + (time * MSEC_IN_HOUR));
  110. }
  111. /**
  112. * Calculate Sunrise time for given longitude, latitude, zenith and date
  113. */
  114. function getSunrise(latitude, longitude, date = new Date()) {
  115. return calculate(latitude, longitude, true, DEFAULT_ZENITH, date);
  116. }
  117. /**
  118. * Calculate Sunset time for given longitude, latitude, zenith and date
  119. */
  120. function getSunset(latitude, longitude, date = new Date()) {
  121. return calculate(latitude, longitude, false, DEFAULT_ZENITH, date);
  122. }
  123. exports.getSunrise = getSunrise;
  124. exports.getSunset = getSunset;