updated for timezone handling and asr calc

This commit is contained in:
Ali Camarata 2023-11-13 08:51:34 +07:00
parent 13a477abee
commit b867162ace
12 changed files with 191 additions and 39 deletions

16
CHANGELOG.md Normal file
View file

@ -0,0 +1,16 @@
# Changelog
All notable changes to this project will be documented in this file.
## [1.0.0] - 2023-11-11
- Initial release
## [1.1.0] - 2023-11-12
- Updated calculation behavior to be more accurate (major)
## [1.2.2] - 2023-11-12
- Moved timezone to main args and changed default behavior (major)
- Updated test cases and readme to reflect new usage (minor)

View file

@ -14,15 +14,37 @@ npm install praycalc
Example of using praycalc to get prayer times:
```js
const { calcTimes } = require('./calcTimes');
const { getTimes, calcTimesAll } = require('praycalc');
const date = new Date(); // Current date
const latitude = 40.7128; // Latitude for New York City
const longitude = -74.006; // Longitude for New York City
const elevation = 10; // Elevation for New York City
const date = new Date();
const prayerTimes = calcTimes(date, latitude, longitude, elevation);
console.log(prayerTimes);
/* NYC - minimum params
const city = "New York"
const lat = 40.7128;
const lng = -74.006;
const tz = null
const elevation = null
const temperature = null
const pressure = null
*/
// Jakarta - all params
const city = "Jakarta"
const lat = -6.2088
const lng = 106.8456
const tz = 7
const elevation = 18
const temperature = 26.56
const pressure = 1017
// Get results
const get = getTimes(date, lat, lng); // minimal args
const calc = calcTimesAll(date, lat, lng, tz, elevation, temperature, pressure);
// Print results
console.log(`\nTest: ${city} with current Date():\n`)
console.log("getTimes =", get, "\n");
console.log("calcTimesAll =", calc, "\n");
```
Exported functions include getTimes, calcTimes, getTimesAll, calcTimesAll where the "get" functions return fractal or decimal times directly from the source nrel-spa calculator and the "calc" functions return formatted times in HH:MM:SS.sss format. The functions will give results including our custom angle but the "All" functions will include a methods key with all traditional static angle methods (Muslim World League, Egyptian General Authority of Survey, ISNA, etc.) included as well for their Fajr and Isha times.

View file

