pray-calc/src/getAsr.ts
Aric Camarata 6f165b79ad ci: fix eslint parser devDeps, typed linting config, prettier formatting
- Add @typescript-eslint/parser and @typescript-eslint/eslint-plugin as
  direct devDependencies (were only transitive, not linked in node_modules)
- Add files pattern and parserOptions.project to eslint.config.mjs so
  ESLint finds and type-checks src/**/*.ts files correctly
- Run prettier --write to fix formatting across all src files
2026-05-31 08:47:17 -04:00

47 lines
1.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Asr prayer time calculation.
*
* Asr begins when the shadow of an object equals (Shafi'i/Maliki/Hanbali)
* or twice (Hanafi) the object's length plus its shadow at solar noon.
* This is a pure spherical trigonometry problem once solar declination
* and solar noon are known.
*/
import { DEG } from "./constants.js";
/**
* Compute Asr time as fractional hours.
*
* @param solarNoon - Solar noon in fractional hours (from getSpa)
* @param latitude - Observer latitude in degrees
* @param declination - Solar declination in degrees (from solarEphemeris)
* @param hanafi - true for Hanafi (shadow factor 2), false for Shafi'i (factor 1)
* @returns Fractional hours, or NaN if the sun never reaches the required altitude
*/
export function getAsr(
solarNoon: number,
latitude: number,
declination: number,
hanafi = false,
): number {
const phi = latitude * DEG;
const delta = declination * DEG;
const shadowFactor = hanafi ? 2 : 1;
// Required solar altitude:
// tan(A) = 1 / (shadowFactor + tan(|φ δ|))
const X = Math.abs(phi - delta);
const tanA = 1 / (shadowFactor + Math.tan(X));
const sinA = tanA / Math.sqrt(1 + tanA * tanA); // sin(atan(tanA))
// Solve the hour-angle equation:
// cos(H0) = (sin(A) sin(φ)sin(δ)) / (cos(φ)cos(δ))
const cosH0 = (sinA - Math.sin(phi) * Math.sin(delta)) / (Math.cos(phi) * Math.cos(delta));
if (cosH0 < -1 || cosH0 > 1) return NaN; // sun never reaches A
// H0 in hours (15°/hr)
const H0h = Math.acos(cosH0) / DEG / 15;
return solarNoon + H0h;
}