From b867162acec21b6370fe56202add1d36498bdc3f Mon Sep 17 00:00:00 2001 From: Ali Camarata Date: Mon, 13 Nov 2023 08:51:34 +0700 Subject: [PATCH] updated for timezone handling and asr calc --- CHANGELOG.md | 16 ++++++++++++ README.md | 36 +++++++++++++++++++++------ calcTimes.js | 4 +-- calcTimesAll.js | 4 +-- getAsr.js | 7 +++--- getTimes.js | 6 ++--- getTimesAll.js | 6 ++--- index.d.ts | 63 +++++++++++++++++++++++++++++++++++++++++++++++ package-lock.json | 12 ++++----- package.json | 4 +-- test-spa.js | 34 +++++++++++++++++++++++++ test.js | 38 ++++++++++++++++++++-------- 12 files changed, 191 insertions(+), 39 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 index.d.ts create mode 100644 test-spa.js diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..11b751e --- /dev/null +++ b/CHANGELOG.md @@ -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) diff --git a/README.md b/README.md index 73f0345..ca8a979 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/calcTimes.js b/calcTimes.js index 023540e..b446e5f 100644 --- a/calcTimes.js +++ b/calcTimes.js @@ -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) diff --git a/calcTimesAll.js b/calcTimesAll.js index ca155f4..9f5a796 100644 --- a/calcTimesAll.js +++ b/calcTimesAll.js @@ -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) diff --git a/getAsr.js b/getAsr.js index d3db1db..4aebc58 100644 --- a/getAsr.js +++ b/getAsr.js @@ -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; diff --git a/getTimes.js b/getTimes.js index e166566..11c302e 100644 --- a/getTimes.js +++ b/getTimes.js @@ -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); diff --git a/getTimesAll.js b/getTimesAll.js index 40f7261..a8e7a22 100644 --- a/getTimesAll.js +++ b/getTimesAll.js @@ -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); diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..ae8f0da --- /dev/null +++ b/index.d.ts @@ -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; + Angles: number[]; + } + + interface CalcTimesAllReturnType { + Qiyam: string; + Fajr: string; + Sunrise: string; + Noon: string; + Dhuhr: string; + Asr: string; + Maghrib: string; + Isha: string; + Methods: Record; + Angles: number[]; + } + } diff --git a/package-lock.json b/package-lock.json index 3e63d6e..cbc121e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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==" } } } diff --git a/package.json b/package.json index 6d795ad..abe73ff 100644 --- a/package.json +++ b/package.json @@ -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" } } diff --git a/test-spa.js b/test-spa.js new file mode 100644 index 0000000..1f72b7d --- /dev/null +++ b/test-spa.js @@ -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"); diff --git a/test.js b/test.js index 83be6f8..396765b 100644 --- a/test.js +++ b/test.js @@ -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");