UNPKG

salat-first

Version:

Islamic prayer times calculation with special support for Moroccan methods and Maliki madhab

205 lines (204 loc) 8.12 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Astronomy = void 0; const math_1 = require("./math"); const datetime_1 = require("./datetime"); /** * Utility class for astronomical calculations */ class Astronomy { /** * Calculates the Julian day for a given date * @param year The year * @param month The month (1-12) * @param day The day * @param hours The hours (0-23) * @returns The Julian day */ static julianDay(year, month, day, hours = 0) { const Y = Math.trunc(month > 2 ? year : year - 1); const M = Math.trunc(month > 2 ? month : month + 12); const D = day + hours / 24; const A = Math.trunc(Y / 100); const B = Math.trunc(2 - A + Math.trunc(A / 4)); const i0 = Math.trunc(365.25 * (Y + 4716)); const i1 = Math.trunc(30.6001 * (M + 1)); return i0 + i1 + D + B - 1524.5; } /** * Calculates the Julian century for a given Julian day * @param julianDay The Julian day * @returns The Julian century */ static julianCentury(julianDay) { return (julianDay - 2451545.0) / 36525; } /** * Calculates the mean solar longitude in degrees * @param julianCentury The Julian century * @returns The mean solar longitude in degrees */ static meanSolarLongitude(julianCentury) { const T = julianCentury; const term1 = 280.4664567; const term2 = 36000.76983 * T; const term3 = 0.0003032 * Math.pow(T, 2); const L0 = term1 + term2 + term3; return (0, math_1.unwindAngle)(L0); } /** * Calculates the mean solar anomaly in degrees * @param julianCentury The Julian century * @returns The mean solar anomaly in degrees */ static meanSolarAnomaly(julianCentury) { const T = julianCentury; const term1 = 357.52911; const term2 = 35999.05029 * T; const term3 = 0.0001537 * Math.pow(T, 2); const M = term1 + term2 - term3; return (0, math_1.unwindAngle)(M); } /** * Calculates the equation of the center of the Sun in degrees * @param julianCentury The Julian century * @param meanAnomaly The mean anomaly in degrees * @returns The equation of the center in degrees */ static solarEquationOfCenter(julianCentury, meanAnomaly) { const T = julianCentury; const Mrad = (0, math_1.degreesToRadians)(meanAnomaly); const term1 = (1.914602 - 0.004817 * T - 0.000014 * Math.pow(T, 2)) * Math.sin(Mrad); const term2 = (0.019993 - 0.000101 * T) * Math.sin(2 * Mrad); const term3 = 0.000289 * Math.sin(3 * Mrad); return term1 + term2 + term3; } /** * Calculates the apparent solar longitude in degrees * @param julianCentury The Julian century * @param meanLongitude The mean longitude in degrees * @returns The apparent solar longitude in degrees */ static apparentSolarLongitude(julianCentury, meanLongitude) { const T = julianCentury; const L0 = meanLongitude; const longitude = L0 + Astronomy.solarEquationOfCenter(T, Astronomy.meanSolarAnomaly(T)); const Omega = 125.04 - 1934.136 * T; const Lambda = longitude - 0.00569 - 0.00478 * Math.sin((0, math_1.degreesToRadians)(Omega)); return (0, math_1.unwindAngle)(Lambda); } /** * Calculates the altitude of a celestial body in degrees * @param observerLatitude The observer's latitude in degrees * @param declination The declination of the celestial body in degrees * @param localHourAngle The local hour angle of the celestial body in degrees * @returns The altitude of the celestial body in degrees */ static altitudeOfCelestialBody(observerLatitude, declination, localHourAngle) { const Phi = observerLatitude; const delta = declination; const H = localHourAngle; const term1 = Math.sin((0, math_1.degreesToRadians)(Phi)) * Math.sin((0, math_1.degreesToRadians)(delta)); const term2 = Math.cos((0, math_1.degreesToRadians)(Phi)) * Math.cos((0, math_1.degreesToRadians)(delta)) * Math.cos((0, math_1.degreesToRadians)(H)); return (0, math_1.radiansToDegrees)(Math.asin(term1 + term2)); } /** * Calculates the days since the winter solstice * @param dayOfYear The day of the year (1-366) * @param year The year * @param latitude The latitude in degrees * @returns The number of days since the winter solstice */ static daysSinceSolstice(dayOfYear, year, latitude) { let daysSinceSolstice = 0; const northernOffset = 10; const southernOffset = (0, datetime_1.isLeapYear)(year) ? 173 : 172; const daysInYear = (0, datetime_1.isLeapYear)(year) ? 366 : 365; if (latitude >= 0) { daysSinceSolstice = dayOfYear + northernOffset; if (daysSinceSolstice >= daysInYear) { daysSinceSolstice = daysSinceSolstice - daysInYear; } } else { daysSinceSolstice = dayOfYear - southernOffset; if (daysSinceSolstice < 0) { daysSinceSolstice = daysSinceSolstice + daysInYear; } } return daysSinceSolstice; } /** * Adjusts the morning twilight time based on the season and latitude * @param latitude The latitude in degrees * @param day The day of the year (1-366) * @param year The year * @param sunrise The sunrise time * @returns The adjusted morning twilight time */ static adjustMorningTwilight(latitude, day, year, sunrise) { const a = 75 + (28.65 / 55.0) * Math.abs(latitude); const b = 75 + (19.44 / 55.0) * Math.abs(latitude); const c = 75 + (32.74 / 55.0) * Math.abs(latitude); const d = 75 + (48.1 / 55.0) * Math.abs(latitude); const dyy = Astronomy.daysSinceSolstice(day, year, latitude); let adjustment; if (dyy < 91) { adjustment = a + ((b - a) / 91.0) * dyy; } else if (dyy < 137) { adjustment = b + ((c - b) / 46.0) * (dyy - 91); } else if (dyy < 183) { adjustment = c + ((d - c) / 46.0) * (dyy - 137); } else if (dyy < 229) { adjustment = d + ((c - d) / 46.0) * (dyy - 183); } else if (dyy < 275) { adjustment = c + ((b - c) / 46.0) * (dyy - 229); } else { adjustment = b + ((a - b) / 91.0) * (dyy - 275); } return (0, datetime_1.addSeconds)(sunrise, Math.round(adjustment * -60.0)); } /** * Adjusts the evening twilight time based on the season and latitude * @param latitude The latitude in degrees * @param day The day of the year (1-366) * @param year The year * @param sunset The sunset time * @returns The adjusted evening twilight time */ static adjustEveningTwilight(latitude, day, year, sunset) { const a = 75 + (25.6 / 55.0) * Math.abs(latitude); const b = 75 + (2.05 / 55.0) * Math.abs(latitude); const c = 75 - (9.21 / 55.0) * Math.abs(latitude); const d = 75 + (6.14 / 55.0) * Math.abs(latitude); const dyy = Astronomy.daysSinceSolstice(day, year, latitude); let adjustment; if (dyy < 91) { adjustment = a + ((b - a) / 91.0) * dyy; } else if (dyy < 137) { adjustment = b + ((c - b) / 46.0) * (dyy - 91); } else if (dyy < 183) { adjustment = c + ((d - c) / 46.0) * (dyy - 137); } else if (dyy < 229) { adjustment = d + ((c - d) / 46.0) * (dyy - 183); } else if (dyy < 275) { adjustment = c + ((b - c) / 46.0) * (dyy - 229); } else { adjustment = b + ((a - b) / 91.0) * (dyy - 275); } return (0, datetime_1.addSeconds)(sunset, Math.round(adjustment * 60.0)); } } exports.Astronomy = Astronomy;