UNPKG

salat-first

Version:

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

229 lines (228 loc) 10.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PrayerTimes = void 0; const astronomy_1 = require("../core/astronomy"); const datetime_1 = require("../core/datetime"); const shadow_1 = require("../core/shadow"); const adjustments_1 = require("./adjustments"); /** * Class representing prayer times for a specific date and location */ class PrayerTimes { /** * Creates a new prayer times object * @param coordinates The coordinates * @param date The date * @param calculationParameters The calculation parameters */ constructor(coordinates, date, calculationParameters) { this.coordinates = coordinates; this.date = date; this.calculationParameters = calculationParameters; // Calculate the Julian day const year = date.getFullYear(); const month = date.getMonth() + 1; const day = date.getDate(); const julianDay = astronomy_1.Astronomy.julianDay(year, month, day); const julianCentury = astronomy_1.Astronomy.julianCentury(julianDay); // Solar calculations const meanSolarLongitude = astronomy_1.Astronomy.meanSolarLongitude(julianCentury); const meanSolarAnomaly = astronomy_1.Astronomy.meanSolarAnomaly(julianCentury); const apparentSolarLongitude = astronomy_1.Astronomy.apparentSolarLongitude(julianCentury, meanSolarLongitude); // Calculate solar declination and right ascension const solarDeclination = 23.45 * Math.sin((Math.PI / 180) * (360 / 365) * ((0, datetime_1.dayOfYear)(date) - 81)); // Calculate Dhuhr time (transit) const transit = 12 + (0 - coordinates.longitude) / 15; this.dhuhr = new Date(date); this.dhuhr.setHours(Math.floor(transit)); this.dhuhr.setMinutes(Math.round((transit - Math.floor(transit)) * 60)); this.dhuhr.setSeconds(0); this.dhuhr.setMilliseconds(0); // Calculate sunrise and sunset const sunriseSunsetAngle = -0.833; // Standard refraction and semi-diameter const sunriseHourAngle = this.calculateHourAngle(sunriseSunsetAngle, solarDeclination, coordinates.latitude, false); const sunsetHourAngle = this.calculateHourAngle(sunriseSunsetAngle, solarDeclination, coordinates.latitude, true); this.sunrise = this.timeFromHourAngle(sunriseHourAngle, date); this.sunset = this.timeFromHourAngle(sunsetHourAngle, date); // Calculate Fajr const fajrHourAngle = this.calculateHourAngle(-calculationParameters.fajrAngle, solarDeclination, coordinates.latitude, false); this.fajr = this.timeFromHourAngle(fajrHourAngle, date); // Calculate Asr const asrShadowFactor = calculationParameters.getShadowLength(); const asrAngle = (0, shadow_1.calculateAsrAngle)(coordinates.latitude, solarDeclination, asrShadowFactor); const asrHourAngle = this.calculateHourAngle(asrAngle, solarDeclination, coordinates.latitude, true); this.asr = this.timeFromHourAngle(asrHourAngle, date); // Calculate Maghrib if (calculationParameters.maghribAngle > 0) { const maghribHourAngle = this.calculateHourAngle(-calculationParameters.maghribAngle, solarDeclination, coordinates.latitude, true); this.maghrib = this.timeFromHourAngle(maghribHourAngle, date); } else { this.maghrib = new Date(this.sunset); } // Calculate Isha if (calculationParameters.ishaInterval > 0) { this.isha = (0, datetime_1.addMinutes)(this.maghrib, calculationParameters.ishaInterval); } else { const ishaHourAngle = this.calculateHourAngle(-calculationParameters.ishaAngle, solarDeclination, coordinates.latitude, true); this.isha = this.timeFromHourAngle(ishaHourAngle, date); } // Apply method and manual adjustments this.fajr = (0, datetime_1.addMinutes)(this.fajr, calculationParameters.methodAdjustments.fajr + calculationParameters.adjustments.fajr); this.sunrise = (0, datetime_1.addMinutes)(this.sunrise, calculationParameters.methodAdjustments.sunrise + calculationParameters.adjustments.sunrise); this.dhuhr = (0, datetime_1.addMinutes)(this.dhuhr, calculationParameters.methodAdjustments.dhuhr + calculationParameters.adjustments.dhuhr); this.asr = (0, datetime_1.addMinutes)(this.asr, calculationParameters.methodAdjustments.asr + calculationParameters.adjustments.asr); this.maghrib = (0, datetime_1.addMinutes)(this.maghrib, calculationParameters.methodAdjustments.maghrib + calculationParameters.adjustments.maghrib); this.isha = (0, datetime_1.addMinutes)(this.isha, calculationParameters.methodAdjustments.isha + calculationParameters.adjustments.isha); // Round times according to rounding setting this.fajr = (0, datetime_1.roundToNearestMinute)(this.fajr); this.sunrise = (0, datetime_1.roundToNearestMinute)(this.sunrise); this.dhuhr = (0, datetime_1.roundToNearestMinute)(this.dhuhr); this.asr = (0, datetime_1.roundToNearestMinute)(this.asr); this.maghrib = (0, datetime_1.roundToNearestMinute)(this.maghrib); this.isha = (0, datetime_1.roundToNearestMinute)(this.isha); } /** * Calculates the hour angle for a given angle, declination and latitude * @param angle The angle in degrees * @param declination The solar declination in degrees * @param latitude The latitude in degrees * @param afterTransit Whether the hour angle is after transit (true) or before (false) * @returns The hour angle in degrees */ calculateHourAngle(angle, declination, latitude, afterTransit) { const term1 = Math.sin((angle * Math.PI) / 180); const term2 = Math.sin((latitude * Math.PI) / 180) * Math.sin((declination * Math.PI) / 180); const term3 = Math.cos((latitude * Math.PI) / 180) * Math.cos((declination * Math.PI) / 180); const hourAngleRadians = Math.acos((term1 - term2) / term3); const hourAngleDegrees = (hourAngleRadians * 180) / Math.PI; return afterTransit ? hourAngleDegrees : -hourAngleDegrees; } /** * Converts an hour angle to a time * @param hourAngle The hour angle in degrees * @param date The base date * @returns The time */ timeFromHourAngle(hourAngle, date) { const transit = 12 + (0 - this.coordinates.longitude) / 15; const timeDecimal = transit + hourAngle / 15; const hours = Math.floor(timeDecimal); const minutes = Math.floor((timeDecimal - hours) * 60); const seconds = Math.floor((timeDecimal - hours - minutes / 60) * 3600); const result = new Date(date); result.setHours(hours, minutes, seconds, 0); return result; } /** * Gets the time for a specific prayer * @param prayer The prayer name * @returns The prayer time or null if invalid */ getTimeForPrayer(prayer) { switch (prayer) { case adjustments_1.Prayer.Fajr: return this.fajr; case adjustments_1.Prayer.Sunrise: return this.sunrise; case adjustments_1.Prayer.Dhuhr: return this.dhuhr; case adjustments_1.Prayer.Asr: return this.asr; case adjustments_1.Prayer.Maghrib: return this.maghrib; case adjustments_1.Prayer.Isha: return this.isha; default: return null; } } /** * Gets the current prayer at a specific time * @param time The time to check (defaults to now) * @returns The current prayer name */ getCurrentPrayer(time = new Date()) { if (time >= this.isha) { return adjustments_1.Prayer.Isha; } else if (time >= this.maghrib) { return adjustments_1.Prayer.Maghrib; } else if (time >= this.asr) { return adjustments_1.Prayer.Asr; } else if (time >= this.dhuhr) { return adjustments_1.Prayer.Dhuhr; } else if (time >= this.sunrise) { return adjustments_1.Prayer.Sunrise; } else if (time >= this.fajr) { return adjustments_1.Prayer.Fajr; } else { return adjustments_1.Prayer.None; } } /** * Gets the next prayer at a specific time * @param time The time to check (defaults to now) * @returns The next prayer name */ getNextPrayer(time = new Date()) { if (time >= this.isha) { // After Isha, the next prayer is Fajr of the next day return adjustments_1.Prayer.Fajr; } else if (time >= this.maghrib) { return adjustments_1.Prayer.Isha; } else if (time >= this.asr) { return adjustments_1.Prayer.Maghrib; } else if (time >= this.dhuhr) { return adjustments_1.Prayer.Asr; } else if (time >= this.sunrise) { return adjustments_1.Prayer.Dhuhr; } else if (time >= this.fajr) { return adjustments_1.Prayer.Sunrise; } else { return adjustments_1.Prayer.Fajr; } } /** * Gets all prayer times as an object * @returns Object with all prayer times */ getAllTimes() { return { fajr: this.fajr, sunrise: this.sunrise, dhuhr: this.dhuhr, asr: this.asr, maghrib: this.maghrib, isha: this.isha, }; } /** * Returns a string representation of all prayer times * @returns String with all prayer times */ toString() { return `Fajr: ${this.fajr.toLocaleTimeString()}, Sunrise: ${this.sunrise.toLocaleTimeString()}, Dhuhr: ${this.dhuhr.toLocaleTimeString()}, Asr: ${this.asr.toLocaleTimeString()}, Maghrib: ${this.maghrib.toLocaleTimeString()}, Isha: ${this.isha.toLocaleTimeString()}`; } } exports.PrayerTimes = PrayerTimes;