consider adding multiple language, and next new moon/full moon? Here is my code
talpx0 opened this issue · 1 comments
talpx0 commented
export function calculateMoonPhase(currentDate: Date): number {
const newMoonDate = new Date(Date.UTC(2019, 0, 6, 1, 28, 0)); // Reference New Moon date
const lunarCycleLength = 29.53; // Average length of the lunar cycle in days
const diffInDays = (currentDate.getTime() - newMoonDate.getTime()) / (1000 * 3600 * 24);
const moonPhase = (diffInDays % lunarCycleLength) / lunarCycleLength;
return moonPhase;
}
export function estimateNextMoonPhases(currentDate: Date): { nextNewMoon: string, nextFullMoon: string} {
const currentMoonPhase = calculateMoonPhase(currentDate);
const lunarCycleLength = 29.53; // Average length of the lunar cycle in days
let daysUntilNextNewMoon = lunarCycleLength * (1 - currentMoonPhase);
if (currentMoonPhase >= 0 && currentMoonPhase < 0.5) {
daysUntilNextNewMoon = lunarCycleLength * (0.5 - currentMoonPhase);
}
let daysUntilNextFullMoon = lunarCycleLength * (0.5 - currentMoonPhase);
if (currentMoonPhase >= 0.5) {
daysUntilNextFullMoon = lunarCycleLength * (1 - currentMoonPhase) + (lunarCycleLength / 2);
}
const nextNewMoon = formatMMDDDate(new Date(currentDate.getTime() + daysUntilNextNewMoon * 24 * 3600 * 1000));
const nextFullMoon = formatMMDDDate(new Date(currentDate.getTime() + daysUntilNextFullMoon * 24 * 3600 * 1000));
return { nextNewMoon, nextFullMoon };
}
export function getMoonPhaseName(moonPhase: number): string {
if(moonPhase < 0.03 || moonPhase > 0.97) {
return "NewMoon";
} else if(moonPhase < 0.22) {
return "WaxingCrescent";
} else if(moonPhase < 0.28) {
return "FirstQuarter";
} else if(moonPhase < 0.47) {
return "WaxingGibbous";
} else if(moonPhase < 0.53) {
return "FullMoon";
} else if(moonPhase < 0.72) {
return "WaningGibbous";
} else if(moonPhase < 0.78) {
return "LastQuarter";
} else {
return "WaningCrescent";
}
}
export function getMoonPhasesForPeriod(currentDate: Date = new Date()): MoonPhase[] {
const todayMoonPhaseNumber = calculateMoonPhase(currentDate);
const todayMoonPhaseName = getMoonPhaseName(todayMoonPhaseNumber);
const { nextNewMoon, nextFullMoon } = estimateNextMoonPhases(currentDate);
const today: MoonPhase = {
date: formatMMDDDate(currentDate),
moonPhaseIcon: MoonPhaseIcons[todayMoonPhaseName],
name: todayMoonPhaseName,
};
const nextNewMoonPhase: MoonPhase = {
date: nextNewMoon,
moonPhaseIcon: MoonPhaseIcons["NewMoon"],
name: "NewMoon",
};
const nextFullMoonPhase: MoonPhase = {
date: nextFullMoon,
moonPhaseIcon: MoonPhaseIcons["FullMoon"],
name: "FullMoon",
};
// Determine the sequence based on current phase
let phases: MoonPhase[];
if (todayMoonPhaseNumber < 0.5) {
// Today -> Next Full Moon -> Next New Moon
phases = [today, nextFullMoonPhase, nextNewMoonPhase];
} else {
// Today -> Next New Moon -> Next Full Moon
phases = [today, nextNewMoonPhase, nextFullMoonPhase];
}
return phases;
}
jasonsturges commented
Appreciate sharing the ideas and implementation.
Internationalization support was something I had considered based on the lunar phase enumeration, but adds a hefty amount of complexity.
Any i18n implementation and corresponding translations would be local to that project.
Similar requests for next cycles have been made, in #30, and pull request in #17.
My formula has a small margin of error that I never had time to resolve. There are some other aspects in regards to how this library handles time windows versus events.