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