const phases = [{ phase: "new", min: 0, max: 1 }, { phase: "waxing crescent", min: 1, max: 6.38264692644 }, { phase: "first quarter", min: 6.38264692644, max: 8.38264692644 }, { phase: "waxing gibbous", min: 8.38264692644, max: 13.76529385288 }, { phase: "full", min: 13.76529385288, max: 15.76529385288 }, { phase: "waning gibbous", min: 15.76529385288, max: 21.14794077932 }, { phase: "last quarter", min: 21.14794077932, max: 23.14794077932 }, { phase: "waning crescent", min: 23.14794077932, max: 28.53058770576 }, { phase: "new", min: 28.53058770576, max: 29.53058770576 }]; function fmod(dividend, divisor) { let multiplier = 0; while(divisor * multiplier < dividend) { ++multiplier; } --multiplier; return dividend - (divisor * multiplier); } function getMoonPhase(date) { const $unixdate = Math.round(date.getTime() / 1000); const $lunardays = 29.53058770576; const $lunarsecs = $lunardays * (24 * 60 *60); const $new2000 = Math.round((new Date('2000-01-06T18:14:00.000Z')).getTime() / 1000); const $totalsecs = $unixdate - $new2000; let $currentsecs = fmod($totalsecs, $lunarsecs); if ($currentsecs < 0) { $currentsecs += $lunarsecs; } const $currentfrac = $currentsecs / $lunarsecs; const $currentdays = $currentfrac * $lunardays; const { phase } = phases.filter(each => ($currentdays >= each.min && $currentdays <= each.max))[0]; return { phase, age: $currentdays.toFixed(2), lunation: ($currentfrac*100).toFixed(2), }; } console.log(getMoonPhase(new Date('2022-02-21T03:00:00.000Z')));