Comparing version 0.2.0 to 0.2.1
213
lib/lune.js
@@ -12,4 +12,7 @@ /** | ||
(function() { | ||
"use strict"; | ||
var julian = require("./julian"); | ||
// Phases of the moon & precision | ||
var PRECISION = 0.05; | ||
@@ -22,111 +25,59 @@ var NEW = 0 / 4.0; | ||
/** | ||
* Gets the Julian value from a date object. | ||
* Source: http://javascript.about.com/library/bljulday.htm | ||
* @return {Number} Julian number representation of the date. | ||
*/ | ||
Date.prototype.getJulian = function() { | ||
return (this.valueOf() / 86400000) - (this.getTimezoneOffset() / 1440) + 2440587.5; | ||
}; | ||
// Astronomical Constants | ||
// JDN stands for Julian Day Number | ||
// Angles here are in degrees | ||
/** | ||
* Converts a Number in Julian date form to a Date object. | ||
* Source: http://blog.bahrenburgs.com/2011/01/javascript-julian-day-conversions.html | ||
*/ | ||
Number.prototype.Julian2Date = function(inUTC) { | ||
var X = parseFloat(this)+0.5; | ||
var Z = Math.floor(X); //Get day without time | ||
var F = X - Z; //Get time | ||
var Y = Math.floor((Z-1867216.25)/36524.25); | ||
var A = Z+1+Y-Math.floor(Y/4); | ||
var B = A+1524; | ||
var C = Math.floor((B-122.1)/365.25); | ||
var D = Math.floor(365.25*C); | ||
var G = Math.floor((B-D)/30.6001); | ||
//must get number less than or equal to 12) | ||
var month = (G<13.5) ? (G-1) : (G-13); | ||
//if Month is January or February, or the rest of year | ||
var year = (month<2.5) ? (C-4715) : (C-4716); | ||
month -= 1; //Handle JavaScript month format | ||
var UT = B-D-Math.floor(30.6001*G)+F; | ||
var day = Math.floor(UT); | ||
//Determine time | ||
UT -= Math.floor(UT); | ||
UT *= 24; | ||
var hour = Math.floor(UT); | ||
UT -= Math.floor(UT); | ||
UT *= 60; | ||
var minute = Math.floor(UT); | ||
UT -= Math.floor(UT); | ||
UT *= 60; | ||
var second = Math.round(UT); | ||
// 1980 January 0.0 in JDN | ||
// XXX: DateTime(1980).jdn yields 2444239.5 -- which one is right? | ||
var EPOCH = 2444238.5; | ||
if (inUTC) { | ||
return new Date(Date.UTC(year, month, day, hour, minute, second)); | ||
} else { | ||
return new Date(year, month, day, hour, minute, second); | ||
} | ||
}; | ||
// Ecliptic longitude of the Sun at epoch 1980.0 | ||
var ECLIPTIC_LONGITUDE_EPOCH = 278.833540; | ||
/** | ||
* Astronomical Constants | ||
* @type {Object} | ||
*/ | ||
const c = { | ||
// JDN stands for Julian Day Number | ||
// Angles here are in degrees | ||
// Ecliptic longitude of the Sun at perigee | ||
var ECLIPTIC_LONGITUDE_PERIGEE = 282.596403; | ||
// 1980 January 0.0 in JDN | ||
// XXX: DateTime(1980).jdn yields 2444239.5 -- which one is right? | ||
epoch: 2444238.5, | ||
// Eccentricity of Earth's orbit | ||
var ECCENTRICITY = 0.016718; | ||
// Ecliptic longitude of the Sun at epoch 1980.0 | ||
ecliptic_longitude_epoch: 278.833540, | ||
// Semi-major axis of Earth's orbit, in kilometers | ||
var SUN_SMAXIS = 1.49585e8; | ||
// Ecliptic longitude of the Sun at perigee | ||
ecliptic_longitude_perigee: 282.596403, | ||
// Sun's angular size, in degrees, at semi-major axis distance | ||
var SUN_ANGULAR_SIZE_SMAXIS = 0.533128; | ||
// Eccentricity of Earth's orbit | ||
eccentricity: 0.016718, | ||
// Elements of the Moon's orbit, epoch 1980.0 | ||
// Moon's mean longitude at the epoch | ||
var MOON_MEAN_LONGITUDE_EPOCH = 64.975464; | ||
// Semi-major axis of Earth's orbit, in kilometers | ||
sun_smaxis: 1.49585e8, | ||
// Mean longitude of the perigee at the epoch | ||
var MOON_MEAN_PERIGEE_EPOCH = 349.383063; | ||
// Sun's angular size, in degrees, at semi-major axis distance | ||
sun_angular_size_smaxis: 0.533128, | ||
// Mean longitude of the node at the epoch | ||
var NODE_MEAN_LONGITUDE_EPOCH = 151.950429; | ||
// Elements of the Moon's orbit, epoch 1980.0 | ||
// Inclination of the Moon's orbit | ||
var MOON_INCLINATION = 5.145396; | ||
// Moon's mean longitude at the epoch | ||
moon_mean_longitude_epoch: 64.975464, | ||
// Mean longitude of the perigee at the epoch | ||
moon_mean_perigee_epoch: 349.383063, | ||
// Eccentricity of the Moon's orbit | ||
var MOON_ECCENTRICITY = 0.054900; | ||
// Mean longitude of the node at the epoch | ||
node_mean_longitude_epoch: 151.950429, | ||
// Moon's angular size at distance a from Earth | ||
var MOON_ANGULAR_SIZE = 0.5181; | ||
// Inclination of the Moon's orbit | ||
moon_inclination: 5.145396, | ||
// Semi-mojor axis of the Moon's orbit, in kilometers | ||
var MOON_SMAXIS = 384401.0; | ||
// Eccentricity of the Moon's orbit | ||
moon_eccentricity: 0.054900, | ||
// Parallax at a distance a from Earth | ||
var MOON_PARALLAX = 0.9507; | ||
// Moon's angular size at distance a from Earth | ||
moon_angular_size: 0.5181, | ||
// Synodic month (new Moon to new Moon), in days | ||
var SYNODIC_MONTH = 29.53058868; | ||
// Semi-mojor axis of the Moon's orbit, in kilometers | ||
moon_smaxis: 384401.0, | ||
// Parallax at a distance a from Earth | ||
moon_parallax: 0.9507, | ||
// Base date for E. W. Brown's numbered series of lunations (1923 January 16) | ||
var LUNATIONS_BASE = 2423436.0; | ||
// Synodic month (new Moon to new Moon), in days | ||
synodic_month: 29.53058868, | ||
// Properties of the Earth | ||
var EARTH_RADIUS = 6378.16; | ||
// Base date for E. W. Brown's numbered series of lunations (1923 January 16) | ||
lunations_base: 2423436.0, | ||
// #Properties of the Earth | ||
earth_radius: 6378.16 | ||
}; | ||
function fixangle(a) { | ||
@@ -189,9 +140,7 @@ return a - 360.0 * Math.floor(a/360.0); | ||
if(!phase_date) { | ||
phase_date = (new Date()).getJulian(); | ||
phase_date = new Date(); | ||
} | ||
else { | ||
phase_date = phase_date.getJulian(); | ||
} | ||
phase_date = julian.fromDate(phase_date); | ||
var day = phase_date - c.epoch; | ||
var day = phase_date - EPOCH; | ||
@@ -201,18 +150,18 @@ // Mean anomaly of the Sun | ||
//Convert from perigee coordinates to epoch 1980 | ||
var M = fixangle(N + c.ecliptic_longitude_epoch - c.ecliptic_longitude_perigee); | ||
var M = fixangle(N + ECLIPTIC_LONGITUDE_EPOCH - ECLIPTIC_LONGITUDE_PERIGEE); | ||
// Solve Kepler's equation | ||
var Ec = kepler(M, c.eccentricity); | ||
Ec = Math.sqrt((1 + c.eccentricity) / (1 - c.eccentricity)) * Math.tan(Ec/2.0); | ||
var Ec = kepler(M, ECCENTRICITY); | ||
Ec = Math.sqrt((1 + ECCENTRICITY) / (1 - ECCENTRICITY)) * Math.tan(Ec / 2); | ||
// True anomaly | ||
Ec = 2 * todeg(Math.atan(Ec)); | ||
// Suns's geometric ecliptic longuitude | ||
var lambda_sun = fixangle(Ec + c.ecliptic_longitude_perigee); | ||
var lambda_sun = fixangle(Ec + ECLIPTIC_LONGITUDE_PERIGEE); | ||
// Orbital distance factor | ||
var F = ((1 + c.eccentricity * Math.cos(torad(Ec))) / (1 - Math.pow(c.eccentricity, 2))); | ||
var F = ((1 + ECCENTRICITY * Math.cos(torad(Ec))) / (1 - ECCENTRICITY * ECCENTRICITY)); | ||
// Distance to Sun in km | ||
var sun_dist = c.sun_smaxis / F; | ||
var sun_angular_diameter = F * c.sun_angular_size_smaxis; | ||
var sun_dist = SUN_SMAXIS / F; | ||
var sun_angular_diameter = F * SUN_ANGULAR_SIZE_SMAXIS; | ||
@@ -222,9 +171,9 @@ // Calculation of the Moon's position | ||
// Moon's mean longitude | ||
var moon_longitude = fixangle(13.1763966 * day + c.moon_mean_longitude_epoch); | ||
var moon_longitude = fixangle(13.1763966 * day + MOON_MEAN_LONGITUDE_EPOCH); | ||
// Moon's mean anomaly | ||
var MM = fixangle(moon_longitude - 0.1114041 * day - c.moon_mean_perigee_epoch); | ||
var MM = fixangle(moon_longitude - 0.1114041 * day - MOON_MEAN_PERIGEE_EPOCH); | ||
// Moon's ascending node mean longitude | ||
// MN = fixangle(c.node_mean_longitude_epoch - 0.0529539 * day) | ||
// MN = fixangle(NODE_MEAN_LONGITUDE_EPOCH - 0.0529539 * day) | ||
@@ -265,22 +214,20 @@ var evection = 1.2739 * Math.sin(torad(2*(moon_longitude - lambda_sun) - MM)); | ||
// Calculate distance of Moon from the centre of the Earth | ||
var moon_dist = (c.moon_smaxis * (1 - Math.pow(c.moon_eccentricity,2))) / (1 + c.moon_eccentricity * Math.cos(torad(MmP + mEc))); | ||
var moon_dist = (MOON_SMAXIS * (1 - MOON_ECCENTRICITY * MOON_ECCENTRICITY)) / (1 + MOON_ECCENTRICITY * Math.cos(torad(MmP + mEc))); | ||
// Calculate Moon's angular diameter | ||
var moon_diam_frac = moon_dist / c.moon_smaxis; | ||
var moon_angular_diameter = c.moon_angular_size / moon_diam_frac; | ||
var moon_diam_frac = moon_dist / MOON_SMAXIS; | ||
var moon_angular_diameter = MOON_ANGULAR_SIZE / moon_diam_frac; | ||
// Calculate Moon's parallax (unused?) | ||
// moon_parallax = c.moon_parallax / moon_diam_frac | ||
// moon_parallax = MOON_PARALLAX / moon_diam_frac | ||
var res = { | ||
'phase': fixangle(moon_age) / 360.0, | ||
'illuminated': moon_phase, | ||
'age': c.synodic_month * fixangle(moon_age) / 360.0, | ||
'distance': moon_dist, | ||
'angular_diameter': moon_angular_diameter, | ||
'sun_distance': sun_dist, | ||
'sun_angular_diameter': sun_angular_diameter | ||
return { | ||
phase: fixangle(moon_age) / 360.0, | ||
illuminated: moon_phase, | ||
age: SYNODIC_MONTH * fixangle(moon_age) / 360.0, | ||
distance: moon_dist, | ||
angular_diameter: moon_angular_diameter, | ||
sun_distance: sun_dist, | ||
sun_angular_diameter: sun_angular_diameter | ||
}; | ||
return res; | ||
} | ||
@@ -300,3 +247,3 @@ | ||
var adate = new Date(sdate.valueOf()); // today! | ||
var adate = new Date(sdate.getTime()); // today! | ||
var x = 45; // go back 45 days! | ||
@@ -309,6 +256,6 @@ adate.setDate(adate.getDate() - x); | ||
sdate = sdate.getJulian(); | ||
sdate = julian.fromDate(sdate); | ||
var k2; | ||
while(1) { | ||
adate = adate + c.synodic_month; | ||
adate = adate + SYNODIC_MONTH; | ||
k2 = k1 + 1; | ||
@@ -356,3 +303,3 @@ var nt2 = meanphase(adate, k2); | ||
var pt = ( | ||
2415020.75933 + c.synodic_month * k + 0.0001178 * t2 - | ||
2415020.75933 + SYNODIC_MONTH * k + 0.0001178 * t2 - | ||
0.000000155 * t3 + 0.00033 * dsin(166.56 + 132.87 * t - | ||
@@ -425,3 +372,3 @@ 0.009173 * t2) | ||
return pt.Julian2Date(true); | ||
return julian.toDate(pt); | ||
} | ||
@@ -441,4 +388,4 @@ | ||
// Time in Julian centuries from 1900 January 12 noon | ||
var delta_t = (sdate - (new Date(1900,0,1,12))) / (1000*60*60*24); | ||
// Time in Julian centuries from 1900 January 12 noon UTC | ||
var delta_t = (sdate - (-2208945600000)) / (1000*60*60*24); | ||
var t = delta_t / 36525; | ||
@@ -451,4 +398,4 @@ | ||
nt1 = ( | ||
2415020.75933 + c.synodic_month * k + 0.0001178 * t2 - | ||
var nt1 = ( | ||
2415020.75933 + SYNODIC_MONTH * k + 0.0001178 * t2 - | ||
0.000000155 * t3 + 0.00033 * dsin(166.56 + 132.87 * t - | ||
@@ -461,6 +408,4 @@ 0.009173 * t2) | ||
module.exports = { | ||
'phase_hunt': phase_hunt, | ||
'phase': phase | ||
}; | ||
exports.phase = phase; | ||
exports.phase_hunt = phase_hunt; | ||
})(); |
{ | ||
"name": "lune", | ||
"version": "0.2.0", | ||
"version": "0.2.1", | ||
"description": "Calculate the phases of the moon", | ||
@@ -21,7 +21,7 @@ "keywords": [ | ||
}, | ||
"main": "index.js", | ||
"main": "lib/lune.js", | ||
"license": "Apache-2.0", | ||
"devDependencies": { | ||
"assert": "~1.1.1", | ||
"mocha": "~1.17.1" | ||
"chai": "~3.5.0", | ||
"mocha": "~2.4.5" | ||
}, | ||
@@ -28,0 +28,0 @@ "scripts": { |
@@ -5,3 +5,3 @@ <div align="center"> | ||
# Lune [![Build Status](https://travis-ci.org/ryanseys/lune.png)](https://travis-ci.org/ryanseys/lune) | ||
# Lune [![Build Status](https://travis-ci.org/ryanseys/lune.svg?branch=0.2.0)](https://travis-ci.org/ryanseys/lune) | ||
@@ -12,3 +12,5 @@ Lune.js — calculate the phases of the moon. | ||
`npm install lune` | ||
```sh | ||
npm install lune | ||
``` | ||
@@ -15,0 +17,0 @@ ## Usage |
@@ -1,40 +0,113 @@ | ||
var assert = require("assert"); | ||
var lune = require('../lib/lune'); | ||
var assert = require("chai").assert; | ||
var lune = require("../lib/lune"); | ||
var julian = require("../lib/julian"); | ||
describe('lune', function() { | ||
describe('#phase()', function() { | ||
it('should return expected values for feb 17th data', function() { | ||
describe("lune", function() { | ||
describe("#phase()", function() { | ||
it("should return expected values for Feb 17th data", function() { | ||
var phase = lune.phase(new Date("2014-02-17T00:00-0500")); | ||
var feb17 = { | ||
phase: 0.5616632223402672, | ||
illuminated: 0.9629393807872504, | ||
age: 16.586245595613818, | ||
distance: 396868.3763643785, | ||
angular_diameter: 0.5018242066159135, | ||
sun_distance: 147816061.66410872, | ||
sun_angular_diameter: 0.5395080276270386 | ||
}; | ||
assert.closeTo(phase.phase, 0.568 , 0.001 ); | ||
assert.closeTo(phase.illuminated, 0.955 , 0.001 ); | ||
assert.closeTo(phase.age, 16.779 , 0.030 ); | ||
assert.closeTo(phase.distance, 396084.5 , 384.4 ); | ||
assert.closeTo(phase.angular_diameter, 0.5028, 0.0005); | ||
assert.closeTo(phase.sun_distance, 147822500 , 149600 ); | ||
assert.closeTo(phase.sun_angular_diameter, 0.5395, 0.0005); | ||
}); | ||
var lunedata = lune.phase(new Date(2014, 1, 17)); | ||
// http://bazaar.launchpad.net/~keturn/py-moon-phase/trunk/view/head:/moontest.py | ||
it("should be accurate to astronomical observations", function() { | ||
var observations = [ | ||
["1989-01-07T19:22Z", 0.00], | ||
["1989-01-14T13:58Z", 0.25], | ||
["1989-01-21T21:33Z", 0.50], | ||
["1989-01-30T02:02Z", 0.75], | ||
["1989-02-06T07:37Z", 0.00], | ||
["1989-02-12T23:15Z", 0.25], | ||
["1989-02-20T15:32Z", 0.50], | ||
["1989-02-28T20:08Z", 0.75], | ||
["1989-03-07T18:19Z", 0.00], | ||
["1989-03-14T10:11Z", 0.25], | ||
["1989-03-22T09:58Z", 0.50], | ||
["1989-03-30T10:21Z", 0.75], | ||
["1989-04-06T03:33Z", 0.00], | ||
["1989-04-12T23:13Z", 0.25], | ||
["1989-04-21T03:13Z", 0.50], | ||
["1989-04-28T20:46Z", 0.75], | ||
["1989-05-05T11:46Z", 0.00], | ||
["1989-05-12T14:19Z", 0.25], | ||
["1989-05-20T18:16Z", 0.50], | ||
["1989-05-28T04:01Z", 0.75], | ||
["1989-06-03T19:53Z", 0.00], | ||
["1989-06-11T06:59Z", 0.25], | ||
["1989-06-19T06:57Z", 0.50], | ||
["1989-06-26T09:09Z", 0.75], | ||
["1989-07-03T04:59Z", 0.00], | ||
["1989-07-11T00:19Z", 0.25], | ||
["1989-07-18T17:42Z", 0.50], | ||
["1989-07-25T13:31Z", 0.75], | ||
["1989-08-01T16:06Z", 0.00], | ||
["1989-08-09T17:28Z", 0.25], | ||
["1989-08-17T03:07Z", 0.50], | ||
["1989-08-23T18:40Z", 0.75], | ||
["1989-08-31T05:44Z", 0.00], | ||
["1989-09-08T09:49Z", 0.25], | ||
["1989-09-15T11:51Z", 0.50], | ||
["1989-09-22T02:10Z", 0.75], | ||
["1989-09-29T21:47Z", 0.00] | ||
]; | ||
assert.equal(JSON.stringify(feb17), JSON.stringify(lunedata)); | ||
var error = 0; | ||
var i; | ||
var obs; | ||
var e; | ||
for(i = 0; i < observations.length; i++) { | ||
obs = observations[i]; | ||
e = Math.abs(lune.phase(new Date(obs[0])).phase - obs[1]); | ||
if(e > 0.5) { | ||
// phase is circular | ||
e = 1 - e; | ||
} | ||
error += e; | ||
} | ||
assert.isAtMost(error / observations.length, 0.001); | ||
}); | ||
}); | ||
describe('#phase_hunt', function() { | ||
it('should handle timezones correctly', function() { | ||
process.env.TZ = 'America/New_York'; | ||
var d = new Date(2014, 10, 1, 16, 56, 00); | ||
var t = d.getTime(); | ||
if (1414837560000 != t) { | ||
console.log('Unable to run timezone test because process.env.TZ quirk. '+ | ||
'See https://github.com/joyent/node/issues/3286'); | ||
return; | ||
} | ||
var hunt = lune.phase_hunt(d); | ||
// 1415292777000 incorrect EST time | ||
// 1415312577000 correct UTC time | ||
assert(1415312577000, hunt.full_date.getTime()); | ||
}); | ||
describe("#phase_hunt", function() { | ||
it("should handle timezones correctly", function() { | ||
var d = new Date("2014-11-01T06:26-0400"); | ||
var hunt = lune.phase_hunt(d); | ||
// 1415292777000 incorrect EST time | ||
// 1415312577000 correct UTC time | ||
// date conversion is now accurate to the millisecond, but these tests | ||
// were written when they were only accurate to the second | ||
assert.closeTo(hunt.full_date.getTime(), 1415312577000, 500); | ||
}); | ||
}); | ||
}); | ||
describe("julian", function() { | ||
describe("#fromDate", function() { | ||
/* http://aa.usno.navy.mil/data/docs/JulianDate.php */ | ||
it("should convert 2000-01-01T00:00Z to 2451544.5", function() { | ||
assert.closeTo( | ||
julian.fromDate(new Date("2000-01-01T00:00Z")), | ||
2451544.5, | ||
0.5/86400 | ||
); | ||
}); | ||
}); | ||
describe("#toDate", function() { | ||
/* http://aa.usno.navy.mil/data/docs/JulianDate.php */ | ||
it("should convert 2457464.179862 to 2016-03-16T16:19Z", function() { | ||
assert.closeTo( | ||
julian.toDate(2457464.179862).getTime(), | ||
(new Date("2016-03-16T16:19Z")).getTime(), | ||
500 | ||
); | ||
}); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
30118
8
434
114
0