mirror of
https://github.com/acamarata/pray-calc.git
synced 2026-06-30 19:04:26 +00:00
Complete rewrite from plain JavaScript to TypeScript with dual CJS/ESM output via tsup. Removes all legacy .js source files and the old CommonJS-only index. Key changes: - Full TypeScript source in src/ with strict mode and declaration maps - tsup build: dist/index.cjs + dist/index.mjs + dual .d.ts / .d.mts types - 14 traditional fixed-angle methods (UOIF through MUIS) + MSC seasonal method - PCD dynamic algorithm: MSC seasonal base + Earth-Sun distance correction + ecliptic geometry + atmospheric refraction + observer elevation - getTimesAll() batches all 14x2 zenith angles into a single SPA call - getMscFajr() / getMscIsha() expose MSC seasonal reference directly - getAngles() returns the PCD-computed fajrAngle and ishaAngle - High-latitude bounds: angles clipped to [10, 20] above 55N - 106 tests across ESM and CJS (test.mjs + test-cjs.cjs) - CI matrix: Node 20/22/24, typecheck, pack-check - Wiki: 12 reference pages + 6-page research section with global accuracy study, home-territory comparison, observational evidence, and field observation matrix - Moon functions removed (migrated to moon-sighting package) - pnpm-only, Node >=20, sideEffects: false
83 lines
2.5 KiB
Markdown
83 lines
2.5 KiB
Markdown
# Asr Calculation
|
||
|
||
## The Rule
|
||
|
||
Asr is the afternoon prayer. Its start time is defined by shadow length, not by
|
||
a solar depression angle.
|
||
|
||
The standard definition: Asr begins when an object's shadow equals its height
|
||
**plus** the length of its shadow at solar noon.
|
||
|
||
For the Shafi'i, Maliki, and Hanbali schools of law (the majority), the shadow
|
||
multiplier is **1**. For the Hanafi school, the multiplier is **2**.
|
||
|
||
In practice, the difference is typically 30–60 minutes, with Hanafi Asr being later.
|
||
|
||
## The Math
|
||
|
||
Let:
|
||
- φ = observer latitude in radians
|
||
- δ = solar declination in radians at local noon
|
||
- s = shadow factor (1 for Shafi'i, 2 for Hanafi)
|
||
|
||
The Sun's altitude when the shadow multiplier condition is met:
|
||
|
||
```
|
||
A = arccot(s + tan(|φ - δ|))
|
||
= arctan(1 / (s + tan(|φ - δ|)))
|
||
```
|
||
|
||
This altitude corresponds to a specific hour angle H:
|
||
|
||
```
|
||
cos(H) = (sin(A) - sin(φ)sin(δ)) / (cos(φ)cos(δ))
|
||
```
|
||
|
||
Asr time in local fractional hours:
|
||
|
||
```
|
||
asrTime = solarNoon + H / 15 (H in degrees, since 15° = 1 hour)
|
||
```
|
||
|
||
If `cos(H) < -1` or `cos(H) > 1`, the Sun never reaches the required altitude,
|
||
and `getAsr` returns `NaN`. This can happen at extreme latitudes when latitude
|
||
and declination are far apart.
|
||
|
||
## Implementation
|
||
|
||
`getAsr` is a pure math function. It requires:
|
||
|
||
1. `solarNoon` — fractional hours (from the SPA output)
|
||
2. `latitude` — decimal degrees
|
||
3. `declination` — solar declination in degrees (from `solarEphemeris`)
|
||
4. `hanafi` — boolean (default `false`)
|
||
|
||
```typescript
|
||
import { getAsr } from 'pray-calc';
|
||
|
||
const asr = getAsr(
|
||
12.15, // solar noon at ~12:09 local time
|
||
40.7128, // New York latitude
|
||
23.44, // solar declination at summer solstice
|
||
false, // Shafi'i
|
||
);
|
||
```
|
||
|
||
## Why Not Use the SPA for Asr?
|
||
|
||
Some prayer time libraries solve for Asr by running the SPA with the altitude A
|
||
as the zenith input. This requires an extra SPA call or a second zenith slot in
|
||
the batch call.
|
||
|
||
pray-calc computes Asr analytically using the Meeus declination (`solarEphemeris`)
|
||
rather than the SPA's internal declination. This avoids a second SPA call, removes
|
||
any dependency on internal SPA state, and is accurate to well within a minute
|
||
for any realistic use case.
|
||
|
||
The SPA uses a more rigorous ephemeris for declination (accurate to ~0.0003°
|
||
vs. Meeus at ~0.01°). For Asr, the difference in δ of 0.01° translates to less
|
||
than 5 seconds of timing error — completely negligible.
|
||
|
||
---
|
||
|
||
*[Back to Home](Home) | [API Reference](API-Reference) | [Architecture](Architecture)*
|