@ -12,8 +12,8 @@ const { getTimes } = require('./getTimes');
* @param {number} [pressure=1013.25] - Atmospheric pressure in millibars (default 1013.25).
* @returns {Object} - Object containing prayer times.
*/
function calcTimes(date, lat, lng, elevation = 50, temperature = 15, pressure = 1013.25) {
let result = getTimes(date, lat, lng, elevation, temperature, pressure);
function calcTimes(date, lat, lng, tz, elevation = 50, temperature = 15, pressure = 1013.25) {
let result = getTimes(date, lat, lng, tz, elevation, temperature, pressure);
// Sort the result object by their values, excluding "Angle"
let sortedEntries = Object.entries(result)

View file

@ -1,8 +1,8 @@
const { fractalTime } = require('nrel-spa');
const { getTimesAll } = require('./getTimesAll');
function calcTimesAll(date, lat, lng, elevation = 10, temperature = 15, pressure = 1013.25) {
let result = getTimesAll(date, lat, lng, elevation, temperature, pressure);
function calcTimesAll(date, lat, lng, tz, elevation = 10, temperature = 15, pressure = 1013.25) {
let result = getTimesAll(date, lat, lng, tz, elevation, temperature, pressure);
// Sort the methods by Fajr time
let sortedMethods = Object.entries(result.Methods)

View file

@ -1,7 +1,7 @@
const { getSpa, fractalTime } = require('nrel-spa');
function getAsr(solarNoonDate, latitude, longitude, standard = true) {
const solarNoonAltitude = getSpa(solarNoonDate, latitude, longitude).zenith;
function getAsr(solarNoonDate, latitude, longitude, tz, standard = true) {
const solarNoonAltitude = getSpa(solarNoonDate, latitude, longitude, tz).zenith;
const shadowLengthAtNoon = 1 / Math.tan((90 - solarNoonAltitude) * Math.PI / 180);
// For standard method: Shadow length = object height + shadow length at noon
@ -12,9 +12,8 @@ function getAsr(solarNoonDate, latitude, longitude, standard = true) {
let asrTime;
for (let i = 0; i < 720; i++) { // Check next 12 hours
const testTime = new Date(solarNoonDate.getTime() + i * 60000); // Increment by one minute
const currentAltitude = getSpa(testTime, latitude, longitude).zenith;
const currentAltitude = getSpa(testTime, latitude, longitude, tz).zenith;
const currentShadowLength = 1 / Math.tan((90 - currentAltitude) * Math.PI / 180);
if (currentShadowLength >= targetShadowLength) {
asrTime = testTime;
break;

View file

@ -3,13 +3,13 @@ const { getAngles } = require('./getAngles');
const { getAsr } = require('./getAsr');
const { getQiyam } = require('./getQiyam');
function getTimes(date, lat, lng, elevation = 50, temperature = 15, pressure = 1013.25, standard = true) {
function getTimes(date, lat, lng, tz, elevation = 50, temperature = 15, pressure = 1013.25, standard = true) {
// Step 1: Get the custom angles
const { fajrAngle, ishaAngle } = getAngles(elevation, pressure, temperature);
// Step 2: Get SPA data with custom angle for Fajr/Isha
const spaParams = { elevation, temperature, pressure };
const spaData = getSpa(date, lat, lng, spaParams, [fajrAngle+90, ishaAngle+90]);
const spaData = getSpa(date, lat, lng, tz, spaParams, [fajrAngle+90, ishaAngle+90]);
// Organize prayer times
const fajrTime = spaData.angles[0].sunrise; // Lower time from custom angle
@ -25,7 +25,7 @@ function getTimes(date, lat, lng, elevation = 50, temperature = 15, pressure = 1
const solarNoonSeconds = Math.floor((spaData.solarNoon * 3600) - (solarNoonHours * 3600) - (solarNoonMinutes * 60));
const solarNoonDate = new Date(date);
solarNoonDate.setHours(solarNoonHours, solarNoonMinutes, solarNoonSeconds);
const asrPrayerTime = getAsr(solarNoonDate, lat, lng, standard);
const asrPrayerTime = getAsr(solarNoonDate, lat, lng, tz, standard);
// Step 4: Calculate Qiyam time
const qiyamTime = getQiyam(fajrTime, ishaTime);

View file

@ -16,14 +16,14 @@ const methods = [
{n:'MUIS', f:20, i:18, r:'SG'},
];
function getTimesAll(date, lat, lng, elevation = 50, temperature = 15, pressure = 1013.25, standard = true) {
function getTimesAll(date, lat, lng, tz, elevation = 50, temperature = 15, pressure = 1013.25, standard = true) {
// Step 1: Get the custom angles
const { fajrAngle, ishaAngle } = getAngles(elevation, pressure, temperature);
const methodAngles = methods.map(m => [m.f + 90, m.i + 90]);
// Step 2: Get SPA data with custom angle for Fajr/Isha and other methods
const spaParams = { elevation, temperature, pressure };
const spaData = getSpa(date, lat, lng, spaParams, [fajrAngle + 90, ishaAngle + 90, ...methodAngles.flat()]);
const spaData = getSpa(date, lat, lng, tz, spaParams, [fajrAngle + 90, ishaAngle + 90, ...methodAngles.flat()]);
// Organize prayer times
const fajrTime = spaData.angles[0].sunrise;
@ -39,7 +39,7 @@ function getTimesAll(date, lat, lng, elevation = 50, temperature = 15, pressure
const solarNoonSeconds = Math.floor((spaData.solarNoon * 3600) - (solarNoonHours * 3600) - (solarNoonMinutes * 60));
const solarNoonDate = new Date(date);
solarNoonDate.setHours(solarNoonHours, solarNoonMinutes, solarNoonSeconds);
const asrPrayerTime = getAsr(solarNoonDate, lat, lng, standard);
const asrPrayerTime = getAsr(solarNoonDate, lat, lng, tz, standard);
// Step 4: Calculate Qiyam time
const qiyamTime = getQiyam(fajrTime, ishaTime);

63
index.d.ts vendored Normal file
View file

@ -0,0 +1,63 @@
declare module 'praycalc' {
export function getMoon(date: Date): MoonReturnType;
export function getTimes(date: Date, lat: number, lng: number, elevation?: number, temperature?: number, pressure?: number): TimesReturnType;
export function calcTimes(date: Date, lat: number, lng: number, elevation?: number, temperature?: number, pressure?: number): CalcTimesReturnType;
export function getTimesAll(date: Date, lat: number, lng: number, elevation?: number, temperature?: number, pressure?: number): TimesAllReturnType;
export function calcTimesAll(date: Date, lat: number, lng: number, elevation?: number, temperature?: number, pressure?: number): CalcTimesAllReturnType;
interface MoonReturnType {
fraction: number;
phase: number;
angle: number;
}
interface TimesReturnType {
Qiyam: number;
Fajr: number;
Sunrise: number;
Noon: number;
Dhuhr: number;
Asr: number;
Maghrib: number;
Isha: number;
Angles: number[];
}
interface CalcTimesReturnType {
Qiyam: string;
Fajr: string;
Sunrise: string;
Noon: string;
Dhuhr: string;
Asr: string;
Maghrib: string;
Isha: string;
Angles: number[];
}
interface TimesAllReturnType {
Qiyam: number;
Fajr: number;
Sunrise: number;
Noon: number;
Dhuhr: number;
Asr: number;
Maghrib: number;
Isha: number;
Methods: Record<string, string[]>;
Angles: number[];
}
interface CalcTimesAllReturnType {
Qiyam: string;
Fajr: string;
Sunrise: string;
Noon: string;
Dhuhr: string;
Asr: string;
Maghrib: string;
Isha: string;
Methods: Record<string, string[]>;
Angles: number[];
}
}

12
package-lock.json generated
View file

@ -1,21 +1,21 @@
{
"name": "praycalc",
"version": "1.0.0",
"version": "1.2.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "praycalc",
"version": "1.0.0",
"version": "1.2.2",
"license": "ISC",
"dependencies": {
"nrel-spa": "^1.1.0"
"nrel-spa": "^1.2.2"
}
},
"node_modules/nrel-spa": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/nrel-spa/-/nrel-spa-1.1.0.tgz",
"integrity": "sha512-uoVKBDIj5vvAMEzRr2LSKXo/r9IcadE46CeBSepU47ssByoDZ6QFUsmzTUvg9DAggGbVTTCCEvM29bGUI4YYzA=="
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/nrel-spa/-/nrel-spa-1.2.2.tgz",
"integrity": "sha512-2mycHd7PP0l+pPjPvrT6vr+PRHufCFOxsPcpaIOQ9GwhhfzgyTvSsLKPsqC6ZENNU65yq4PetT5XlWj3CoLjiQ=="
}
}
}

View file

@ -1,6 +1,6 @@
{
"name": "praycalc",
"version": "1.0.0",
"version": "1.2.2",
"description": "Prayer times calculator using nrel-spa and custom formula for Fajr and Isha angles (as well as traditional static angle methods in the All function)",
"main": "index.js",
"scripts": {
@ -13,6 +13,6 @@
"author": "USF",
"license": "ISC",
"dependencies": {
"nrel-spa": "^1.1.0"
"nrel-spa": "^1.2.2"
}
}

34
test-spa.js Normal file
View file

@ -0,0 +1,34 @@
const { getSpa, calcSpa } = require('nrel-spa');
const date = new Date();
console.log(date)
/* NYC - minimum params
const city = "New York"
const lat = 40.7128;
const lng = -74.006;
const tz = -5;
const params = null
const angles = []
*/
// Jakarta - all params
const city = "Jakarta"
const lat = -6.2088
const lng = 106.8456
const tz = 7
const elevation = 18
const temperature = 26.56
const pressure = 1017
const params = {elevation, temperature, pressure}
const angles = [63.435]
// Get results
const get = getSpa(date, lat, lng); // minimal args
const calc = calcSpa(date, lat, lng, tz, params, angles);
// Print results
console.log(`\nTest: ${city} with current Date():\n`)
console.log("getSpa =", get, "\n");
console.log("calcSpa =", calc, "\n");

38
test.js
View file

@ -1,13 +1,31 @@
const { calcTimesAll } = require('./index');
const lat = 40.7128; // Latitude for New York City
const lng = -74.0060; // Longitude for New York City
const elevation = 10; // Average elevation for NYC in meters
const temperature = 15; // Average temperature for NYC in Celsius
const pressure = 1013.25; // Average atmospheric pressure in millibars
const { getTimes, calcTimesAll } = require('./index');
const date = new Date();
const prayerTimes = calcTimesAll(date, lat, lng, elevation, temperature, pressure);
console.log(`NYC Prayer Times for Today:\n\n`);
console.log(prayerTimes);
/* NYC - minimum params
const city = "New York"
const lat = 40.7128;
const lng = -74.006;
const tz = null
const elevation = null
const temperature = null
const pressure = null
*/
// Jakarta - all params
const city = "Jakarta"
const lat = -6.2088
const lng = 106.8456
const tz = 7
const elevation = 18
const temperature = 26.56
const pressure = 1017
// Get results
const get = getTimes(date, lat, lng); // minimal args
const calc = calcTimesAll(date, lat, lng, tz, elevation, temperature, pressure);
// Print results
console.log(`\nTest: ${city} with current Date():\n`)
console.log("getTimes =", get, "\n");
console.log("calcTimesAll =", calc, "\n");