Astronomy.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. 'use strict';
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.incrementGregorianDays = incrementGregorianDays;
  6. exports.getUTCDateForTwinBirthdaysOnYear = getUTCDateForTwinBirthdaysOnYear;
  7. exports.getUTCDateForSunsetOnDate = getUTCDateForSunsetOnDate;
  8. exports.getUTCDateForNextNewMoonFromDate = getUTCDateForNextNewMoonFromDate;
  9. exports.getUTCDateForNawRuzOnYear = getUTCDateForNawRuzOnYear;
  10. var _blueyonder = require('./extern/blueyonder');
  11. var _blueyonder2 = _interopRequireDefault(_blueyonder);
  12. var _LocationMap = require('./LocationMap');
  13. var _LocationMap2 = _interopRequireDefault(_LocationMap);
  14. var _stellafane = require('./extern/stellafane');
  15. var _stellafane2 = _interopRequireDefault(_stellafane);
  16. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  17. var MillisPerDay = 1000 * 60 * 60 * 24;
  18. /**
  19. * Increment a gregorian date by the number of days specified.
  20. */
  21. function incrementGregorianDays(gregorianDate, days) {
  22. return new Date(gregorianDate.getTime() + days * MillisPerDay);
  23. }
  24. /**
  25. * Finds the time (sunset in Tehran) that twin birthdays start. Twin birthdays
  26. * occur at Sunset in tehran 8 new moons after Naw Ruz.
  27. */
  28. function getUTCDateForTwinBirthdaysOnYear(gregorianYear) {
  29. var gregorianNawRuz = getUTCDateForNawRuzOnYear(gregorianYear);
  30. var UTCNewMoons = getUTCDateForSunsetOnDate(gregorianNawRuz, _LocationMap2.default.Tehran);
  31. for (var i = 0; i < 8; ++i) {
  32. UTCNewMoons = getUTCDateForNextNewMoonFromDate(UTCNewMoons);
  33. }
  34. var UTCSunset = getUTCDateForSunsetOnDate(UTCNewMoons, _LocationMap2.default.Tehran);
  35. if (UTCNewMoons < UTCSunset) {
  36. UTCNewMoons = incrementGregorianDays(UTCNewMoons, 1);
  37. } else {
  38. UTCNewMoons = incrementGregorianDays(UTCNewMoons, 2);
  39. }
  40. UTCNewMoons = getUTCDateForSunsetOnDate(UTCNewMoons, _LocationMap2.default.Tehran);
  41. return new Date(Date.UTC(UTCNewMoons.getUTCFullYear(), UTCNewMoons.getUTCMonth(), UTCNewMoons.getUTCDate()));
  42. }
  43. function getUTCDateForSunsetOnDate(gregorianDate, place) {
  44. var sunsetTime = _blueyonder2.default.SunRiseSet(gregorianDate.getUTCFullYear(), gregorianDate.getUTCMonth() + 1, gregorianDate.getUTCDate(), place.latitude, place.longitude)[1];
  45. var sunsetHours = Math.floor(sunsetTime);
  46. var sunsetMinutes = Math.floor((sunsetTime - sunsetHours) * 60);
  47. var sunsetSeconds = Math.floor(((sunsetTime - sunsetHours) * 60 - sunsetMinutes) * 60);
  48. return new Date(Date.UTC(gregorianDate.getUTCFullYear(), gregorianDate.getUTCMonth(), gregorianDate.getUTCDate(), sunsetHours, sunsetMinutes, sunsetSeconds));
  49. }
  50. /**
  51. * Takes a date and returns the date of the next new moon. This function is
  52. * recursive. A client should call this function with two identical parameters.
  53. *
  54. * The detailed contract is this: find the first new moon during or after the
  55. * lunar cycle containing 'date' but occurring after the time 'min'.
  56. */
  57. function getUTCDateForNextNewMoonFromDate(UTCDate) {
  58. return recurse(UTCDate, UTCDate);
  59. }
  60. function recurse(UTCDate, minUTCDate) {
  61. var quarters = _blueyonder2.default.MoonQuarters(UTCDate.getUTCFullYear(), UTCDate.getUTCMonth() + 1, // Month 0-based to 1-based indexing
  62. UTCDate.getUTCDate(), 0);
  63. var newMoonDateComponents = _blueyonder2.default.jdtocd(quarters[0]);
  64. var UTCNewMoon = new Date(Date.UTC(newMoonDateComponents[0], // Year
  65. newMoonDateComponents[1] - 1, // Month: 1-based to 0-based indexing
  66. newMoonDateComponents[2], // Day
  67. newMoonDateComponents[4], // Hour
  68. newMoonDateComponents[5], // Minute
  69. newMoonDateComponents[6]));
  70. if (UTCNewMoon > minUTCDate) {
  71. return UTCNewMoon;
  72. }
  73. return recurse(incrementGregorianDays(minUTCDate, 30), minUTCDate);
  74. }
  75. /**
  76. * Gets the day of Naw Ruz in a given gregorian year. It returns the day at
  77. * 00:00:00 UTC.
  78. */
  79. function getUTCDateForNawRuzOnYear(gregorianYear) {
  80. // Step 0: Follow to the UHJ
  81. // In 2026, the equinox is less than a minute from sunset. The
  82. // algorithms from Meeus which we're using don't give accuraccy
  83. // better than one minute, and don't give us the right answer. The
  84. // UHJ has said that Naw Ruz this day is on the 21st.
  85. if (gregorianYear == 2026) {
  86. return new Date(Date.UTC(2026, 2, 21));
  87. }
  88. // Step 1: find UTC time of the equinox
  89. var UTCEquinox = _stellafane2.default.vernal_equinox(gregorianYear);
  90. // Step 2: Find Tehran's sunset on the day of the equinox
  91. var UTCSunset = getUTCDateForSunsetOnDate(UTCEquinox, _LocationMap2.default.Tehran);
  92. // Step 3: Find the final day.
  93. if (UTCEquinox < UTCSunset) {
  94. return new Date(Date.UTC(UTCEquinox.getUTCFullYear(), UTCEquinox.getUTCMonth(), UTCEquinox.getUTCDate()));
  95. }
  96. return new Date(Date.UTC(UTCEquinox.getUTCFullYear(), UTCEquinox.getUTCMonth(),
  97. // NOTE: Date class handles the case where the day spills to the
  98. // next month.
  99. UTCEquinox.getUTCDate() + 1));
  100. }