not really known
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

413 lines
21 KiB

define(function() {
/*
Moon phase data model and various utility methods.
Accessible properties:
-> functions
update_moon_calculations()
moon_phase_name()
-> Julian Date
julian_date
-> Age
days_old
hours_old
minutes_old
-> Lunation
phase_of_moon
lunation
-> Visibility
percent_of_full_moon
-> Selenography
selenographic_deg
west_or_east
rise_or_set
-> Next new-moon
days_until_new_moon
next_new_moon_date
-> Next full-moon
days_until_full_moon
next_full_moon_date
-> Next lunar-eclipse
days_until_lunar_eclipse
next_lunar_eclipse_date
-> Next solar-eclipse
days_until_solar_eclipse
next_solar_eclipse_date
*/
'use strict';
var self = {};
var new_moon_array, full_moon_array, first_quarter_array, last_quarter_array;
var currOffset = (new Date()).getTimezoneOffset() * 60;
/*
Init hard coded, tuples for New, First Quarter, Full Last
Quarter Moon UTC data.
T2018 to T2028 data from
http://sunearth.gsfc.nasa.gov/eclipse/phase/phasecat.html (now
only found on web.archive.org) algorithms used in predicting
the phases of the Moon and eclipses are based on Jean Meeus'
Astronomical Algorithms (Willmann-Bell, Inc.,T1998). All
calculations are by Fred Espenak, and he assumes full
responsibility for their accuracy. Permission is freely
granted to reproduce this data when accompanied by an
acknowledgment.
Data is all UTC and in YYYY-MM-DD HH:MM format, with New and
Full Moon arrays with an extra end character for eclipse types
T=Total (Solar), A=Annular (Solar), H=Hybrid (Solar
Annular/Total), P=Partial (Solar), t=Total (Lunar Umbral),
p=Partial (Lunar Umbral), n=Penumbral (Lunar), _=none.
*/
new_moon_array = ["2018-01-17T02:17Z_", "2018-02-15T21:05ZP", "2018-03-17T13:12Z_", "2018-04-16T01:57Z_", "2018-05-15T11:48Z_", "2018-06-13T19:43Z_", "2018-07-13T02:48ZP", "2018-08-11T09:58ZP", "2018-09-09T18:01Z_", "2018-10-09T03:47Z_", "2018-11-07T16:02Z_", "2018-12-07T07:20Z_", "2019-01-06T01:28ZP", "2019-02-04T21:04Z_", "2019-03-06T16:04Z_", "2019-04-05T08:50Z_", "2019-05-04T22:45Z_", "2019-06-03T10:02Z_", "2019-07-02T19:16ZT", "2019-08-01T03:12Z_", "2019-08-30T10:37Z_", "2019-09-28T18:26Z_", "2019-10-28T03:38Z_", "2019-11-26T15:06Z_", "2019-12-26T05:13ZA", "2020-01-24T21:42Z_", "2020-02-23T15:32Z_", "2020-03-24T09:28Z_", "2020-04-23T02:26Z_", "2020-05-22T17:39Z_", "2020-06-21T06:41ZA", "2020-07-20T17:33Z_", "2020-08-19T02:41Z_", "2020-09-17T11:00Z_", "2020-10-16T19:31Z_", "2020-11-15T05:07Z_", "2020-12-14T16:17ZT", "2021-01-13T05:00Z_", "2021-02-11T19:06Z_", "2021-03-13T10:21Z_", "2021-04-12T02:31Z_", "2021-05-11T19:00Z_", "2021-06-10T10:53ZA", "2021-07-10T01:17Z_", "2021-08-08T13:50Z_", "2021-09-07T00:52Z_", "2021-10-06T11:05Z_", "2021-11-04T21:15Z_", "2021-12-04T07:43ZT", "2022-01-02T18:33Z_", "2022-02-01T05:46Z_", "2022-03-02T17:35Z_", "2022-04-01T06:24Z_", "2022-04-30T20:28ZP", "2022-05-30T11:30Z_", "2022-06-29T02:52Z_", "2022-07-28T17:55Z_", "2022-08-27T08:17Z_", "2022-09-25T21:54Z_", "2022-10-25T10:49ZP", "2022-11-23T22:57Z_", "2022-12-23T10:17Z_", "2023-01-21T20:53Z_", "2023-02-20T07:06Z_", "2023-03-21T17:23Z_", "2023-04-20T04:12ZH", "2023-05-19T15:53Z_", "2023-06-18T04:37Z_", "2023-07-17T18:32Z_", "2023-08-16T09:38Z_", "2023-09-15T01:40Z_", "2023-10-14T17:55ZA", "2023-11-13T09:27Z_", "2023-12-12T23:32Z_", "2024-01-11T11:57Z_", "2024-02-09T22:59Z_", "2024-03-10T09:00Z_", "2024-04-08T18:21ZT", "2024-05-08T03:22Z_", "2024-06-06T12:38Z_", "2024-07-05T22:57Z_", "2024-08-04T11:13Z_", "2024-09-03T01:55Z_", "2024-10-02T18:49ZA", "2024-11-01T12:47Z_", "2024-12-01T06:21Z_", "2024-12-30T22:27Z_"];
full_moon_array = ["2018-01-02T02:24Z_", "2018-01-31T13:27Zt", "2018-03-02T00:51Z_", "2018-03-31T12:37Z_", "2018-04-30T00:58Z_", "2018-05-29T14:20Z_", "2018-06-28T04:53Z_", "2018-07-27T20:20Zt", "2018-08-26T11:56Z_", "2018-09-25T02:53Z_", "2018-10-24T16:45Z_", "2018-11-23T05:39Z_", "2018-12-22T17:49Z_", "2019-01-21T05:16Zt", "2019-02-19T15:53Z_", "2019-03-21T01:43Z_", "2019-04-19T11:12Z_", "2019-05-18T21:11Z_", "2019-06-17T08:31Z_", "2019-07-16T21:38Zp", "2019-08-15T12:29Z_", "2019-09-14T04:33Z_", "2019-10-13T21:08Z_", "2019-11-12T13:34Z_", "2019-12-12T05:12Z_", "2020-01-10T19:21Zn", "2020-02-09T07:33Z_", "2020-03-09T17:48Z_", "2020-04-08T02:35Z_", "2020-05-07T10:45Z_", "2020-06-05T19:12Zn", "2020-07-05T04:44Zn", "2020-08-03T15:59Z_", "2020-09-02T05:22Z_", "2020-10-01T21:05Z_", "2020-10-31T14:49Z_", "2020-11-30T09:30Zn", "2020-12-30T03:28Z_", "2021-01-28T19:16Z_", "2021-02-27T08:17Z_", "2021-03-28T18:48Z_", "2021-04-27T03:31Z_", "2021-05-26T11:14Zt", "2021-06-24T18:40Z_", "2021-07-24T02:37Z_", "2021-08-22T12:02Z_", "2021-09-20T23:55Z_", "2021-10-20T14:57Z_", "2021-11-19T08:58Zp", "2021-12-19T04:36Z_", "2022-01-17T23:49Z_", "2022-02-16T16:57Z_", "2022-03-18T07:17Z_", "2022-04-16T18:55Z_", "2022-05-16T04:14Zt", "2022-06-14T11:52Z_", "2022-07-13T18:37Z_", "2022-08-12T01:36Z_", "2022-09-10T09:59Z_", "2022-10-09T20:55Z_", "2022-11-08T11:02Zt", "2022-12-08T04:08Z_", "2023-01-06T23:08Z_", "2023-02-05T18:29Z_", "2023-03-07T12:40Z_", "2023-04-06T04:35Z_", "2023-05-05T17:34Zn", "2023-06-04T03:42Z_", "2023-07-03T11:39Z_", "2023-08-01T18:31Z_", "2023-08-31T01:35Z_", "2023-09-29T09:57Z_", "2023-10-28T20:24Zp", "2023-11-27T09:16Z_", "2023-12-27T00:33Z_", "2024-01-25T17:54Z_", "2024-02-24T12:30Z_", "2024-03-25T07:00Zn", "2024-04-23T23:49Z_", "2024-05-23T13:53Z_", "2024-06-22T01:08Z_", "2024-07-21T10:17Z_", "2024-08-19T18:26Z_", "2024-09-18T02:34Zp", "2024-10-17T11:26Z_", "2024-11-15T21:29Z_", "2024-12-15T09:02Z_"];
first_quarter_array = ["2018-01-24T22:20Z", "2018-02-23T08:09Z", "2018-03-24T15:35Z", "2018-04-22T21:46Z", "2018-05-22T03:49Z", "2018-06-20T10:51Z", "2018-07-19T19:52Z", "2018-08-18T07:49Z", "2018-09-16T23:15Z", "2018-10-16T18:02Z", "2018-11-15T14:54Z", "2018-12-15T11:49Z", "2019-01-14T06:45Z", "2019-02-12T22:26Z", "2019-03-14T10:27Z", "2019-04-12T19:06Z", "2019-05-12T01:12Z", "2019-06-10T05:59Z", "2019-07-09T10:55Z", "2019-08-07T17:31Z", "2019-09-06T03:10Z", "2019-10-05T16:47Z", "2019-11-04T10:23Z", "2019-12-04T06:58Z", "2020-01-03T04:45Z", "2020-02-02T01:42Z", "2020-03-02T19:57Z", "2020-04-01T10:21Z", "2020-04-30T20:38Z", "2020-05-30T03:30Z", "2020-06-28T08:16Z", "2020-07-27T12:32Z", "2020-08-25T17:58Z", "2020-09-24T01:55Z", "2020-10-23T13:23Z", "2020-11-22T04:45Z", "2020-12-21T23:41Z", "2021-01-20T21:02Z", "2021-02-19T18:47Z", "2021-03-21T14:40Z", "2021-04-20T06:59Z", "2021-05-19T19:13Z", "2021-06-18T03:54Z", "2021-07-17T10:11Z", "2021-08-15T15:20Z", "2021-09-13T20:39Z", "2021-10-13T03:25Z", "2021-11-11T12:46Z", "2021-12-11T01:36Z", "2022-01-09T18:11Z", "2022-02-08T13:50Z", "2022-03-10T10:45Z", "2022-04-09T06:47Z", "2022-05-09T00:21Z", "2022-06-07T14:48Z", "2022-07-07T02:14Z", "2022-08-05T11:06Z", "2022-09-03T18:08Z", "2022-10-03T00:14Z", "2022-11-01T06:37Z", "2022-11-30T14:36Z", "2022-12-30T01:21Z", "2023-01-28T15:19Z", "2023-02-27T08:06Z", "2023-03-29T02:32Z", "2023-04-27T21:20Z", "2023-05-27T15:22Z", "2023-06-26T07:50Z", "2023-07-25T22:07Z", "2023-08-24T09:57Z", "2023-09-22T19:32Z", "2023-10-22T03:29Z", "2023-11-20T10:50Z", "2023-12-19T18:39Z", "2024-01-18T03:53Z", "2024-02-16T15:01Z", "2024-03-17T04:11Z", "2024-04-15T19:13Z", "2024-05-15T11:48Z", "2024-06-14T05:18Z", "2024-07-13T22:49Z", "2024-08-12T15:19Z", "2024-09-11T06:06Z", "2024-10-10T18:55Z", "2024-11-09T05:56Z", "2024-12-08T15:27Z"];
last_quarter_array = ["2018-01-08T22:25Z", "2018-02-07T15:54Z", "2018-03-09T11:20Z", "2018-04-08T07:18Z", "2018-05-08T02:09Z", "2018-06-06T18:32Z", "2018-07-06T07:51Z", "2018-08-04T18:18Z", "2018-09-03T02:37Z", "2018-10-02T09:45Z", "2018-10-31T16:40Z", "2018-11-30T00:19Z", "2018-12-29T09:34Z", "2019-01-27T21:10Z", "2019-02-26T11:28Z", "2019-03-28T04:10Z", "2019-04-26T22:18Z", "2019-05-26T16:33Z", "2019-06-25T09:46Z", "2019-07-25T01:18Z", "2019-08-23T14:56Z", "2019-09-22T02:41Z", "2019-10-21T12:39Z", "2019-11-19T21:11Z", "2019-12-19T04:57Z", "2020-01-17T12:58Z", "2020-02-15T22:17Z", "2020-03-16T09:34Z", "2020-04-14T22:56Z", "2020-05-14T14:03Z", "2020-06-13T06:24Z", "2020-07-12T23:29Z", "2020-08-11T16:45Z", "2020-09-10T09:26Z", "2020-10-10T00:39Z", "2020-11-08T13:46Z", "2020-12-08T00:37Z", "2021-01-06T09:37Z", "2021-02-04T17:37Z", "2021-03-06T01:30Z", "2021-04-04T10:02Z", "2021-05-03T19:50Z", "2021-06-02T07:24Z", "2021-07-01T21:11Z", "2021-07-31T13:16Z", "2021-08-30T07:13Z", "2021-09-29T01:57Z", "2021-10-28T20:05Z", "2021-11-27T12:28Z", "2021-12-27T02:24Z", "2022-01-25T13:41Z", "2022-02-23T22:32Z", "2022-03-25T05:37Z", "2022-04-23T11:56Z", "2022-05-22T18:43Z", "2022-06-21T03:11Z", "2022-07-20T14:18Z", "2022-08-19T04:36Z", "2022-09-17T21:52Z", "2022-10-17T17:15Z", "2022-11-16T13:27Z", "2022-12-16T08:56Z", "2023-01-15T02:10Z", "2023-02-13T16:01Z", "2023-03-15T02:08Z", "2023-04-13T09:11Z", "2023-05-12T14:28Z", "2023-06-10T19:31Z", "2023-07-10T01:48Z", "2023-08-08T10:28Z", "2023-09-06T22:21Z", "2023-10-06T13:48Z", "2023-11-05T08:37Z", "2023-12-05T05:49Z", "2024-01-04T03:30Z", "2024-02-02T23:18Z", "2024-03-03T15:24Z", "2024-04-02T03:15Z", "2024-05-01T11:27Z", "2024-05-30T17:13Z", "2024-06-28T21:53Z", "2024-07-28T02:51Z", "2024-08-26T09:26Z", "2024-09-24T18:50Z", "2024-10-24T08:03Z", "2024-11-23T01:28Z", "2024-12-22T22:18Z"];
self.update_moon_calculations = function() {
/*
Generate all Moon data ready for display.
*/
var currDate = (new Date().getTime()) / 1000;
var SECONDS_PER_DAY = 86400;
var last_new_moon_sec = last_new_moon_sec_at_time(currDate);
var next_new_moon_sec = next_new_moon_sec_at_time(currDate);
var last_full_moon_sec = last_full_moon_sec_at_time(currDate);
var next_full_moon_sec = next_full_moon_sec_at_time(currDate);
var last_quarter_moon_sec = last_quarter_moon_sec_at_time(currDate);
var next_quarter_moon_sec = next_quarter_moon_sec_at_time(currDate);
/* Calculate phase percent of Moon based on nearest two data values */
if (next_full_moon_sec <= next_new_moon_sec) {
if (next_quarter_moon_sec <= next_full_moon_sec) {
self.phase_of_moon = (last_new_moon_sec / (last_new_moon_sec + next_quarter_moon_sec)) * 0.25;
} else {
self.phase_of_moon = (last_quarter_moon_sec / (last_quarter_moon_sec + next_full_moon_sec)) * 0.25 + 0.25;
}
} else {
if (next_quarter_moon_sec <= next_new_moon_sec) {
self.phase_of_moon = (last_full_moon_sec / (last_full_moon_sec + next_quarter_moon_sec)) * 0.25 + 0.5;
} else {
self.phase_of_moon = (last_quarter_moon_sec / (last_quarter_moon_sec + next_new_moon_sec)) * 0.25 + 0.75;
}
}
/* Generate interesting human readable values */
self.percent_of_full_moon = (Math.cos(((self.phase_of_moon + 0.5) / 0.5 * Math.PI)) + 1) * 0.5;
self.julian_date = 2452135 + ((currDate - 997700400) / SECONDS_PER_DAY);
self.lunation = lunation_at_time(currDate);
var day_with_fraction = last_new_moon_sec / SECONDS_PER_DAY;
self.days_old = Math.floor(day_with_fraction);
self.hours_old = Math.floor((day_with_fraction - self.days_old) * 24);
self.minutes_old = Math.floor((((day_with_fraction - self.days_old) * 24) - self.hours_old) * 60);
self.days_until_new_moon = next_new_moon_sec / SECONDS_PER_DAY;
self.next_new_moon_date = currDate + next_new_moon_sec - correct_for_tz_and_dst(currDate + next_new_moon_sec);
self.days_until_full_moon = next_full_moon_sec / SECONDS_PER_DAY;
self.next_full_moon_date = currDate + next_full_moon_sec - correct_for_tz_and_dst(currDate + next_full_moon_sec);
/* Eclipse information */
self.next_lunar_eclipse_sec = next_lunar_eclipse_sec_at_time(currDate);
var next_solar_eclipse_sec = next_solar_eclipse_sec_at_time(currDate);
self.last_lunar_eclipse_sec = last_lunar_eclipse_sec_at_time(currDate);
self.days_until_lunar_eclipse = self.next_lunar_eclipse_sec / SECONDS_PER_DAY;
self.next_lunar_eclipse_date = currDate + self.next_lunar_eclipse_sec - correct_for_tz_and_dst(currDate + self.next_lunar_eclipse_sec);
self.days_until_solar_eclipse = next_solar_eclipse_sec / SECONDS_PER_DAY;
self.next_solar_eclipse_date = currDate + next_solar_eclipse_sec - correct_for_tz_and_dst(currDate + next_solar_eclipse_sec);
/* Selenographic terminator longitude */
var selenographic_tmp = 270 + (self.phase_of_moon * 360);
if (selenographic_tmp >= 360) {
selenographic_tmp -= 360;
}
if (selenographic_tmp >= 270) {
selenographic_tmp -= 360;
} else if (selenographic_tmp >= 180) {
selenographic_tmp -= 180;
} else if (selenographic_tmp >= 90) {
selenographic_tmp -= 180;
}
selenographic_tmp = -selenographic_tmp;
if (selenographic_tmp < 0) {
self.west_or_east = "west";
} else {
self.west_or_east = "east";
}
self.selenographic_deg = Math.abs(selenographic_tmp);
if (self.phase_of_moon >= 0.5) {
self.rise_or_set = "Sunset";
} else {
self.rise_or_set = "Sunrise";
}
};
function correct_for_tz_and_dst(date_sec_of_event) {
/*
Time-zone and/or daylight-saving correction (internal data is UTC).
*/
return currOffset;
// if (time.daylight === 0 || time.localtime(date_sec_of_event)[8] === 0) {
// /* Time-zone correction */
// return time.timezone;
// } else {
// /* Time-zone & daylight saving correction */
// return time.altzone;
// }
}
self.moon_phase_name = function() {
/*
Return the moon image name for a given phase value.
*/
if (self.phase_of_moon >= 0 && self.phase_of_moon < 0.025) {
return "phase-0";
// return "New Moon";
} else if (self.phase_of_moon >= 0.025 && self.phase_of_moon < 0.225) {
return "phase-1";
// return "Waxing Crescent";
} else if (self.phase_of_moon >= 0.225 && self.phase_of_moon < 0.275) {
return "phase-2";
// return "First Quarter";
} else if (self.phase_of_moon >= 0.275 && self.phase_of_moon < 0.475) {
return "phase-3";
// return "Waxing Gibbous";
} else if (self.phase_of_moon >= 0.475 && self.phase_of_moon < 0.525) {
return "phase-4";
// return "Full Moon";
} else if (self.phase_of_moon >= 0.525 && self.phase_of_moon < 0.735) {
return "phase-5";
// return "Waning Gibbous";
} else if (self.phase_of_moon >= 0.735 && self.phase_of_moon < 0.775) {
return "phase-6";
// return "Last Quarter";
} else if (self.phase_of_moon >= 0.775 && self.phase_of_moon < 0.975) {
return "phase-7";
// return "Waning Crescent";
} else {
return "phase-0";
// return "New Moon";
}
};
function next_full_moon_sec_at_time(now) {
/*
Return seconds to the next Full Moon.
*/
var next;
for (var i = 0; i < full_moon_array.length; i++) {
var date_string = full_moon_array[i];
next = Date.parse(date_string.slice(0, -1)) / 1000 + currOffset;
if (next >= now) {
break;
}
}
return next - now;
}
function next_new_moon_sec_at_time(now) {
/*
Return seconds to the next New Moon.
*/
var next;
for (var i = 0; i < new_moon_array.length; i++) {
var date_string = new_moon_array[i];
next = Date.parse(date_string.slice(0, -1)) / 1000 + currOffset;
if (next >= now) {
break;
}
}
return next - now;
}
function next_quarter_moon_sec_at_time(now) {
/*
Return seconds to the next Quater Moon phase (could be First or Last).
*/
var next1, next2;
for (var i = 0; i < first_quarter_array.length; i++) {
var date_string = first_quarter_array[i];
next1 = Date.parse(date_string) / 1000 + currOffset;
if (next1 >= now) {
break;
}
}
for (var i = 0; i < last_quarter_array.length; i++) {
var date_string = last_quarter_array[i];
next2 = Date.parse(date_string) / 1000 + currOffset;
if (next2 >= now) {
break;
}
}
var next = Math.min(next1, next2);
return next - now;
}
function last_full_moon_sec_at_time(now) {
/*
Return (positive) seconds since the last Full Moon.
*/
var last;
for (var i = 0; i < full_moon_array.length; i++) {
var date_string = full_moon_array[i];
var then = Date.parse(date_string.slice(0, -1)) / 1000 + currOffset;
if (then >= now) {
break;
}
last = then;
}
return now - last;
}
function last_new_moon_sec_at_time(now) {
/*
Return (positive) seconds since the last New Moon.
*/
var last;
for (var i = 0; i < new_moon_array.length; i++) {
var date_string = new_moon_array[i];
var then = Date.parse(date_string.slice(0, -1)) / 1000 + currOffset;
if (then >= now) {
break;
}
last = then;
}
return now - last;
}
function last_quarter_moon_sec_at_time(now) {
/*
Return (positive) seconds to the last Quater Moon phase (could be First or Last).
*/
var last1, last2;
for (var i = 0; i < first_quarter_array.length; i++) {
var date_string = first_quarter_array[i];
var then = Date.parse(date_string) / 1000 + currOffset;
if (then >= now) {
break;
}
last1 = then;
}
for (var i = 0; i < last_quarter_array.length; i++) {
var date_string = last_quarter_array[i];
var then = Date.parse(date_string) / 1000 + currOffset;
if (then >= now) {
break;
}
last2 = then;
}
var last = Math.max(last1, last2);
return now - last;
}
function lunation_at_time(now) {
/*
Return lunation number, 0 started on Dec 18, 1922, current data set starts as 2008
*/
self.lunation = 1051;
for (var i = 0; i < new_moon_array.length; i++) {
var date_string = new_moon_array[i];
var next = Date.parse(date_string.slice(0, -1)) / 1000 + currOffset;
if (next >= now) {
break;
}
self.lunation += 1;
}
return self.lunation;
}
function next_lunar_eclipse_sec_at_time(now) {
/*
Return (positive) seconds to the next Lunar eclipe or -1.
*/
for (var i = 0; i < full_moon_array.length; i++) {
var date_string = full_moon_array[i];
if (date_string.slice(-1) !== "_") {
var next = Date.parse(date_string.slice(0, -1)) / 1000 + currOffset;
if (next >= now) {
console.log(new Date(1000*next))
return next - now;
}
}
}
return -1;
}
function last_lunar_eclipse_sec_at_time(now) {
/*
Return (positive) seconds to the last Lunar eclipe or -1.
*/
var last = -1;
for (var i = 0; i < full_moon_array.length; i++) {
var date_string = full_moon_array[i];
if (date_string.slice(-1) !== "_") {
var then = Date.parse(date_string.slice(0, -1)) / 1000 + currOffset;
if (then >= now) {
break;
}
last = then;
}
}
if (last === -1) {
return -1;
} else {
return now - last;
}
}
function next_solar_eclipse_sec_at_time(now) {
/*
Return (positive) seconds to the next Solar eclipe or -1.
*/
for (var i = 0; i < new_moon_array.length; i++) {
var date_string = new_moon_array[i];
if (date_string.slice(-1) !== "_") {
var next = Date.parse(date_string.slice(0, -1)) / 1000 + currOffset;
if (next >= now) {
return next - now;
}
}
}
return -1;
}
return self;
});