salat-first
Version:
Islamic prayer times calculation with special support for Moroccan methods and Maliki madhab
205 lines (204 loc) • 8.12 kB
JavaScript
"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;